C++입니다.
position 입력 메시지 출력시 빈칸 숫자들을 ","로 구분하여 나열하는 부분을 간과하면 안될 듯.
프로그램 설명:
"turn"이 9가 될 때까지 진행. 짝수 "turn"은 "O", 홀수 "turn"은 "X". "board[]"값은 Empty, O, X 중 하나.
Winning 조건 점검은, Clever한 방법을 고민하다가 포기하고 평범하게 갔습니다.
board[] index에 따른 보드판이 다음과 같다면:
0|1|2
3|4|5
6|7|8
- 현재 위치 기준 가로방향 (row) 점검 : 0,1,2 또는 3,4,5 또는 6,7,8
- 현재 위치 기준 세로방향 (column) 점검 : 0,3,6 또는 1,4,7 또는 2,5,8
- 현재 위치가 1,3,5,7이 아니면 사선방향(diagonal) 점검 : 0,4,8 **및** 2,4,6
Note : 현재 위치가 4가 아닌 경우, 현재 위치가 속한 한쪽 사선만 점검하면 되지만
조건식 추가로 코드가 복잡해지는거 같아서 그냥 두 사선 뱡향을 모두 점검합니다.
```{.cpp}
#include <iostream>
using namespace std;
typedef enum { Player_Empty, Player_O, Player_X } PlayerType;
static PlayerType board[9];
int getValidPosition(int turn)
{
int position;
int numEmpty = 10-turn;
do {
cout << "Player " << (turn%2 ? 1 : 2) << " - please type a position ";
cout << "(available position(s) are ";
for (int i=0, count=0; i<9; ++i)
{
if (board[i] == Player_Empty)
{
cout << i+1;
cout << (numEmpty != ++count ? "," : "):");
}
}
cin >> position;
if (position < 1 || 9 < position || board[position-1] != Player_Empty)
cout << "Invalid position. Try again.\n";
else
return position-1; // convert to array index
} while (true);
}
bool hasWon(PlayerType player, int ndx)
{
// check row
int base = (ndx/3)*3;
if (board[base + (ndx-base+0)%3] == player &&
board[base + (ndx-base+1)%3] == player &&
board[base + (ndx-base+2)%3] == player) return true;
// check column
if (board[(ndx+0*3)%9] == player &&
board[(ndx+1*3)%9] == player &&
board[(ndx+2*3)%9] == player) return true;
// check diagonals
if (ndx % 2 != 0)
return false; // indices 1,3,5,7 cannot make a diagonal win condition
if (board[0] == player &&
board[4] == player &&
board[8] == player) return true;
if (board[2] == player &&
board[4] == player &&
board[6] == player) return true;
return false;
}
bool printBoard()
{
for (int row=0; row<3; ++row)
{
cout << "|";
for (int col=0; col<3; ++col)
{
int ndx = row*3+col;
switch (board[ndx])
{
case Player_O: cout << "O"; break;
case Player_X: cout << "X"; break;
default: cout << ndx+1; break;
}
cout << "|";
}
cout << endl;
}
}
int main(void)
{
int turn = 0; // even = "O", odd = "X"
printBoard();
while (++turn < 10)
{
int position = getValidPosition(turn);
board[position] = (turn%2) ? Player_X : Player_O;
printBoard();
if (hasWon(board[position], position))
{
cout << ((board[position] == Player_X) ? "X" : "O") << " has won.\n";
return 0;
}
}
cout << "This game is a draw\n";
return 0;
}
```
C++입니다.
position 입력 메시지 출력시 빈칸 숫자들을 ","로 구분하여 나열하는 부분을 간과하면 안될 듯.
프로그램 설명:
"turn"이 9가 될 때까지 진행. 짝수 "turn"은 "O", 홀수 "turn"은 "X". "board[]"값은 Empty, O, X 중 하나.
Winning 조건 점검은, Clever한 방법을 고민하다가 포기하고 평범하게 갔습니다.
board[] index에 따른 보드판이 다음과 같다면:
0|1|2
3|4|5
6|7|8
- 현재 위치 기준 가로방향 (row) 점검 : 0,1,2 또는 3,4,5 또는 6,7,8
- 현재 위치 기준 세로방향 (column) 점검 : 0,3,6 또는 1,4,7 또는 2,5,8
- 현재 위치가 1,3,5,7이 아니면 사선방향(diagonal) 점검 : 0,4,8 **및** 2,4,6
Note : 현재 위치가 4가 아닌 경우, 현재 위치가 속한 한쪽 사선만 점검하면 되지만
조건식 추가로 코드가 복잡해지는거 같아서 그냥 두 사선 뱡향을 모두 점검합니다.
```{.cpp}
#include <iostream>
using namespace std;
typedef enum { Player_Empty, Player_O, Player_X } PlayerType;
static PlayerType board[9];
int getValidPosition(int turn)
{
int position;
int numEmpty = 10-turn;
do {
cout << "Player " << (turn%2 ? 1 : 2) << " - please type a position ";
cout << "(available position(s) are ";
for (int i=0, count=0; i<9; ++i)
{
if (board[i] == Player_Empty)
{
cout << i+1;
cout << (numEmpty != ++count ? "," : "):");
}
}
cin >> position;
if (position < 1 || 9 < position || board[position-1] != Player_Empty)
cout << "Invalid position. Try again.\n";
else
return position-1; // convert to array index
} while (true);
}
bool hasWon(PlayerType player, int ndx)
{
// check row
int base = (ndx/3)*3;
if (board[base + (ndx-base+0)%3] == player &&
board[base + (ndx-base+1)%3] == player &&
board[base + (ndx-base+2)%3] == player) return true;
// check column
if (board[(ndx+0*3)%9] == player &&
board[(ndx+1*3)%9] == player &&
board[(ndx+2*3)%9] == player) return true;
// check diagonals
if (ndx % 2 != 0)
return false; // indices 1,3,5,7 cannot make a diagonal win condition
if (board[0] == player &&
board[4] == player &&
board[8] == player) return true;
if (board[2] == player &&
board[4] == player &&
board[6] == player) return true;
return false;
}
bool printBoard()
{
for (int row=0; row<3; ++row)
{
cout << "|";
for (int col=0; col<3; ++col)
{
int ndx = row*3+col;
switch (board[ndx])
{
case Player_O: cout << "O"; break;
case Player_X: cout << "X"; break;
default: cout << ndx+1; break;
}
cout << "|";
}
cout << endl;
}
}
int main(void)
{
int turn = 0; // even = "O", odd = "X"
printBoard();
while (++turn < 10)
{
int position = getValidPosition(turn);
board[position] = (turn%2) ? Player_X : Player_O;
printBoard();
if (hasWon(board[position], position))
{
cout << ((board[position] == Player_X) ? "X" : "O") << " has won.\n";
return 0;
}
}
cout << "This game is a draw\n";
return 0;
}
```