코린이의 개발 일지

[자바] 콘솔로 간단한 보드게임 만들기 - 설계편 본문

프로젝트/콘솔 프로그램

[자바] 콘솔로 간단한 보드게임 만들기 - 설계편

폴라민 2022. 6. 13. 02:11
반응형

학교 소프트웨어 공학 수업에서 중간고사 대체 텀 프로젝트가 나왔습니다.

 

중간고산데 왜 이제 블로그를 올리느냐구요?

최근에 겨우 다했거든요...ㅋㅋㅋㅋㅋ 

벼락치기 국룰이잖아요.

 

농담이구요. 이게 설계 과목이라 맨 처음 설계부터 구현까지 하느라 시간이 너무 오래걸렸습니다. 

저의 삽질의 시간을 공유해 보고자 합니다.

 

우선 설계부터 시작을 했습니다. 사정상 자바를 사용해야만 했어서 (이유는 후에 구현 편에서 말씀드리겠습니다.)

자바로 구현할 것을 염두해 두고 설계를 했습니다.

 

설계는 이번 과제에서 처음 해보는데 생각보다 정말 만만치 않았습니다. 저는 솔직히 구현보다 시간 오래걸렸던 거 같아요.

근데 수업시간에 들은 바로는 그게 정상이라고 하더군요? 

설계를 제대로 했다면 구현은 금방이라고 합니다. 근데 이번 과제를 해보니 정말 맞는 말이에요. 구현 하다가 하나 어긋나서 설계부터 다시해야한다면 정말.... 하지만 이런 경우가 종종 일어나기 때문에 Waterfall 방식보다 agile방식을 업계에서 선호하는 것이겠죠?

 

아무튼 이번에는 팀프로젝트가 아닌 개인 프로젝트였어서 제 편의대로 설계하고 구현하다가 다시 설계 수정하고 구현하고 이렇게 했지만 나름 배워가는 게 많은 시간이었습니다.

 

과제는 보드게임을 만드는 것이었는데, 플레이 규칙부터 게임판 모양까지 자세하게 제시 되어있고 그거를 다 준수하면서 설계 후 구현해야 했습니다.

간단한 규칙을 얘기하자면 게임판이 있고 게임을 시작하면 유저는 플레이어 수를 입력합니다.

그럼 플레이어 수만큼 플레이어가 생성되고 맵이 출력됩니다.

그리고 각각의 플레이어는 돌아가면서 주사위를 굴리고 그 수만큼 칸을 이동합니다.

 

게임은 한명의 플레이어를 제외한 나머지 모든 플레이어가 도착지에 도착하면 종료되고, 플레이어의 총점을 계산해 최종 우승자를 가립니다. 더 많은 규칙이 있지만 전체적인 틀은 이렇습니다.

 

우선 설계한 거 부터 보시죠.

설계 처음해보는 사람의 설계이니 부족한 점은 감안하고 봐주시면 감사하겠습니다.

 

1. 요구 정의 및 분석 산출물

- UseCase Diagram

 

 

우선 요구 분석을 하고 그에 따라 usecase 다이어그램을 만들어 봤습니다. 우선 유저가 입력한 플레이어 수만큼 플레이어를 생성해야 하니, Create Player라는 Usecase를 만들어 보았고, 각각의 플레이어가 생성되면 플레이어마다 게임에서 각 턴을 진행하니 GamePlay라는 usecase도 만들었습니다. 그리고 플레이어가 이동할 때마다 게임판을 출력해주기 위해 print map이라는 Usecase도 만들었습니다. 여기에서는 대략적인 감만 잡는 느낌으로 했습니다. 애초에 아직 이단계는 요구분석을 하는 단계라서 이렇게 마무리를 지었습니다.

 

- UseCase 명세

Usecase 명세

 

Use Case UC1 : print map

1.     마지막으로 로드된 지도의 데이터 가져온다.

2.     지도의 데이터를 바탕으로 화면에 지도 표시.

    A.      플레이어의 현재 위치도 같이 표시

3.     플레이어가 가진 카드의 개수 표시.

 

