794.有效的井字游戏
- 题目难度:中等
- 题目链接:leetcode-cn.com/problems/va…
一、题目描述
给你一个字符串数组board表示井字游戏的棋盘。当且仅当在井字游戏过程中,棋盘有可能达到board所显示的状态时,才返回true。
井字游戏的棋盘是一个3x3数组,有字符 ,X和O组成。字符 表示一个空位。
以下是井字游戏的规则:
- 玩家轮流将字符放入空位(
)中 - 玩家1总是放字符
X,玩家2总是放字符O. X和O只允许放置在空位中,不允许对已放有字符的位置进行填充。- 当有3个相同(且非空)的字符填充任何行、列或对角线时,游戏结束。
- 当所有位置非空时,也算为游戏结束。
- 如果游戏结束,玩家不允许再放置字符。
二、大白话解释
毫不夸张的说,看见这道题的时候我是😳的~
读了不下10遍,才明白这道题到底要干嘛~
咱就是说,出题者何必呢???
好吧,没办法了。
我们先大声朗读一下题目描述,找一些关键信息:
- 井字游戏有9个位置
- 井字游戏有两个玩家:玩家1和玩家2
- 玩家1和玩家2 轮流下棋
- 玩家1只能在井字棋盘中填入
X - 玩家2只能在井字棋盘中填入
O - 玩家1先下棋
- 只能在棋盘的空位置下棋
- 游戏结束条件
- 无玩家赢但棋盘满了
- 有玩家赢了
- 游戏结束了就不能再下棋了
分析完关键信息,我们再看一下这道题到底要考什么?
这道题主要是想让你判断字符串数组board是否是合法的井字游戏。其实说白了就是:将board字符串数组组成一个完整的字符串boardStr,该字符串只包含三种类型的字符(X,O, )。玩家1和玩家2从boardStr中自己专属的字符放入井字棋盘。最后,判定board字符串数组包含的是三种类型的字符是否符合井字游戏的合法性。
那如何判定是合法的井字游戏呢?我给你大家写一下井字游戏的测试用例哈~
- 有效井字游戏
- 无人获胜情况
- 棋盘满了:玩家1 下棋次数 - 玩家2 下棋次数 = 1
- 棋盘未满:玩家1 下棋次数 = 玩家2 下棋次数
- 有人获胜情况
- 玩家1获胜 且 玩家1下棋次数 - 玩家2下棋次数 = 1
- 玩家2获胜 且 玩家1下棋次数 = 玩家2下棋次数
- 无人获胜情况
- 无效井字游戏
- 无人获胜情况
- 棋盘满了:玩家1下棋次数 - 玩家2下棋次数 != 1
- 棋盘未满:玩家1下棋次数 != 玩家2下棋次数
- 有人获胜情况
- 玩家1获胜 且 玩家1下棋次数 - 玩家2下棋次数 != 1
- 玩家2获胜 且 玩家1下棋次数 != 玩家2下棋次数
- 玩家1 和 玩家2 同时获胜
- 无人获胜情况
三、算法实现
- 计算玩家下棋次数
/**
* 计算玩家下棋次数
*/
private static int calculateChessCount(String[] board,char player){
String result = new String();
for (String str : board) {
result += str;
}
int count = 0;
for (char c : result.toCharArray()) {
if (c == player){
count += 1;
}
}
return count;
}
- 判定玩家是否赢得游戏
/**
* 判断是否有人获胜
*/
private static boolean informPlayer1WinTheGame(String[] board,char player){
```
return isRowWin(board,player) || isColumnWin(board,player) || isDiagonalWin(board,player);
}
- 判断是否是某一行相同
/**
* 判断是否是 行相同
* @return
*/
private static boolean isRowWin(String[] board,char player){
for (String str : board) {
if (str.charAt(0) == str.charAt(1) && str.charAt(0) == str.charAt(2) && str.charAt(0) == player){
return true;
}
}
return false;
}
- 判断是否是某一列相同
/**
* 判断是否是 列相同
* @return
*/
private static boolean isColumnWin(String[] board,char player){
for (int i = 0; i < board.length; i++) {
if (board[0].charAt(i) == board[1].charAt(i) && board[0].charAt(i) == board[2].charAt(i) && board[i].charAt(i) == player){
return true;
}
}
return false;
}
- 判断是否是对角线相同
/**
* 判断是否是对角线相同
* @param board
* @param player
* @return
*/
private static boolean isDiagonalWin(String[] board,char player){
boolean diagonal1Win = board[0].charAt(0) == board[1].charAt(1) && board[0].charAt(0) == board[2].charAt(2) && board[0].charAt(0) == player;
boolean diagonal2Win = board[0].charAt(2) == board[1].charAt(1) && board[0].charAt(2) == board[2].charAt(0) && board[0].charAt(2) == player;
return diagonal1Win || diagonal2Win;
}
- 判断
board中的字符串是否是有效井字游戏
private static boolean validTicTacToe(String[] board){
if (null == board){
return false;
}
//# 玩家1 下棋次数
int player1Cnt = calculateChessCount(board,'X');
//# 玩家2 下棋次数
int player2Cnt = calculateChessCount(board,'O');
//# 玩家1 获胜
boolean player1Win = informPlayer1WinTheGame(board,'X');
//# 玩家2 获胜
boolean player2Win = informPlayer1WinTheGame(board,'O');
//# 无人获胜
if (!player1Win && !player2Win){
return player1Cnt == player2Cnt || player1Cnt - player2Cnt == 1;
}
//# 不存在双方同时获胜
if (player1Win && player2Win){
return false;
}
//# 如果玩家1 获胜
if (player1Win){
return player1Cnt - player2Cnt == 1;
}
//# 如果玩家2 获胜
if (player2Win){
return player1Cnt == player2Cnt;
}
return false;
}
算法题做完了~
感谢观看~
希望能帮到有缘人!