- Gist가 생소하다.
- 문제 자체를 보니 정신이 나갈 것 같다. 으아아악
- 최상위 디렉토리의
Map.txt
파일을 읽어와 File객체MAP_FILE
생성 - 이를 static 상수로 한다.
- 소스파일의 텍스트를 스테이지단위로 분리하여 List에 나눠 저장하도록 하는 메서드
splitStageStr
생성- 스캐너의
.useDelimiter("=+")
을 활용함 - 나눠진 문자열들의 양 끝의 공백을
.trim()
메서드를 이용하여 제거 -> 마지막의 구분자가 제거되고 남은 개행문자도 제거됨.
- 스캐너의
각 Stage를 정의한 Stage 클래스 정의
- 멤버
- String
stageName
: 스테이지명 - Integer[][]
stageMap
: 맵
- String
- 어떤 좌표를 정의한 Point 클래스 정의
- 멤버
- int x;
- int y;
- 메서드
- equals : 같은 x,y 좌표면 true, 다르면 false 반환
- hashCode : x,y 좌표를 기준으로 hashCode를 반환하도록 함
- toString : (x, y)의 형태로 좌표를 문자열로 반환
- revision 1.03에서 만들어진
splitStageStr
을 통해 분리된, 스테이지 단위의 문자열을 읽고, 이를 통해 스테이지를 만드는 용도로 정의한 클래스 - 멤버
- String
stageName
: 만들고자 하는 stage의 이름 - List<Sring>
stageMapSrc
: 스테이지 맵 문자열을 라인단위로 쪼갬
- String
- 생성자
- 스테이지 문자열을 읽고, 첫번째 줄은
stageName
, 나머지 줄은stageMapSrc
에 라인단위로 저장
- 스테이지 문자열을 읽고, 첫번째 줄은
- 구현해야할 것
- 스테이지 문자열들을 분석하여,
Stage
를 만드는 것
- 스테이지 문자열들을 분석하여,
- 멤버
stageMapSrc
를 읽어, 각 라인 문자열의 길이들의 최댓값을 반환
- 멤버
stageMapSrc
를 읽어 size()값에 1을 더한 값이 맵의 세로길이- 맵의 마지막 줄에 스테이지 구분값을 채워야함. 따라서 한 줄이 더 필요
calHeight
로calWidth
로 세로, 가로를 구한 뒤, 이를 각각 열, 행의 갯수로 한 Integer[][] 이차원 배열 생성- 초기화를 해주지 않았기 때문에 모든 값은 어떤
Integer
객체도 참조하지 않고 있다. - 이 이차원 배열은 Stage의 Map으로 사용될 것이다.
- 문자를 인자로, 스테이지 맵의 오브젝트 값으로 파싱하는 메서드 parseMapObject(char ch) 정의
- 문자를 인자로 이를 Map의 오브젝트에 대응하는 Integer로 반환
- Map 오브젝트 값이 헷갈릴 수 있으므로, 이를 static 상수화함.
WALL_CODE
== 0,HALL_CODE
== 1,BALL_CODE
== 2,PLAYER_CODE
== 3STAGE_DELIM_CODE
==4;
build()
메서드 : Stage를 생성하는 메서드- 멤버변수
stageName
을 읽어오고, stageMap을 만들어 이를 토대로 Stage를 생성한다.
- 멤버변수
makeStageMap()
메서드 : stageMap을 생성하는 메서드makeEmptyStageMap()
을 통해 빈 StageMap을 생성하고 fill StageMap을 생성한다.
fillMapObject(Integer[][] stageMap, int rowNumber)
메서드 : 행단위로 행에 다응하는stageMapSrc
의 인덱스의 라인을 읽어와, 각 라인을 문자단위로 파싱하고 StageMap을 채운다.
- 기존 StageBuilder에서 정의되었던 static 상수였으나, 범용성을 위해 Stage의 static 상수로 함.
getMapSymbol(Integer mapObjectCode)
: 오브젝트 코드(숫자)를 인자로 문자로 형식화한다.
- stageMap의 각 인덱스를 읽고 그 값을
getMapSymbol
메서드를 통해 각각 형식화하여, stageMap 전체를 문자 형식화한다. - 형식화된 문자를 반환한다.
getNmbOf(Integer mapObjectCode)
: 지정 오브젝트 코드(숫자)에 대응하는 오브젝트의 갯수를 반환getNmbOfBall()
: 공의 갯수 반환getNmbOfHall()
: 구멍의 갯수 반환
getWidth()
: 맵의 가로폭getHeight()
: 맵의 세로폭
getStageName()
: 스테이지명 반환
getPointOfPlayer()
: 플레이어 위치Point
반환isPlayer(Integer mapObjectCode)
: 지정
- Main -
main
메서드 : Prompt 객체 생성, run() 메서드 호출 - Prompt : 실행 내용, 현재 구체적으로 실행 내용구현은 안 됨
- List
stages
: 로딩된 Stage들의 리스트 - List
initStages()
: 파일을 읽어와,stages
를 초기화
- 작업상황
printStage(Stage stage)
: 지정 스테이지의 세부사항을 출력- 스테이지명
- 스테이지맵 화면 출력
- 가로크기, 세로크기
- 구멍의 수, 공의 수
- 플레이어 위치
run()
:stages
의 모든 stage에 대하여printStage(Stage stage)
수행
- 동작
- Main 클래스 실행시 run() 메서드를 호출하여, 스테이지의 모든 세부사항을 출력하도록함
- 결론 : 1단계 완료
- 작업상황
stageMap
을originalMap
과currentMap
두가지로 나눔originalMap
은 Stage 생성시점의 원본 맵currentMap
은 현재 맵. 플레이어의 조작에 따라 currentMap이 변화하도록 할 것이다.
reset()
:originalMap
을 복제하여currentMap
을 초기화함.- 깊은 복사를 위하여 내부 MapObject Code 인 Integer 값들을 새로 생성했다.
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 모든 stage의 세부사항을 출력함.
- 작업상황
- Stage 맵에 존재하는 모든 오브젝트를 Integer로 관리하다보니 불편함을 느껴서, 모든 맵 오브젝트를 Integer 대신, MapObject 인터페이스의 구현체로 객체화했다.
- 이에 따라 기존에 Integer로 맵의 오브젝트를 다루던 클래스들을 전면적으로 개편하지 않을 수 없었고 이번 커밋은 커밋 단위가 매우 커져버렸다.
- 공백을
Space
로 추가 정의했다. - MapObject 인터페이스는
getSymbol()
메서드를 추상메서드로 하였고, 이를 구현해야 인스턴스를 생성할 수 있다. - MapObject 인터페이스는 static 메서드 getInstance(char symbol)를 통해, 문자를 통하여 symbol에 대응하는 구현체 인스턴스를 반환한다.
- StageBuilder 클래스의 parseMapObject 클래스는 MapObject의 getInstace() 메서드가 그 역할을 수행하도록 하고, 제거했다.
- 공백을
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 모든 stage의 세부사항을 출력함.
-
작업상황
- 지정 인덱스에 위치한 MapObject를 반환하는 메서드
getMapObject
를 정의
- 지정 인덱스에 위치한 MapObject를 반환하는 메서드
-
동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 모든 stage의 세부사항을 출력함.
- 작업상황
- 지정 Point에 대응하는 인덱스에 위치한 MapObject를 반환하는 메서드
getMapObject
를 정의.
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 모든 stage의 세부사항을 출력함.
1.작업상황
- Prompt 클래스의
run()
메서드 호출 시, Stage2의 스테이지명을 출력하고, 현재 상태를 출력하도록 함.- 기존의
printStage()
메서드 제거 printStageName
: 스테이지명 출력printCurrentStatus
: 스테이지의 현재 상태를 출력(맵, 가로크기, 세로크기, 구멍수, 공수, 플레이어 위치)
- 기존의
- 동작
- 실행 시 Stage2의 스테이지명이 출력되고, 현재 스테이지 상태를 출력하면서 종료된다.
1.작업상황
- Point 클래스에서
getEastPoint()
,getSouthPoint()
,getWestPoint()
,getNorthPoint()
메서드 정의- 각각 Point 기준 동쪽, 남쪽, 서쪽, 북쪽 좌표를 반환함
- Prompt 클래스의
printCurrentStatus
메서드가, 플레이어 기준 동남서북의 좌표를 출력하도록 함.
- 동작
- 실행 시 Stage2의 스테이지명이 출력되고, 현재 스테이지 상태를 출력하면서 종료된다.
- 추가내용 : 플레이어의 동남서북 좌표도 출력
- 작업상황
getMapObject(Point p)
메서드는getMapObject(int i, int j)
메서드를 참조하는데, 이때 i,j에 각각 y, 좌표를 넘겨야했던 것을 x, y 좌표로 넘기는 문제가 있었음. 이를 정정함.README.md
에서 2.07 revision의 오타 수정(동서남푹-> 동서남북)
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 Stage의 스테이지명이 출력되고, 현재 스테이지 상태를 출력하면서 종료된다.
- 작업상황
isSpace(MapObject mo)
메서드 : 지정 MapObject가 빈 공간인지 여부를 반환
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 Stage의 스테이지명이 출력되고, 현재 스테이지 상태를 출력하면서 종료된다.
- 작업상황
isMovable()
: 움직일 수 있는 지 여부를 반환- 구현체인 Wall, Hall, Ball, Player, Space, StageDelim 에서 이를 구현하도록 함ㅁ.
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 Stage의 스테이지명이 출력되고, 현재 스테이지 상태를 출력하면서 종료된다.
- 작업상황
getPointOfPlayer()
메서드의 심각한 오류 수정- : 행-열을 y-x로 바꿔야했는데 x-y로 해서 Point를 생성했었음. 여태까지 출력했던 플레이어 위치는 x,y가 뒤바뀐 것이였다!
// 플레이어의 좌표 반환 public Point getPointOfPlayer() { for (int i=0; i<currentMap.length; i++) { for (int j=0; j<currentMap[i].length; j++) { MapObject mapObject = currentMap[i][j]; if (isPlayer(mapObject)) return new Point(j,i); // i,j 순으로 작성해버렸는데 j,i였다. } } return null; }
- 동작
- 실행시 콘솔에 보이는 내용은 이전과 달라졌을 것임. 플레이어의 x,y좌표가 바뀌었을 것이다. (정정)
- 작업상황
exchange(Point p1, Point p2)
: p1과 p2에 위치한 MapObject를 자리바꿈한다.- 두 MapObject 어느 한쪽이라도
isMovable()
메서드가 false를 반환하면 이동할 수 없다.
- 두 MapObject 어느 한쪽이라도
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 Stage의 스테이지명이 출력되고, 현재 스테이지 상태를 출력하면서 종료된다.
- 작업상황
- 플레이어를 동쪽,남쪽,서쪽,북쪽으로 이동시키는 메서드
movePlayerToEast
,movePlayerToSouth
,movePlayerToWest
,movePlayerToNorth
생성\ - Prompt의
run()
메서드에서, 위의 메서드를 한번씩 호출하고 그 결과를 맵의 상태를 매번 출력하게 함.
- 플레이어를 동쪽,남쪽,서쪽,북쪽으로 이동시키는 메서드
- 동작
- 실행시, 스테이지명이 뜨고 플레이어의 현재 상태가 출력된다.
- 동쪽, 남쪽, 서쪽, 북쪽 순서대로 플레이어가 이동을 시도하고, 이동할 때마다 맵 상태가 출력된다.
- 작업상황
- 스테이지의 맵을 출력하는 메서드를 Stage에서 정의함.
- Prompt에서
getMapString()
메서드를 이용해 출력했었으나, 이 메서드가 추가되어서 더 이상 사용할 필요가 없어져, printStageMap() 메서드로 대체 getMapString()
메서드의 접근제어자를 private로 변경
- 동작
- 실행시 콘솔에 보이는 내용은 이전 revision과 별 차이 없음. 실행 시 Stage의 스테이지명이 출력되고, 동쪽, 남쪽, 서쪽, 북쪽 순서대로 플레이어가 이동을 시도한 뒤, 이동할 때마다 맵 상태가 출력된다.
- 작업상황
- 스테이지의 이름을 출력하는 printStageName() 메서드는 더 이상 사용하지 않음.
- 스테이지의 상태를 출력하는 메서드
printCurrentStatus()
메서드는 더 이상 사용하지 않음. 제거. - 이동하였을 때 맵이 어떻게 변했는지만 출력하도록 함.
- 동작
- 실행 시 스테이지 명이 바로 뜨고, 맵이 출력된다.
- 맵이 출력되고 동, 남, 서, 북으로 각각 한번씩 이동을 시도한다.
- 이동 시도 이후 맵의 변화를 출력한다.
- 작업상황
exchange(Point p1, Point p2)
메서드는 두 좌표의 객체 교환 시도 및 true, false 반환만 하도록 함.movePlayerTo~()
메서드는exchange~
메서드에서 성공, 실패 여부를 화면에 출력하도록 함.movePlayerTo~()
메서드는 플레이어의 이동 시도 결과 맵의 상태를 출력하는 역할도 하도록 함.- 이에 따라, Prompt에서 별도로 이동 후
printStageMap
메서드를 호출할 필요가 없어짐.
- 동작
- 실행 시 스테이지 명이 바로 뜨고, 맵이 출력된다.
- 맵이 출력되고 동, 남, 서, 북으로 각각 한번씩 이동을 시도한다.
- 이동 시도 이후 맵의 변화를 출력한다.
-
작업상황
- Prompt의
run()
메서드의 메서드명을execute
로 변경
- Prompt의
-
동작 (변경 없음)
- 실행 시 스테이지 명이 바로 뜨고, 맵이 출력된다.
- 맵이 출력되고 동, 남, 서, 북으로 각각 한번씩 이동을 시도한다.
- 이동 시도 이후 맵의 변화를 출력한다.
- 작업상황
- 멤버변수
isPlaying
: 초기값은true
, 종료 명령이 들어왔을 때false
로 변한다. 무한 반복문을 종료하기위한 용도로 사용. initCommandMap(Stage stage)
: stage를 기반으로 하여, 수행할 작업들을 모아둔Map<String, Runnable>
을 생성하는 메서드- key값 : 으로 W,A,S,D,Q와 같은 입력값
- value값 : W,A,S, D에 대해서는 stage의 플레이어 이동을 수행하는 Runnable을 저장, Q에 대해서는 현재 Prompt의
isRunnable
을false
로 변경하도록 함.
execute
메서드- commandMap 생성 :
initCommandMap
메서드를 통해stage
의 commandMap 생성 - Queue에 명령어 D,S,A,W,Q,S를 순차적으로 삽입
- while문에서, queue에서 poll한 값들로 commandQueue에서 value인 Runnable을 찾도록 한다.
- 각각 Runnable의 작업을 수행하도록 한다.
- commandMap 생성 :
- 멤버변수
- 동작
- 실행 시 스테이지 명이 바로 뜨고, 맵이 출력된다.
- stage의 command맵이 생성된다.
- 맵이 출력되고 D, S, A, F, Q, S 문자열을 Queue에 삽입한다.
- 반복문을 통해 queue의 작업이 순차적으로 출력된다.
- while문 도중에 Q 명령에 의해
isPlaying
이 false가 되고 반복문을 탈출하여 프로그램이 종료된다.
- while문 도중에 Q 명령에 의해
- 작업상황
- static 상수로
PROMPT
를 생성함. 이 문자는"SOKOBAN > "
이 저장되어 있다. inputCommandQueue(Scanner sc)
메서드 : 사용자로부터 라인단위로 명령을 입력받고 이를 Queue으로 반환한다.- 사용자로부터 라인단위로 입력받은 문자열을 한자 한자 쪼개서, List화 한뒤 이를 기반으로
Queue
를 생성함.
- 사용자로부터 라인단위로 입력받은 문자열을 한자 한자 쪼개서, List화 한뒤 이를 기반으로
execute
메서드- 다른 과정은 동일하고, 사용자 입력을 받아
Queue<String>
를 생성하도록 함. - 사용자 입력시 지정된 명령이 존재하지 않을 경우, 명령 수행을 시행하지 않고 다음 명령을 수행하도록 함.
- 다른 과정은 동일하고, 사용자 입력을 받아
- Main 클래스
- 프로그램이 종료되면 "bye~" 를 출력하도록 함.
- static 상수로
- 동작
- 스테이지 명, 초기 맵상태가 출력됨
- 사용자 입력을 받음.
- 사용자 입력을 순차적으로 수행하고 모든 명령이 수행되거나, Q명령이 들어오면 종료됨.
- 작업상황
runCommandQueue(Stage stage, Queue<String> commandQueue)
: 지정 stage에 대하여 commandQueue의 작업을 순차적으로 수행함.initCommandMap(Stage stage)
메서드를 호출하여 자체적으로 stage에 대한commandMap
을 생성함.
execute
메서드에서 runCommandQueue 메서드가 분리되어execute
메서드의 길이가 상당히 줄어듬.
- 동작
- 스테이지 명, 초기 맵상태가 출력됨
- 사용자 입력을 받음.
- 사용자 입력을 순차적으로 수행하고 모든 명령이 수행되거나, Q명령이 들어오면 종료됨.
- 작업상황
playStage(Stage stage, Scanner sc)
: 사용자로부터 입력받아 각 스테이지를 수행하는 메서드.- 스테이지명을 띄운다.
- 맵을 출력한다.
while(isPlaying)
에 의해 q 명령이 들어오기 전까지 계속 명령을 수행한다.
- 이에 따라
execute
메서드에서playStage
메서드가 분리되고 메서드 길이가 짧아짐.
- 동작
- Q명령이 들어올 때까지 플레이어 이동을 자유자재로 할 수 있음.
- 하지만 앞의 오브젝트와 상호작용(예 : 공을 민다) 등의 행위를 수행할 수 없음. 이는 3단계에서 구현해야함.
- 결론
- 2단계 끝!
- 작업상황
- Stage 클래스 변경
- 생성자 : currentMap 초기 설정에서,
copyOriginalMap()
메서드에 의해 만들어진 복사본을 기반으로 설정되도록 함. reset()
: 스테이지 맵을 초기화하는 void 메서드copyOriginalMap()
: originalMap을 복사하여 반환
- 생성자 : currentMap 초기 설정에서,
- Prompt 클래스 변경
initCommandMap(Stage stage)
: R 명령 추가. R 입력시 스테이지를 리셋함.
- Stage 클래스 변경
- 동작
- 리셋 기능이 추가됨.
- 작업상황
- MapObject 인터페이스를 추상클래스로 변경함.
- Wall, Hall, Player 등 구현체와의 관계를 구현이 아닌, 상속으로 변경함. 따라서, Wall, Hall ,... 은
MapObject
의 하위 클래스이다.
- Wall, Hall, Player 등 구현체와의 관계를 구현이 아닌, 상속으로 변경함. 따라서, Wall, Hall ,... 은
- MapObject 인터페이스를 추상클래스로 변경함.
- 동작
- 기존과 차이 없음.
- 작업상황
- MapObject의 하위클래스에게 소속 스테이지, 좌표를 부여함.
- 각 MapObject 하위 클래스들은 소속 스테이지, 좌표를 멤버로 가진다.
- MapObject의 하위 클래스 생성시 별다른 속성을 부여하지 않았던 기존과 달리, 현재는 스테이지 속성, 좌표 속성이 추가되어야하기 때문에 스테이지 생성 과정도 함께 손대야했음.
- 기존에 Stage 생성에는 StageBuilder 객체를 생성하고 이를 통해 Stage를 생성해야했으나, 이제 Stage의 static 메서드
build
를 통하여, StageBuilder의 static메서드를 거쳐, Stage 클래스에서 Stage를 생성하도록 함.
- MapObject의 하위클래스에게 소속 스테이지, 좌표를 부여함.
- 동작
- 기존과 차이 없음.
- 작업상황
- MapObject의 하위 클래스에게
getPoint()
메서드를 추가함. : 현재 좌표를 반환하게 함.
- MapObject의 하위 클래스에게
- 동작
- 기존과 차이 없음.
- 작업상황
- Stage 클래스에서 player를 멤버로 하도록 함.
- 동작
- 기존과 차이 없음.
- 작업상황
- Player, Ball 클래스에 Hall 멤버변수
ownHall
을 추가. 소지한 Hall을 가리킴addHall(Hall hall)
: Hall을 소지한다.Hall removeHall()
: 소지한 hall을 제거하고 반환함.hasHall()
: hall을 가지고 있는지 여부를 boolean으로 반환함.
- Player, Ball 클래스에 Hall 멤버변수
- 동작
- 기존과 차이 없음.
- 작업상황
- Player, Hall의
hasHall()
메서드 오류 수정 : hall을 가지고 있지 않으면 true가 반환되는 문제가 있었으나 정정함. - 지정 두 좌표의 맵 오브젝트를 교체하는
exchange
메서드 제거 splitPlayerFromMap()
추가 : 플레이어를 맵의 위치에서 제거하고 플레이어를 반환하는 메서드. Hall을 가지고 있으면 Hall을 놓고, 아니면 그 자리에 Space를 놓는다.movePlayerToHall(Point hallPoint)
추가 : 플레이어를 지정 좌표의 Hall로 이동하는 메서드. 플레이어는 Hall을 가지게 된다.movePlayerToSpace(Point spacePoint)
추가 : 플레이어를 지정 좌표의 Space로 이동하는 메서드.addHall(Hall hall)
: Hall을 소지한다.Hall removeHall()
: 소지한 hall을 제거하고 반환함.hasHall()
: hall을 가지고 있는지 여부를 boolean으로 반환함.
movePlayerToEast
,movePlayerToSouth
,movePlayerToWest
,movePlayerToNorth
: 플레이어를 동남서북으로 이동시킴.getNmbOfHall()
: 플레이어가 Hall을 가지고 있는 경우도 전체 Hall의 갯수로 집계함.
- Player, Hall의
- 동작
- 플레이어가 구멍 위를 지나갈 수 있음.
- 구멍 위에 있을 때는 구멍이 보이지 않지만, 플레이어가 구멍을 통과할 때 구멍이 다시 보인다.
- 작업상황
- Movable 인터페이스 추가 : 자의적이든 타의적이든 다른 위치로 움직일 수 있는 객체 Ball, Player를
Movable
로 추상화함.Movable
은 Hall 위에 올라설 수 있으므로, [3.06 revision]에서 정의한add(Hall hall)
,Hall removeHall()
,hasHall()
을 Movable 인터페이스의 추상메서드로 함.void moveTo(Point p)
: 지정 좌표로 이동
- Stage 클래스
PushBall(Point fromBallPoint, Point arrivalPoint)
: 공을 지정 좌표로 미는 시도를 하는 메서드. 지정 좌표에 space나 Hall이 있으면 밀 수 있고, 없으면 밀 수 없다.splitMovableFromMap(Movable movable)
: 지정 Movable 객체를 맵에서 분리시킴.splitBallFromMap(Ball ball)
: 지정 ball 객체를 맵에서 분리시킴. 위의 메서드 참조splitPlayerFromMap()
: Player를 맵에서 분리시킴. 위의 메서드 참조. 기존에 이 메서드가 존재했으나, splitMovableFromMap으로 확장했다.moveBallToHall(Ball fromBall, Point arrivalPoint)
: ball을 hall로 이동moveBallToSpace(Ball fromBall, Point arrivalPoint)
: ball을 space로 이동
movePlayerToEast
,movePlayerToSouth
,movePlayerToWest
,movePlayerToNorth
- 이동 방향에
Ball
이 있을 경우에 대한 처리를 추가.
- 이동 방향에
- Movable 인터페이스 추가 : 자의적이든 타의적이든 다른 위치로 움직일 수 있는 객체 Ball, Player를
- 동작
- 플레이어가 공을 밀 수 있음.
- 공이 만약 구멍 위에 올려지면 공에
Hall
이 포함되고 공의 마커가 '0'으로 출력되게 함. - 공이 다시 구멍에서 빠져나가면 공과 구멍이 분리됨
- 작업상황
- Stage 클래스
isCleared()
: 클리어 여부를 반환함.- Clear 조건 : 스테이지의 공의 갯수와, Hall을 가진 공의 갯수가 일치할 때
getNmbOfInputtedBall()
: Hall에 들어가져있는 Ball의 갯수를 반환함InputtedBallCount(int countOfInputtedBall, MapObject mo)
: 지정 MapObject가 구멍을 가진 Ball이면 매개변수 int값을 증가시켜서 반환
- 멤버
turn
추가- reset() 명령 실행 시 turn이 0이 되도록 함.
- 플레이어의
moveToWest
,moveToEast
,moveToSouth
,moveToNorth
명령이 성공했을 때 turn 값이 1 증가함. getCurrentTurn()
: 현재 턴을 반환함
- Prompt 클래스
- 게임 시작 환영메시지 추가
- static 상수로 취급했던
List<Stage> stages을
execute` 메서드에서 지역변수로 하도록 함. - stages의 모든 멤버를 소모하고, Prompt가
isPlaying
상태일 때 전체 클리어 메시지를 출력하고 프로그램이 종료됨.
- Stage 클래스
- 동작
- 스테이지 1부터 스테이지2까지(현재 소스파일에 포함된 스테이지는 2까지이다.) 클리어할 때마다 순서대로 실행함.
- 각 스테이지 클리어 시 축하메시지와, 해당 스테이지의 소요 turn 수(이동 횟수)를 출력함.
- 모든 스테이지 클리어 및
isPlaying
상태일 때 전체 클리어 메시지를 출력하고 프로그램이 종료됨.
- 작업상황
- [3.05 revision]에서 Stage의 멤버로 Player로 뒀지만, reset메서드에서는 이에 대한 초기화 작업을 수행하지 않았음.
- 이 문제를 해결하기위해 reset메서드에 player 초기화 작업도 수행하도록 함.
- 동작
- 이전과 전체적인 작동원리는 같으나, 리셋이 정상적으로 작동하도록 됨
- 작업상황
- Stage 1의 맵을 내 맘대로 수정함.
- 동작
- Stage 1의 맵이 수정됐다.
- 작업상황
- Stage 2의 맵을 내 맘대로 수정함.
- 동작
- Stage 2의 맵이 수정됐다.
- 작업상황
- Stage 3을 추가
- Movable에서 void addHall(Hall hall) 추가 및 구현체들에서 구현
- 각 구현체들은 자신의 타입으로 자기 자신을 반환하도록 함.
- 맵 읽기에서 0을 읽도록,
MapObject getInstance
에서 0도 변환하도록 함.- 0을 읽으면 Ball에 hall을 add 한뒤 Ball을 반환한다.
- 동작
- Stage 3이 추가됨.
- 작업상황
- Stage 4,5를 추가
- 동작
- Stage 4,5가 추가됨
- 작업상황
- Passable 인터페이스 추가. Space와 Hall은 Passable의 구현체임
- Stage 클래스에서,
moveToWest
,moveToEast
,moveToSouth
,moveToNorth
메서드가 space, Hall에 대해 따로 케이스를 분류하다보니 코드가 길어지는 문제를 해결하고자, 이들을 통과할 수 있는 요소인 Passable로 추상화함. 이로서 이들 메서드의 길이가 좀 더 짧아졌다. movePlayerToSpace
,movePlayerToHall
을movePlayerToPassable
로 통합
- 동작
- 기존과 동일함.
-
작업상황
- Movable 인터페이스의 isMovable 메서드가 더 이상 필요하지 않아서 제거함
-
동작
- 기존과 동일함
-
작업상황
- Stage에 다음 멤버변수를 추가
- Stack<MapObject[][]> beforeStack : 플레이어의 이동이 성공했을 경우, 이동후의 맵의 상태를 저장하는 Stack.
- FirstIn-LastOut 인 Stack구조.
getCurrentTurn()
: beforeStack의 size()가 현재 턴의 수를 지칭함. 따라서 메서드는 beforeStack의 size를 반환하도록 하도록 변경했다.
- Stack<MapObject[][]> beforeStack : 플레이어의 이동이 성공했을 경우, 이동후의 맵의 상태를 저장하는 Stack.
- Stage에 다음 멤버변수를 삭제
- turn : beforeStack의 도입으로 더 이상 필요 없어짐.
- Stage에 recordCurrentTurn() 메서드 추가
- 모든 이동 성공 동작 이후 호출되는 메서드로, 현재 변경된 맵 상태를 beforeStack에 저장한다.
- Stage의 reset메서드가 호출시,
beforeStack
도 초기화(clear
메서드 호출)
- Stage에 다음 멤버변수를 추가
-
동작
- 기존과 동일함
- 요구사항을 만족하는지 여부
- 맵을 txt파일로 스스로 작성함.
- 지도파일 Map.txt를 문자열로 읽어서 처리함.
- 처음 시작시 Stage 1의 지도와 프롬프트가 표시됨.
- r 명령 입력시 스테이지 정상 초기화 확인
- 모든 o를 O자리에 넣으면 클리어 화면을 표시하고 다음 스테이지를 표시함.
- 주어진 모든 스테이지 클리어시 축하 메시지 출력함.
- 플레이어 이동조건을 만족하는가?
- o를 밀어서 이동할 수 있지만, 당길 수 없음.
- o를 O 지점에 밀어넣으면 화면에 0으로 표시됨
- #을 통과할 수 없음.
- 0상태의 o를 밀어내면 다시 o와 O로 분리됨.
- 플레이어가 움직일 때마다 턴수가 카운트 됨.
- 상자가 두 개 연속으로 붙어있는 경우 밀 수 없음.
- 작업상황
- Stage의 player 멤버변수 제거. 써보다보니 멤버로 쓰기엔 손해보는 구석이 많았다.
recordCurrentTurn()
->recordBeforeTurn()
메서드 명 변경- 메서드의 호출시기를, 맵 상태의 변화 직전으로 함. (실제 이동작업 수행 바로 직전)
- 동작
- 기존과 별 눈에 띄는 차이는 없지만, 실제로 beforeStack에 쌓이는 데이터는 첫턴부터, 플레이어의 행동변화가 있는 시점직전마다의 맵 데이터이다. (기존엔 변화 이후의 데이터를 Stack에 쌓았는데, 곰곰히 생각해보니 이상함이 느껴져서 수정함)
- 제출
- 여기까지를 3단계로 제출하도록 함.
- 작업상황
Stack<MapObject[][]> afterStack
추가 : 되돌아가기 기능을 할 때 현재 턴을 저장하는 스택- Stage의 redo() 메서드 추가
- afterStack에 현재 stage를 저장
- beforeStack에서 가장 위에 있는 MapObject[][]을 가져와 currentMap으로 함.
- 돌아가는데 성공하면 성공메시지를, 가장 첫번째 턴일 경우 실패 메시지를 출력함.
- Stage의
CopyMap
메서드 추가- Stage의 기록인
MapObject[][]
을 Stack에 저장할 때 깊은 복사를 해야함. (내부 객체를 새로 생성해야함.) - 따라서 기존의
CopyOriginal()
메서드를 일반화함. 지정 MapObject[][]을 깊은 복사하는 메서드로 일반화. ->copyMap(MapObject[][] stageMap)
- Stage의 기록인
- Stage의
recordBeforeTurn
메서드 수정- 현재 currentMap[][]을 깊은 복사해서 beforeStack에 저장함.
- Prompt의
inputCommandQueue
수정 : 입력을 모두 대문자화했는데, u와 (추후 추가 예정)U를 구분하기 위해서는 대문자화를 하면 안 된다. - Prompt의
initCommandMap
수정 : q,Q,w,W, ... 대소문자 구분을 했었는데 그냥 따로 처리하게 함. 추가로 u 명령어 추가
- 동작
- 되돌아가기 기능이 추가됐다. (u 명령어)
- 작업상황
cancelRedo()
: 다음 턴으로 다시 돌아가기 기능 추가- 현재 턴의 데이터를 다시 beforeStack에 쌓는다.
- afterStack에서 다음 턴의 데이터를 다시 가져온 뒤 이를 currentMap으로 한다.
- 동작
- 다음 턴으로 다시 되돌아가기(돌아가기 취소 기능) 기능이 추가됐다. (U 명령어)