Use Case UC2: create player

1.     플레이어 입력받기

2.     각각의 플레이어 데이터 초기화

 

Use Case UC3 : Game play

Main success scenario

1.     게임 시작

2.     플레이어 생성

3.     지도 출력

4.     첫번째 플레이어의 쉴지 주사위를 굴릴지 결정

         A.      쉬기로 결정한 경우 다리 카드 한장을 시스템으로 반납

         B.      주사위를 굴리는 경우 게임 시스템이 랜덤으로 주사위를 굴려서 1-6까지의 값을 제시

                            i.          플레이어는 주사위 값에서 다리 카드의 개수를 만큼 이동 가능하다. ( 음수인 경우 0 이동)

                           ii.          플레이어는 계산된 만큼 U,D,L,R 혹은 u,d,l,r 조합을 한줄로 입력

                                        1.      주사위 지도에 합당하면 플레이어의 말은 지시대로 진행

                                                 A.      현재 위치에 도구 카드가 있을 경우 도구 카드 획득

                                                 B.      다리를 건널 경우 다리 카드 한장 받는다.

                                        2.      이동불가 하거나 주사위 값과 일치하지 않으면 6-B - i 돌아감.

                          iii.          지도 갱신, 화면에 표시.

5.     모든 플레이어가 4 실행

6.     명의 플레이어만 보드에 남을 까지 4,5 반복

7.     명의 플레이어만 보드에 남으면 게임이 끝나고 플레이어는 이상 턴을 진행 없다.

8.     점수 계산 가장 많은 점수를 얻은 플레이어가 승리.

9.     프로그램 종료.

 

 

이 UseCase 명세는 각각의 usecase를 자세히 정리하며 시나리오도 적어봤으니 궁금하신 분들은 읽어보시면 좋을 듯 합니다.

 

 

- Domain model

 

Domain model도 작성해봤습니다. 저는 우선 4개의 클래스를 구성해 보았고 각각의 클래스에서 필요한 key concept, 그리고 각각의 클래스들 사이의 관계를 표현했습니다.

 

MainGame에서는 전체 게임을 진행하고 GameManaer 통해 얻은 데이터를 출력합니다.

GameManager 에서는 Map에서 map 데이터를 가져오고 Player 객체를 플레이어 수만큼 생성하고 저장해둡니다.

Map에서는 map 데이터를 읽어와서 저장해두고, Player에서는 각각의 플레이어 데이터를 저장해둡니다.

 

 

그리고 마지막으로 게임 시나리오 정리를 위해 system sequence diagram 을 작성해봤습니다.

 

- System Sequence Diagram

 

 

이 시스템 시퀀스 다이어그램은 user와 시스템 사이의 관계만 표현한 것인데, 어떤 동작들이 오고 가는지 한눈에 살펴볼 수 있다는 장점이 있습니다.

 

이번 프로젝트는 그렇게 복잡하지도 않고 많은 기능이 필요한 것도 아니라서 그냥 위에 Usecase에서 다룬 시나리오를 여기에 옮겨놓은 작업입니다. 

 

자 그럼 요구 분석은 끝났고 이제 설계를 해봅시다.

 

 

2. 설계 산출물

- Sequence Diagram

 

위에서 System sequence diagram 만들어 놨으니 바로 이어서 Sequence Diagram을 만들었습니다.

 

 

앞에 것 보다 훨씬 복잡하죠? 사실 크게 어려울 건 없어요. 그냥 시스템 내부에서 각각의 클래스들 사이에 무슨 동작이 일어났는지 적어줬습니다.

 

간단히 위의 시퀀스 다이어그램을 설명해 보자면 우선 User 플레이어를 입력하면 MainGame에서 GameManager 호출합니다. GameManager는 MainGame에서 명령을 받아 플레이어 만큼 플레이어를 생성하고 저장합니다. GameManager Map 호출하고 Map 지도 파일을 읽어와 저장을 하고 GameManager map 정보를 가져와 2차원 배열 게임 보드로 만든 MainGame 넘겨줍니다. MainGame 보드를 읽은 사용자에게 출력해줍니다.

 

