17.2 Design an algorithm to figure out if someone has won a game oftic-tac-toe.
這道題讓我們判斷玩家是否能贏井字棋遊戲,有下面幾點需要考慮:
1. 判斷是否能贏hasWon函式是呼叫一次還是多次,如果是多次,我們可能為了優化而需要加入一些預處理。
2. 井字棋遊戲通常是3x3的大小,我們是否想要實現NxN的大小?
3. 我們需要在程式碼緊湊,執行速度和程式碼清晰之間做出選擇。
#include <iostream> #include <string> #include <vector> #include <ctime> using namespace std; int convertBoardToInt(vector<string> board) { int factor = 1, sum = 0; for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[i].size(); ++j) { int v = 0; if (board[i][j] == 'x') v = 1; else if (board[i][j] == 'o') v = 2; sum += v * factor; factor *= 3; } } return sum; } enum class Piece {Empty, Red, Blue}; enum class Check {Row, Column, Diagonal, ReverseDiagonal}; Piece getIthColor(vector<vector<Piece>> board, int idx, int var, Check check) { int N = board.size(); if (check == Check::Row) { return board[idx][var]; } else if (check == Check::Column) { return board[var][idx]; } else if (check == Check::Diagonal) { return board[var][var]; } else if (check == Check::ReverseDiagonal) { return board[N - 1 - var][var]; } return Piece::Empty; } Piece getWinner(vector<vector<Piece>> board, int fixed_idx, Check check) { Piece color = getIthColor(board, fixed_idx, 0, check); if (color == Piece::Empty) { return Piece::Empty; } for (int var = 1; var < board.size(); ++var) { if (color != getIthColor(board, fixed_idx, var, check)) { return Piece::Empty; } } return color; } // work for 3*3 board Piece hasWon1(vector<vector<Piece>> board) { for (int i = 0; i < board.size(); ++i) { if (board[i][0] != Piece::Empty && board[i][0] == board[i][1] && board[i][0] == board[i][2]) { return board[i][0]; } if (board[0][i] != Piece::Empty && board[0][i] == board[1][i] && board[0][i] == board[2][i]) { return board[0][i]; } } if (board[0][0] != Piece::Empty && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return board[0][0]; } if (board[2][0] != Piece::Empty && board[2][0] == board[1][1] && board[2][0] == board[0][2]) { return board[2][0]; } return Piece::Empty; } // N*N board Piece hasWon2(vector<vector<Piece>> board) { int N = board.size(); Piece winner = Piece::Empty; for (int i = 0; i < N; ++i) { winner = getWinner(board, i, Check::Row); if (winner != Piece::Empty) return winner; winner = getWinner(board, i, Check::Column); if (winner != Piece::Empty) return winner; } winner = getWinner(board, -1, Check::Diagonal); if (winner != Piece::Empty) return winner; winner = getWinner(board, -1, Check::ReverseDiagonal); if (winner != Piece::Empty) return winner; return Piece::Empty; } // N*N board Piece hasWon3(vector<vector<Piece>> board) { int N = board.size(), row = 0, col = 0; for (row = 0; row < N; ++row) { if (board[row][0] != Piece::Empty) { for (col = 1; col < N; ++col) { if (board[row][col] != board[row][col - 1]) { break; } } if (col == N) return board[row][0]; } } for (col = 0; col < N; ++col) { if (board[0][col] != Piece::Empty) { for (row = 1; row < N; ++row) { if (board[row][col] != board[row - 1][col]) { break; } } if (row == N) return board[0][col]; } } if (board[0][0] != Piece::Empty) { for (row = 1; row < N; ++row) { if (board[row][row] != board[row - 1][row - 1]) { break; } } if (row == N) return board[0][0]; } if (board[N - 1][0] != Piece::Empty) { for (row = 1; row < N; ++row) { if (board[N - row - 1][row] != board[N - row][row - 1]) { break; } } if (row == N) return board[N - 1][0]; } return Piece::Empty; } // N*N board Piece hasWon4(vector<vector<Piece>> board) { int N = board.size(), i = 0, j = 0; vector<Piece> pieces{Piece::Red, Piece::Blue}; for (Piece color : pieces) { for (i = 0; i < N; ++i) { bool maybe_col = true, maybe_row = true; for (j = 0; j < N; ++j) { if (board[i][j] != color) maybe_row = false; if (board[j][i] != color) maybe_col = false; } if (maybe_col || maybe_row) return color; } bool maybe_diag = true, maybe_revdiag = true; for (i = 0; i < N; ++i) { if (board[i][i] != color) maybe_diag = false; if (board[N - i - 1][i] != color) maybe_revdiag = false; } if (maybe_diag || maybe_revdiag) return color; } return Piece::Empty; } Piece convertIntToPiece(int i) { if (i == 1) { return Piece::Blue; } else if (i == 2) { return Piece::Red; } else { return Piece::Empty; } } void printVec(vector<vector<int>> v) { for (int i = 0; i < v.size(); ++i) { for (int j = 0; j < v[i].size(); ++j) { cout << v[i][j] << " "; } cout << endl; } cout << endl; } void printPiece(Piece p) { if (p == Piece::Empty) cout << "Empty" << endl; else if (p == Piece::Red) cout << "Red" << endl; else if (p == Piece::Blue) cout << "Blue" << endl; } int main() { srand(time(NULL)); for (int k = 0; k < 10; ++k) { int N = 3; vector<vector<int>> v(N, vector<int>(N, 0)); vector<vector<Piece>> board(N, vector<Piece>(N)); for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { v[i][j] = rand() % 3; board[i][j] = convertIntToPiece(v[i][j]); } } Piece p1 = hasWon1(board); Piece p2 = hasWon2(board); Piece p3 = hasWon3(board); Piece p4 = hasWon4(board); if (p1 != p2 || p2 != p3 || p3 != p4) { printPiece(p1); printPiece(p2); printPiece(p3); printPiece(p4); printVec(v); } cout << endl; } }