https://school.programmers.co.kr/learn/courses/30/lessons/160585
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
1. 문제 개요
이 문제의 핵심은 주어진 게임판이 규칙을 어겼는 지 판별하는 것이다.
예를 들어, 승리한 쪽이 있음에도 게임을 계속했거나, 표시를 잘못 했는 지 등의 경우를 판단하여야 한다.
2. 풀이
1) 데이터 변환 및 변수 초기화
vector<vector<char>> boardCnv(3, vector<char>(3));
int oCnt = 0, xCnt = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
boardCnv[i][j] = board[i][j];
if (boardCnv[i][j] == 'O') oCnt++;
if (boardCnv[i][j] == 'X') xCnt++;
}
}
탐색의 편의성을 위해, 게임판의 정보는 boardCnv라는 2D vector에 저장한다.
이와 동시에, 게임판에 있는 기호별 갯수를 샌다.
2) 기호를 잘못 표기했는 지 확인
if(!(oCnt == xCnt || oCnt == xCnt + 1)) {
return 0;
}
양 쪽이 번갈아가며 놓았다면, O와 X의 갯수가 같거나, O의 갯수가 X보다 1개 더 많다.
이에 해당되지 않는다면, 주어진 게임판은 규칙을 어긴 게임판이므로 0을 반환한다.
3) 한 쪽이 이겼는지 판단하기
bool won(vector<vector<char>>& board, char t) {
// (1) 가로로 빙고를 달성한 경우
for(int i = 0; i < board.size(); i++) {
if (board[i][0] == t && board[i][1] == t && board[i][2] == t) {
return true;
}
}
// (2) 세로로 일직선을 만든 경우
for(int col = 0; col < 3; col++) {
if (board[0][col] == t && board[1][col] == t && board[2][col] == t) {
return true;
}
}
// (3) 좌대각선, 우대각선으로 일직선을 만들었다면
if (board[0][0] == t && board[1][1] == t && board[2][2] == t) {
return true;
}
if (board[2][0] == t && board[1][1] == t && board[0][2] == t) {
return true;
}
// 이기지 않음
return false;
}
bool oWin = won(boardCnv, 'O');
bool xWin = won(boardCnv, 'X');
기호 별, 게임판에서 승패 여부를 확인한다.
4) 승패 여부와, 기호의 개수를 같이 비교하기
if (oWin && xWin || (oWin && oCnt != xCnt + 1) || (xWin && oCnt != xCnt)) {
return 0;
}
return 1;
게임판이 규칙을 지키지 않은 경우는 다음과 같다.
a. 둘 다 이긴 경우
b. O가 이겼는데, O의 갯수가 X보다 1개 많지 않은 경우
c. X가 이겼는데, X의 갯수와 O의 갯수가 다른 경우
둘 다 이기기 전에 한쪽이 승리하여 게임이 끝나므로, a와 같이 둘 다 이기는 경우는 발생할 수 없다.
선공인 O가 이기면, O의 갯수는 X의 갯수보다 1개 더 많아야 한다. O가 이겼음에도 O의 갯수가 X의 갯수보다 1개 더 많지 않다면, 이는 X가 규칙을 어긴 경우이다.
후공 X가 이겼다면, O와 X의 갯수는 같아야 한다. X가 이겼는데 O와 X의 갯수가 다르다면, O가 패했음에도 계속 게임을 진행하여 규칙을 위반한 경우이다.
위의 3가지 경우에도 해당되지 않다면, 주어진 게임판은 규칙을 지켰다고 판단하여 1을 반환한다.
3. 전체 코드
// C++
#include <string>
#include <vector>
#include <iostream>
using namespace std;
bool won(vector<vector<char>>& board, char t) {
for(int i = 0; i < board.size(); i++) {
if (board[i][0] == t && board[i][1] == t && board[i][2] == t) {
return true;
}
}
for(int col = 0; col < 3; col++) {
if (board[0][col] == t && board[1][col] == t && board[2][col] == t) {
return true;
}
}
if (board[0][0] == t && board[1][1] == t && board[2][2] == t) {
return true;
}
if (board[2][0] == t && board[1][1] == t && board[0][2] == t) {
return true;
}
return false;
}
int solution(vector<string> board) {
vector<vector<char>> boardCnv(3, vector<char>(3));
int oCnt = 0, xCnt = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
boardCnv[i][j] = board[i][j];
if (boardCnv[i][j] == 'O') oCnt++;
if (boardCnv[i][j] == 'X') xCnt++;
}
}
if(!(oCnt == xCnt || oCnt == xCnt + 1)) {
return 0;
}
bool oWin = won(boardCnv, 'O');
bool xWin = won(boardCnv, 'X');
if (oWin && xWin || (oWin && oCnt != xCnt + 1) || (xWin && oCnt != xCnt)) {
return 0;
}
return 1;
}
# Python
def won(board, t):
# 가로줄 판단.
for row in board:
if row == [t, t, t]:
return True
# 세로줄 판단.
for col in range(3):
if [board[row][col] for row in range(3)] == [t, t, t]:
return True
# 대각선 판단.
if [board[0][0], board[1][1], board[2][2]] == [t, t, t]:
return True
if [board[2][0], board[1][1], board[0][2]] == [t, t, t]:
return True
return False
def solution(board):
board = [list(row) for row in board]
# O의 개수가 X의 개수보다 같거나 1 많아야 함.
o_count, x_count = 0, 0
for row in board:
for c in row:
if c == 'O':
o_count += 1
if c == 'X':
x_count += 1
if not (o_count == x_count or o_count == x_count + 1):
return 0
# O 혹은 X만 승리조건을 만족해야 함.
if won(board, 'O') and won(board, 'X'):
return 0
# O가 승리했다면 o_count == x_count + 1이어야 함.
if won(board, 'O') and o_count != x_count + 1:
return 0
# X가 승리했다면 o_count == x_count 여야 함.
if won(board, 'X') and o_count != x_count:
return 0
return 1
'CodingTest' 카테고리의 다른 글
숫자 변환하기 (0) | 2025.03.31 |
---|---|
호텔 대실 (0) | 2025.03.24 |
기능개발 (0) | 2024.05.08 |
주식가격 (0) | 2024.05.06 |
213. House Robber II (0) | 2024.05.04 |