이번 글에서는 Java 로 간단한 미니 마블 게임을 만든 과정을 소개합니다 !
실행 결과



미니 마블이란?
8칸으로 이루어진 공간에서 총 3바퀴를 먼저 완주하면 이기는 게임입니다.
기본 규칙
- 이동 가능한 거리는 1~3 사이의 값
→ 1~3 외에 다른 값은 올 수 없습니다. - 플레이어의 이동이 끝난 곳에 상대 플레이어가 있다면 상대 플레이어의 위치는 0으로 초기화됩니다.
제가 생각한 전체적인 흐름을 플로우차트로 그려보았습니다
전체적인 흐름
① 메뉴 보여주기
② 사용자로부터 메뉴 입력 받기
- 게임 시작
- 게임 룰 출력
- 종료
② - ① 게임시작
- 이동거리 입력 받기
- 입력 값만큼 플레이어 이동
- 3번 완주가 끝나지 않았다면 턴 교체하여 위 동작 실행
- 3번 완주가 끝났다면 승리 플레이어 출력 후 메뉴로 이동

큰 흐름별로 세부적인 내용도 확인 해보겠습니다
세부적인 내용
① 메뉴 보여주기

이번 게임에서는 클래스를 이용하여
메뉴 , 게임룰을 보여주는 Show 클래스와
게임을 실행하기 위한 GameSet 클래스를 만들어 사용하였습니다
입력 값에 맞게 객체를 생성만 해주면 되어서 넘어가겠습니다 !


설명
- 입력값을 받기 위한 Scanner 라이브러리 이용 (1~3 사이의 수)
- 입력값이 3이 되기 전 까지는 무한루프
- Show 객체 game 생성 => 생성자 호출 (메뉴 소개)
- 스위치 문을 이용하여 입력 값에 맞춰 각 case로 이동
- case 1: GameSet 객체 생성 => 생성자 호출 (게임 시작)
- case 2: game.showRule 호출 => 게임 규칙 출력
- case 3: 무한루프 isGame = true / 종료
② - ① 게임시작 (GameSet 메인 메서드)

그리려고 하니 꽤 많은 조건들을 거쳐서 나가게 되네요 ㅎㅎ...
어떻게 코드로 작성했는지 한 번 확인해보죠 !

설명
- 플레이어 각각의 맵 , 플레이어 , Lap , turn 변수 초기화
- 무한루프
- (1) 두 플레이어 중에 3바퀴 완주를 하였는가
- (2) showMap 메서드 호출 => 플레이어들의 위치와 lap 값을 보여줌
- (3) 이동할 거리 값 1~3 사이의 숫자를 inputValue 메서드로 입력을 받아 해당 차례 플레이어 변수에 값을 넣어줌
- (4) checkLap 메서드를 통해 해당 차례 플레이어 변수의 값이 8이상이라면 8로 나눠 몫을 가져와 해당 플레이어의
laps 에 더해주고 , 8로 나눈 나머지를 플레이어 변수로 가지게 된다 . - (5) move 메서드에서 플레이어 변수의 값만큼 자리를 이동하며 , 이동 후 상대 플레이어를 잡게 되면 true를 반환하며
if문 실행이 되며 상대 플레이어의 변수값이 0으로 초기화된다 - (6) turn을 계속해서 바꾸며 진행한다. ( 1 - 0 = 1 , 1 -1 = 0 => 0, 1 반복)
무한 루프를 돌며 진행되는 게임 과정에 대해 좀 더 자세히 보겠습니다
(*) 변수 초기화

설명
- index = 0 은 1 플레이어가 가지고 1 은 2 플레이어가 가지는 변수이다.
- 위에서 순서대로
- 각각 8칸 짜리의 맵
- 플레이어 1 , 2
- Lap 1 , 2
- turn = 0 이므로 1 player 부터 시작된다
(1) 두 플레이어 중에 3바퀴 완주를 하였는가



설명
- 배열로 만들어진 플레이어 각각의 turn에 맞는 index값을 자기의 lap으로 갖게 함
- lap[0] 이나 lap[1] 의 값이 4라는 건 3바퀴 완주가 끝났다는 얘기
- boolean 변수로 true 혹은 false를 반환해주며
- main 메서드에서 if문으로 탈출 혹은 반복한다 .
추가
- 파라미터로 laps (int 형 배열) 을 받아오는거라 int [] laps 로 받아와 index로 접근하였다
(2) showMap 메서드 호출



