用字符串数组作为井字游戏的游戏板 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"}
中的一个字符。
思路:
- 统计X和O的个数
- 保证最多只有一个玩家赢
- 如果X或者O赢,保证对应的个数(O或者X)是对的
- 如果X或者O都没有赢,那么保证X或者O的个数统计是对的
参考代码:
class Solution {
public:
bool validTicTacToe(vector<string>& board) {
int x_count = cnt(board, 'X'), o_count = cnt(board, 'O');
bool x_win = win(board, 'X'), o_win = win(board,'O');
if (x_win && o_win) return false;
if (x_win) return x_count == (o_count + 1);
if (o_win) return x_count == o_count;
return x_count == (o_count + 1) || x_count == o_count;
}
private:
int cnt(vector<string>& board, char ch) {
int res = 0;
for (auto &bo : board) res += count(bo.begin(), bo.end(), ch);
return res;
}
bool win(vector<string>& board, char ch) {
for (int i = 0; i < 3; i++) {
if (board[0][i] ==ch && board[1][i] ==ch && board[2][i] == ch) return true;
}
for (int i = 0; i < 3; i++) {
if (board[i][0] ==ch && board[i][1] ==ch && board[i][2] == ch) return true;
}
if (board[0][0] ==ch && board[1][1] ==ch && board[2][2] == ch) return true;
if (board[2][0] ==ch && board[1][1] ==ch && board[0][2] == ch) return true;
return false;
}
};