1. 程式人生 > 其它 >[LeetCode] 1275. Find Winner on a Tic Tac Toe Game 找出井字棋的獲勝者

[LeetCode] 1275. Find Winner on a Tic Tac Toe Game 找出井字棋的獲勝者


Tic-tac-toeis played by two playersAandBon a3 x 3grid. The rules of Tic-Tac-Toe are:

  • Players take turns placing characters into empty squares' '.
  • The first playerAalways places'X'characters, while the second playerBalways places'O'characters.
  • 'X'and'O'characters are always placed into empty squares, never on filled ones.
  • The game ends when there arethreeof the same (non-empty) character filling any row, column, or diagonal.
  • The game also ends if all squares are non-empty.
  • No more moves can be played if the game is over.

Given a 2D integer arraymoveswheremoves[i] = [rowi, coli]indicates that theithmove will be played ongrid[rowi][coli]

. returnthe winner of the game if it exists(AorB). In case the game ends in a draw return"Draw". If there are still movements to play return"Pending".

You can assume thatmovesis valid (i.e., it follows the rules ofTic-Tac-Toe), the grid is initially empty, andAwill play first.

Example 1:

Input: moves = [[0,0],[2,0],[1,1],[2,1],[2,2]]
Output: "A"
Explanation: A wins, they always play first.

Example 2:

Input: moves = [[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]]
Output: "B"
Explanation: B wins.

Example 3:

Input: moves = [[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]]
Output: "Draw"
Explanation: The game ends in a draw since there are no moves to make.

Example 4:

Input: moves = [[0,0],[1,1]]
Output: "Pending"
Explanation: The game has not finished yet.

Constraints:

  • 1 <= moves.length <= 9
  • moves[i].length == 2
  • 0 <= rowi, coli<= 2
  • There are no repeated elements onmoves.
  • movesfollow the rules of tic tac toe.

這道題是關於井字棋遊戲的,這個遊戲簡單容易上手,是課間十五分鐘必備遊戲之一,遊戲規則很簡單,一個人畫叉,一個人畫圓圈,只要有三個相連的位置,包括對角線就算贏。而這道題給了兩個玩家的若干操作,讓判斷當前的棋盤狀態,是哪一方贏了,還是沒下完,或者是平局。判贏的條件就是找到任意行或列,或者對角線有三個相同的符號,若找不到有可能是平局或者沒下完,只要判斷總步數是否為9,就知道有沒有下完了。由於給定的是兩個玩家按順序落子的位置,一個比較直接的方法就是分別還原出兩個玩家在棋盤上的落子,分別還原出兩個 3 by 3 的棋盤的好處是可以不用區分到底是叉還是圓圈,只要找三個連續的落子位置就行了,而且可以把查詢邏輯放到一個子函式中進行復用。在子函式中,判斷各行各列是否有連續三個落子,以及兩條對角線,若有的話返回 true,否則 false。然後分別對還原出來的陣列A和B呼叫子函式,若有返回的 true,則返回對應的A或B。否則就判斷 moves 陣列的長度,若等於9,返回平局 Draw,反之為 Pending,參見程式碼如下:


解法一:

class Solution {
public:
    string tictactoe(vector<vector<int>>& moves) {
        vector<vector<int>> A(3, vector<int>(3)), B = A;
        for (int i = 0; i < moves.size(); ++i) {
            if (i % 2 == 0) A[moves[i][0]][moves[i][1]] = 1;
            else B[moves[i][0]][moves[i][1]] = 1;
        }
        if (helper(A)) return "A";
        if (helper(B)) return "B";
        return (moves.size() == 9) ? "Draw" : "Pending";
    }
    bool helper(vector<vector<int>>& v) {
        for (int i = 0; i < 3; ++i) {
            if (v[i][0] == 1 && v[i][1] == 1 && v[i][2] == 1) return true;
            if (v[0][i] == 1 && v[1][i] == 1 && v[2][i] == 1) return true;
        }
        if (v[0][0] == 1 && v[1][1] == 1 && v[2][2] == 1) return true;
        if (v[2][0] == 1 && v[1][1] == 1 && v[0][2] == 1) return true;
        return false;
    }
};

再來看一種更簡潔的寫法,為了更好的區分玩家A和B落子,這裡可以用1和 -1 來表示,這樣若玩家A有三個相連的落子,則和為3,而玩家B的相連3個落子之和為 -3,只要判斷各行各列以及對角線的和的絕對值,若為3,則肯定有玩家獲勝,具體區分是哪個玩家,可以根據當前運算元的位置來判斷,遍歷 moves 陣列時,若下標為偶數,則表示是玩家A,奇數則為玩家B,根據i的奇偶行來賦值 val 為1或 -1。取出落子位置的橫縱座標r和c,若二者相等,則是主對角線,diag 加上 val,若二者和為2,則是逆對角線,rev_diag 加上 val。然後 row 和 col 陣列對應的位置加上 val,接下來判斷行列對角線的和的絕對值是否有等於3的,有的話就根據 val 的正負來返回玩家A或B。否則就判斷 moves 陣列的長度,若等於9,返回平局 Draw,反之為 Pending,參見程式碼如下:


解法二:

class Solution {
public:
    string tictactoe(vector<vector<int>>& moves) {
        int diag = 0, rev_diag = 0;
        vector<int> row(3), col(3);
        for (int i = 0; i < moves.size(); ++i) {
            int r = moves[i][0], c = moves[i][1], val = i % 2 == 0 ? 1 : -1;
            if (r == c) diag += val;
            if (r + c == 2) rev_diag += val;
            row[r] += val;
            col[c] += val;
            if (abs(diag) == 3 || abs(rev_diag) == 3 || abs(row[r]) == 3 || abs(col[c]) == 3) return val == 1 ? "A" : "B";
        }
        return moves.size() == 9 ? "Draw" : "Pending";
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1275


參考資料:

https://leetcode.com/problems/find-winner-on-a-tic-tac-toe-game/

https://leetcode.com/problems/find-winner-on-a-tic-tac-toe-game/discuss/638224/Short-Java-code-using-diagonals-and-colrow-arrays


LeetCode All in One 題目講解彙總(持續更新中...)


喜歡請點贊,疼愛請打賞❤️~.~


微信打賞


Venmo 打賞