[CareerCup] 17.2 Tic Tac Toe 井字棋遊戲

Grandyang發表於2016-04-19

 

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;
    }
}

 

CareerCup All in One 題目彙總

相關文章