게임이 시작 되면 사용자에게 주사위를 굴릴지 말지 입력을 받습니다.

 

주사위를 굴릴 경우, MainGame 사용자에게 주사위 숫자를 제시하고 길을 입력받습니다. MainGame 입력 받은 길을 GameManager 보내 길이 합당한지 체크하고 (그 길로 갈 수 있는지, 벽은 없는지, 등을 체크) 합당하지 않을 경우 다시 입력받도록 하고 합당할 경우 GameManager playerMove메소드를 실행시킵니다.

Player가 성공적으로 칸을 이동하면 GameManager 각각의 player정보를 업데이트합니다. 그에 맞춰 map데이터도 업데이트 하고 Main Game 사용자에게 업데이트 된 맵을 출력합니다.

 

주사위를 굴리지 않을 경우 MainGame GameManager 다시 호출하고, GameManager 해당 사용자의 다리카드를 1 감소시킵니다. 그에 맞춰 map데이터도 업데이트하고 MainGame 맵을 출력합니다.

 

게임보드에 플레이어가 한명만 남을 경우 게임을 종료하고 MainGame GameManager 호출하여 플레이어의 점수를 얻습니다. GameManager 플레이어의 점수를 계산해 보내주고 MainGame 우승자를 출력합니다.

 

 

뭔가 앞서 설명한 것 보다 기능이 많죠? 

 

게임판이 이렇게 생겼습니다. 저기 칸 중간에 보이는 === 가 다리이고, S,P,H는 각각 아이템이에요.

다리를 건너면 다리카드를 하나 획득하고 다음에 주사위 굴렸을 때, 만약 4가 나왔다. 그러면 다리카드 개수를 제외한 숫자만큼 칸을 이동할 수 있어요. 만약 주사위 숫자가 4고 다리카드 1개있으면 3칸만 이동할 수 있는 거죠.

S,P,H는 각각 아이템인데 S가 있는 곳을 지나면 3점, P가 있는 곳을 지나면 1점, H가 있는 곳을 지나면 2점을 획득합니다.

 

플레이어가 가장 먼저 도착지점에 도착할 경우 7점, 두번째는 3점, 세번째는 1점을 획득합니다.

 

그리고 게임이 종료되면 각각의 플레이어 점수를 계산한 후 우승자 출력!!

 

이런식으로 게임이 진행되요.

 

이걸 저 위의 설계로 옮겨 놓았다고 보시면 됩니다.

 

이제 정말 마지막 설계를 봅시다.

 

- Design Class Diagram

 

솔직히 저는 프로그램 설계하면 얘만 알고 있었거든요. 이번에 수업들으면서 참 다양한 다이어그램을 알게 되었습니다.

 

 

이거는 이제 진짜 구현 직전에 클래스 다 정의하는 느낌이에요. 각각의 클래스 이름, 그 클래스에서 사용할 변수, 메소드, 메소드의 리턴 타입, 매개변수 타입 모두 정합니다.

 

사실 이단계가 있었어서 구현이 빠르게 되지 않았나 생각이 듭니다.

 

이 클래스 다이어그램 설계할 때 신경 쓴 부분이 있다면 Interface와 내부 시스템 구분을 위해 사용자에게 직접 입력받고 출력해주는 UI부분은 MainGame클래스에서만 하고 게임 내부 동작은 GameManager단계에서 이루어지도록 만들었습니다.

 

이 부분이 특별히 신경 쓴 부분이고 나머지는 그냥 구현할 때 필요할 거 같은 변수, 메소드 정의해 줬습니다. 이쯤되니까 그동안의 설계 과정에서 정해놓은 것들이 많아서 크게 정할 부분은 없더라구요.

 

 

이렇게 해서 프로그램 설계가 끝났습니다. 이제 이걸 구현해야겠죠? ㅎㅎ

 

저는 자바 언어를 활용해서 구현했는데, 이 설계 내용 바탕으로 c++로도 금방 구현 가능할 거 같긴 하네요.

그럼 다음 구현편으로 돌아오도록 하겠습니다.

반응형
Comments