LeetCode-794 有效的井字遊戲
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/valid-tic-tac-toe-state
題目描述
用字串陣列作為井字遊戲的遊戲板board。當且僅當在井字遊戲過程中,玩家有可能將字元放置成遊戲板所顯示的狀態時,才返回 true。
該遊戲板是一個 3 x 3 陣列,由字元" ","X"和"O"組成。字元" "代表一個空位。
以下是井字遊戲的規則:
玩家輪流將字元放入空位(" ")中。
第一個玩家總是放字元 “X”,且第二個玩家總是放字元 “O”。
“X” 和 “O” 只允許放置在空位中,不允許對已放有字元的位置進行填充。
當有 3 個相同(且非空)的字元填充任何行、列或對角線時,遊戲結束。
當所有位置非空時,也算為遊戲結束。
如果遊戲結束,玩家不允許再放置字元。
示例 1:
輸入: board = ["O ", " ", " "]
輸出: false
解釋: 第一個玩家總是放置“X”。
示例 2:
輸入: board = ["XOX", " X ", " "]
輸出: false
解釋: 玩家應該是輪流放置的。
示例 3:
輸入: board = ["XXX", " ", "OOO"]
輸出: false
示例 4:
輸入: board = ["XOX", "O O", "XOX"]
輸出: true
說明:
遊戲板board是長度為 3 的字串陣列,其中每個字串board[i]的長度為3。
board[i][j]是集合{" ", "X", "O"}中的一個字元。
解題思路
先說結論,這不是一道好題,像是為了出題而出題,就是為了分類的思想專門出的題
看到題目的時候,我是蒙的,感覺這不是一道演算法題,僅僅是一個需求。根據題幹可以提取的資訊是
1、X的個數永遠是等於O或者比O個個數多1
2、有且僅有一個人能夠獲勝
第一個條件還好,只要統計O和X的個數便可以取得結果。
第二個條件最初的想法是隻要三橫三豎兩斜這八條線最多僅有一個三連就好了,但是我遇到了這麼一個列子:
XXX
OOX
OOX
那麼是不是橫行豎行斜行分別僅可以有一個三連就好了合法了吶?我又遇到了這麼一個例子
XXX
XOO
OO
還有這樣的例子
OXX
XOX
OXO
直到這個時候,我才意識到我的思路可能出現了偏差,我忽略了一個隱藏的條件,重新提取題幹條件如下:
1、X的個數永遠是等於O或者比O個個數多1
2、如果X贏,那麼X應該比O多1,如果O贏,那麼O和X的數目相等
為了檢測方便,我首先建立了一個二維int陣列,將棋盤的資料存成更好處理的形式,1代表X,0代表空,-1代表了O,順便在這個過程統計了X和O的個數,判斷條件1。下一步,我分別對三橫三豎和兩斜進行了求和,藉助之前取得的X和O的數量資訊,判斷條件2.
原始碼展示
class Solution { public: bool validTicTacToe(vector<string>& board) { vector<vector<int>> vviBoard; vviBoard.resize(3); for(int i = 0; i < 3; i++) { vviBoard[i].resize(3); } int iSumX = 0, iSumO = 0; for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { if(board[i].at(j) == 'X') { vviBoard[i][j] = 1; iSumX++; } else if(board[i].at(j) == 'O') { vviBoard[i][j] = -1; iSumO++; } else { vviBoard[i][j] = 0; } } } int iResult = 0; if(iSumX - iSumO == 0) { iResult = -3; } else if(iSumX - iSumO == 1) { iResult = 3; } else { return false; } int aiSum[8] = { 0 }; for(int i = 0; i< 3; i++) { for(int j = 0; j< 3; j++) { aiSum[i] += vviBoard[i][j]; aiSum[i + 3] += vviBoard[j][i]; } aiSum[6] += vviBoard[i][i]; aiSum[7] += vviBoard[i][2 - i]; } for(int i=0; i<8; i++) { if(aiSum[i] == -iResult) return false; } return true; } };
執行結果