설명
- 1번째 반복문에서는 index 값 0부터 시작하며 map의 length = 2 까지 총 2번 반복하며 각각 플레이어의 map 에 접근함
- 0 은 player 1 , 1 은 player 2 임을 알려주는 index 이므로 index+1 을 함으로써 " player 1 : " / " player 2 : " 를 출력한다
- 출력후 player 의 map에 있는 총 길이 8칸 모두 반복문을 통해 m으로 하나씩 꺼내며 m을 이어 출력한다
- 출력이 끝난 후에는 해당 차례 플레이어에게 이동할 거리를 입력 받아야 하는 문장을 출력한다.
추가
- 파라미터로 플레이어들의 map , laps 의 값을 배열로 가져와서 for문을 돌리며 사용하는 index를 사용하여 접근함
(3) inputValue 메서드로 입력 받기



설명
- 입력을 받는데 1 ~ 3 사이의 숫자라면 입력 받은 값을 return 후 해당 차례 플레이어 값에 더해준다.
- 아니라면 반복해서 다시 입력 받기

설명
- 해당 차례 플레이어의 값이 8 이상이라면 1을 return 해주고 아니라면 0을 리턴해준다
- 리턴받은 값은 해당 플레이어 lap에 저장된다
- 플레이어 값이 8 미만이라면 8로 아무리 나눈 나머지로 바꿔도 같은 값이기에
8이상의 값을 가지고 있으면 lap += 1 , player -= 8 이 된다
(4) move



설명
- 상대 플레이어를 잡았는지 안 잡았는지 체크하는 boolean 변수를 만들어준다
- 해당 차례 플레이어의 맵을 모두 0으로 초기화를 시켜준다
- 해당 차례 플레이어의 값의 위치(index)에 해당 turn에 +1 한 값을 넣어준다
( turn 0 일땐 p1 -> 1로 위치표시 , turn 1일땐 p2 -> 2 로 위치표시 ) - 상대 플레이어의 맵에 현재 플레이어 값 위치에 0 이 아닌 다른 숫자가 있다면 그건 같은자리에 있다는 얘기가 된다.
if문을 통해 상대 플레이어 맵의 모든 값을 0으로 만들며 , catchplayer를 return한다 .
(이부분은 쓰면서 알게 되었는데 굳이 메인 메서드에서 if문을 쓰며 조건 확인 후 플레이어 값을 0으로 만들고 있었다
이건 그냥 player를 배열 전체로 받아 메서드 내부에서 해결해도 될듯하다) - true인 경우 상대 플레이어 값 자체도 0으로 만들어주며 turn 을 교체한다
추가
- 파라미터로 플레이어들의 map 값을 배열로 가져와서 for문을 돌리며 사용하는 index와 turn 을 사용하여 접근함
(5) 게임 종료 !


설명
- isEnd 메서드가 참이 되면서 이 무한 루프를 탈출하게 된다
- 탈출 후 마지막으로 끝난 turn의 값을 비교하면서 승리한 플레이어를 출력하면서 다시 메뉴 선택창으로 돌아가게 된다

하면서 알게된 점
- 배열을 사용하지 않고 각각의 변수로 사용을 했더니 5줄이면 끝날 코드가 15줄 이랬는데 배열로 변경하면서 코드 간결해졌음
- 이전 코드 Call by Value : 메서드 내에서 값 변경 힘들고 리턴값이 있어야 했다
- 수정 후 코드 Call by reference : 메서드 내에서 배열의 주소를 직접 참조하여 수정해서 별도의 리턴 없이도 변경이 가능했음
- 배열을 사용하면서 turn 이라는 변수의 응집도? 같은 것이 엄청 커졌던 걸 느꼈다
- 클래스를 사용하여 목적에 맞게 분리시킨 것 같아 보기가 편해졌음
- 리팩토링을 하면 할 수록 분명 코드는 점점 전 보다 좋아지고 있음 다만 아직 한 번에는 이렇게 작성이 안 되고 구현이 끝나고 나서 천천히 수정하면서나 가능하다 ... 꾸준함이 답인 듯 하다
생각보다 글로 적으려니 많이 길었던 내용이었고 ,
또 적다보니까 아쉬운 코드들도 발견되어서 나름 의미있는 블로그 쓰기였습니다
아자아자 화이팅 !