Binding of Isaac은 로그라이크 슈팅 게임으로 무작위로 생성되는 던전 속에서 몬스터를 잡고 성장하며 보스를 잡는 게임이다. 한 번 던전을 생성하고, 생성한 던전을 클리어할 수 있는지 판별하는 프로그램을 작성해 보자.
시드
-이고 나머지 문자는 대문자 알파벳과 숫자로 총 $36$가지의 문자로 구성되어 있다.난수 함수
rand()
randInt($l$, $r$)
chance($p$)
choice($\text{arr}$)
던전 생성
던전은 아래의 단계 순서대로 생성하며, rand() 호출 순서에 따라 결과가 달라질 수 있음에 유의하라.
배열에서 원소를 제거할 때, 제거하지 않은 나머지 원소들의 순서는 유지된다.
1단계
2단계
크기가 $9 \times 9$이고 칸이 총 $81$개인 격자 보드를 생성한다. 좌측 최상단의 좌표가 $(0, 0)$이고 우측 최하단의 좌표가 $(8, 8)$이다. $(x, y)$는 $x$행 $y$열을 의미한다.
2단계에서 생성된 방은 배열 $\text{room}$에 순서대로 넣는다.
$(4, 4)$ 위치에 시작방을 생성한다. (배열 $\text{room}$에도 시작방이 담긴다.)
아래 과정을 총 $N$개(시작방은 제외)의 방을 생성할 때까지 반복한다.
큐 $Q$에 choice($\text{room}$)의 값(방)을 넣는다.
아래 과정을 큐 $Q$가 완전히 빌 때까지 반복한다.
큐 $Q$에서 가장 먼저 넣었던 방을 꺼낸다.
그 방의 좌표 중심으로 동남서북 순서로 인접한 칸에다 새로운 방 생성을 시도한다.
배열 $\text{room}$에서 시작방을 제거한다.
방 생성 과정에서 rand() 함수는 $R_2$번 호출된다.
던전 생성 2단계를 마쳤을 때, rand() 함수는 총 $\sum_{i=1}^{2}R_i$번 호출되었다.
3단계
배열 $\text{special}$은 배열 $\text{room}$에서 인접한 방의 개수가 $1$개인 방들을 생성된 순서대로 넣은 배열이다.
일반방을 지정한다.
보스방을 지정한다.
비밀방을 지정 시도한다.
보물방을 지정 시도한다.
만약 배열 $\text{special}$가 비었다면 보물방 지정 시도를 중지한다.
보물방은 항상 지정에 성공한다.
지정에 성공했다면 choice($\text{special}$)을 보물방으로 지정한다.
이 과정에서 rand() 함수는 $R_6$번 호출된다. $($보물방이 지정되었다면 $R_6 = 1$, 지정되지 않았다면 $R_6 = 0)$
보물방 지정 시도를 마쳤을 때, rand() 함수는 총 $\sum_{i=1}^{6}R_i$번 호출되었다.
$N$이 $15$ 이상이면 보물방을 한 번 더 지정 시도한다.
상점방을 지정 시도한다.
악마방 혹은 천사방을 생성 시도한다.
chance($20$)를 호출한 값이 True면 악마방 혹은 천사방 생성 시도에 성공한다. 그렇지 않으면 실패한다.
배열 $\text{reward}$은 보스방에서 동서남북 순서대로 인접한 칸이 담긴 배열이다.
배열 $\text{reward}$에서 다음 조건 중 하나라도 만족하는 칸들을 제거한다.
생성 시도에 성공했다면 choice($\text{reward}$)에 방을 생성한다.
이 과정에서 rand() 함수는 $R_9$번 호출된다. $($악마방 혹은 천사방이 생성되었다면 $R_9 = 3$, 생성되지 않았다면 $R_9 = 1)$
악마방 혹은 천사방 생성 시도를 마쳤을 때, rand() 함수는 총 $\sum_{i=1}^{9}R_i$번 호출되었다.
희생방을 지정 시도한다.
저주방을 지정 시도한다.
일반방을 추가 지정한다.
던전 생성 3단계를 마쳤을 때, rand() 함수는 총 $\sum_{i=1}^{12}R_i$번 호출되었다.
방 설명
플레이어는 이동하려는 방이 비밀방, 천사방, 악마방이 아니면 자신이 있는 방에서 인접한 방으로 자유롭게 이동할 수 있다.
시작방
플레이어는 해당 방에서 게임을 시작하게 된다.
게임 시작 시 상태는 아래와 같다.
게임 시작 시 아이템 상태는 아래와 같다.
일반방
보스방
비밀방
보물방
상점방
코인 $2$개당 아이템 $1$개씩 구매할 수 있다.
아이템은 두 종류가 있으며, 각각 무한정 구매할 수 있다.
악마방 & 천사방
희생방
저주방
게임 진행
첫 번째 줄에 시드가 주어진다.
첫 번째 줄에 플레이어가 게임에서 승리할 수 있다면 CLEAR를, 승리할 수 없다면 GAME OVER를 출력한다.
두 번째 줄부터 $6H + 3$개 줄에 걸쳐 $(6H + 3) \times (6W + 3)$ 형태로 던전 모습을 출력한다.
생성된 모든 방 $(x_k, y_k)$ 중 $x_k$의 최솟값을 $x_m$, $x_k$의 최댓값을 $x_M$, $y_k$의 최솟값을 $y_m$, $y_k$의 최댓값을 $y_M$라 할 때, $H = x_M - x_m + 1$, $W = y_M - y_m + 1$이다.
방 하나는 $5 \times 5$ 크기로 표현할 수 있다. 각 방끼리는 공백 하나를 두고 있다. 던전의 가장자리에는 공백 하나를 두고 # 문자로 두른 모습을 출력한다.
방의 가장자리에는 벽을 출력한다.
방이 시작방 혹은 보스방인 경우
@ 문자로 출력한다.방이 악마방 혹은 천사방인 경우
< 문자로 출력한다> 문자로 출력한다^ 문자로 출력한다.v 문자로 출력한다./ 문자로 출력한다.\ 문자로 출력한다.\ 문자로 출력한다./ 문자로 출력한다.그 외의 경우
| 문자로 출력한다- 문자로 출력한다.| 문자와 세로 벽면 - 문자가 인접하고 있는 지점은 + 문자로 출력한다.방의 중심에는 방의 종류를 출력한다.
R 문자로 출력한다.B 문자로 출력한다.X 문자로 출력한다.T 문자로 출력한다.M 문자로 출력한다.D 문자로 출력한다.A 문자로 출력한다.S 문자로 출력한다.C 문자로 출력한다.인접한 방끼리는 통로를 출력한다.
두 방 중 한 방이 악마방, 천사방, 비밀방 중 하나인 경우
그 외의 경우
| 문자로 출력한다. $(0, 3)$과 인접한 두 방의 가로 벽면을 제거한다.- 문자로 출력한다. $(3, 0)$과 인접한 두 방의 세로 벽면을 제거한다.+ 문자로 출력한다.
+ 문자 대신 @ 문자로 출력한다.