1+ package week01 .advanced ;
2+
3+ import java .util .Random ;
4+
5+ public class OmokWinChecker {
6+
7+ public static void main (String [] args ) {
8+ System .out .println ("<오목 승리 판정하기>" );
9+ // 29단계 (심화): 오목 승리 판정하기
10+ // 문제: 19x19 크기의 2차원 char 배열로 오목판이 주어져 있다고 가정하고,
11+ // 특정 위치에 `[x, y]`에 방금 돌(`'B'` 또는 `'W'`)이 놓였다고 할 때,
12+ // 그 돌로 인해 게임이 끝났는지(정확히 5개가 연속되는지) 판정하는 프로그램을 작성하세요.
13+ // 가로, 세로, 대각선 2종류(총 4방향)를 모두 검사해야 합니다.
14+ // 핵심 사고: 한 점을 기준으로 4개의 방향(가로, 세로, 대각선)으로
15+ // 5개의 돌이 연속되는지를 탐색하는 로직
16+ // 힌트: `다중 배열`, `if문`, 각 방향을 검사하는 `for문` 또는 `while문`
17+ int N = 19 ;
18+ char EMPTY = '\0' , BLACK = 'B' , WHITE = 'W' ;
19+ // 가로, 세로, 왼쪽위오른쪽아래, 왼쪽아래오른쪽위
20+ int [] dr = {0 , 1 , 1 , 1 };
21+ int [] dc = {1 , 0 , 1 ,-1 };
22+
23+ char [][] board = new char [N ][N ];
24+ Random rnd = new Random ();
25+
26+ // 흑돌,백돌 50개씩 랜덤으로 놓기
27+ int bPlaced = 50 , wPlaced = 50 , bCount =0 , wCount =0 ;
28+ while (bCount < bPlaced ) {
29+ int r =rnd .nextInt (N ), c =rnd .nextInt (N );
30+ if (board [r ][c ]==EMPTY ){
31+ board [r ][c ]=BLACK ;
32+ bCount ++;
33+ }
34+ }
35+ while (wCount < wPlaced ) {
36+ int r =rnd .nextInt (N ), c =rnd .nextInt (N );
37+ if (board [r ][c ]==EMPTY ){
38+ board [r ][c ]=WHITE ;
39+ wCount ++;
40+ }
41+ }
42+
43+ // 흑돌 or 백돌(랜덤) 4연속을 17개 놓기(방향/색 랜덤)
44+ int lineCnt = 17 ;
45+ int placedLine = 0 ;
46+
47+ while (placedLine <lineCnt ) { // 4연속 17개 만들어지면 빠져나오기
48+ char color = rnd .nextBoolean () ? BLACK : WHITE ; // 색 랜덤
49+ int dir = rnd .nextInt (4 ), dx = dr [dir ], dy = dc [dir ]; // 방향 랜덤
50+ int sr = rnd .nextInt (N ); // 행 랜덤
51+ int sc = rnd .nextInt (N ); // 열 랜덤
52+
53+ int er = sr + dx * 3 ; // 마지막 행(0,1,2,3->총 4개) 시작+이동*3
54+ int ec = sc + dy * 3 ; // 마지막 열(0,1,2,3->총 4개) 시작+이동*3
55+ if (er >= 0 && er < N && ec >= 0 && ec < N ) { // 범위안인지 검사
56+ int step = 0 ;
57+ while (step < 4 ) { // 연속 4칸 검사
58+ int r = sr + dx * step ; // 현재 행
59+ int c = sc + dy * step ; // 현재 열
60+ if (board [r ][c ] != EMPTY ) break ; // 하나라도 빈칸이 아니면 실패
61+ step ++;
62+ }
63+ if (step == 4 ) { // 연속 4칸 빈칸 확인되면
64+ step = 0 ; // 0으로 초기화하고
65+ while (step < 4 ) { // 빈칸 확인된 4칸 채우기
66+ board [sr + dx * step ][sc + dy * step ] = color ; // 랜덤색 뽑은걸로 하나씩 이동하면서 채우기
67+ step ++;
68+ }
69+ placedLine ++;
70+ }
71+ }
72+ }
73+
74+ // 마지막 수 놓기(자리,색 랜덤)
75+ char lastColor = rnd .nextBoolean () ? BLACK : WHITE ;
76+ int x , y ;
77+ while (true ) {
78+ x = rnd .nextInt (N );
79+ y = rnd .nextInt (N );
80+ if (board [x ][y ] == EMPTY ) {
81+ board [x ][y ] = lastColor ;
82+ break ;
83+ }
84+ }
85+
86+ // 오목판 출력: EMPTY는->'.', 마지막 수->'L'
87+ System .out .println ();
88+ for (int i =0 ;i <N ;i ++){
89+ for (int j =0 ;j <N ;j ++){
90+ if (i ==x &&j ==y ) {
91+ System .out .print ("L " );
92+ }
93+ else {
94+ System .out .print (board [i ][j ] == EMPTY ? '.' +" " : board [i ][j ]+" " );
95+ }
96+ }
97+ System .out .println ();
98+ }
99+ System .out .println ();
100+
101+ // 마지막 수 기준으로 승패가 결정났는지 확인
102+ boolean win = false ;
103+ for (int i = 0 ; i < 4 ; i ++) { // 4방향 확인
104+ int dx = dr [i ], dy = dc [i ];
105+
106+ int fCnt = 0 ; // 정방향 연속 개수
107+ int r = x + dx , c = y + dy ; // 4방향 이동후 행과 열
108+ while (0 <= r && r < N && 0 <= c && c < N && board [r ][c ] == lastColor ) { // 범위안 && 같은색
109+ fCnt ++;
110+ r += dx ; c += dy ; // 한 칸씩 이동
111+ }
112+
113+ int bCnt = 0 ;// 역방향 연속 개수
114+ r = x - dx ; c = y - dy ;
115+ while (0 <= r && r < N && 0 <= c && c < N && board [r ][c ] == lastColor ) {
116+ bCnt ++;
117+ r -= dx ; c -= dy ;
118+ }
119+
120+ if (1 + fCnt + bCnt != 5 ) { // 마지막수+같은색돌(정방향+역방향) -> 5가 아니면 통과해서 다음 i 확인
121+ continue ;
122+ }
123+
124+ int ax = x - dx * (bCnt + 1 ), ay = y - dy * (bCnt + 1 ); // 시작쪽 바깥 -> 현재-방향*(역방향 이동한 횟수+1), - : (역방향으로 이동)
125+ int bx = x + dx * (fCnt + 1 ), by = y + dy * (fCnt + 1 ); // 끝쪽 바깥 (정방향으로 이동)
126+ boolean overStart = (0 <= ax && ax < N && 0 <= ay && ay < N ) && board [ax ][ay ] == lastColor ; // 바깥 위치가 범위 안 && 마지막수와 색깥이 같음
127+ boolean overEnd = (0 <= bx && bx < N && 0 <= by && by < N ) && board [bx ][by ] == lastColor ;
128+
129+ if (!overStart && !overEnd ) { // 6연속 아니면 승리
130+ win = true ;
131+ break ;
132+ }
133+ }
134+
135+ // 승패 판정 여부
136+ if (win ) {
137+ System .out .println (lastColor + "가 (" + x + ", " + y + ")에 두어 승리하였습니다." );
138+ } else {
139+ System .out .println (lastColor + "의 마지막 수 (" + x + ", " + y + ")로 승패가 결정나지 않았습니다." );
140+ }
141+ }
142+ }
0 commit comments