[LeetCode] 1275. Find Winner on a Tic Tac Toe Game 找出井字棋的獲勝者
Tic-tac-toeis played by two playersA
andB
on a3 x 3
grid. The rules of Tic-Tac-Toe are:
- Players take turns placing characters into empty squares
' '
. - The first player
A
always places'X'
characters, while the second playerB
always 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 arraymoves
wheremoves[i] = [rowi, coli]
indicates that theith
move will be played ongrid[rowi][coli]
A
orB
). In case the game ends in a draw return"Draw"
. If there are still movements to play return"Pending"
.
You can assume thatmoves
is valid (i.e., it follows the rules ofTic-Tac-Toe), the grid is initially empty, andA
will 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 on
moves
. moves
follow 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/
LeetCode All in One 題目講解彙總(持續更新中...)
微信打賞 |
Venmo 打賞 |