794. 有效的井字游戏
给你一个字符串数组 board 表示井字游戏的棋盘。当且仅当在井字游戏过程中,棋盘有可能达到 board 所显示的状态时,才返回 true 。
井字游戏的棋盘是一个 3 x 3 数组,由字符 ‘ ‘,’X’ 和 ‘O’ 组成。字符 ‘ ‘ 代表一个空位。
以下是井字游戏的规则:
玩家轮流将字符放入空位(’ ‘)中。
玩家 1 总是放字符 ‘X’ ,而玩家 2 总是放字符 ‘O’ 。
‘X’ 和 ‘O’ 只允许放置在空位中,不允许对已放有字符的位置进行填充。
当有 3 个相同(且非空)的字符填充任何行、列或对角线时,游戏结束。
当所有位置非空时,也算为游戏结束。
如果游戏结束,玩家不允许再放置字符。
public class Solution { int xNumber = 0; int oNumber = 0; int xLine = 0; int oLine = 0; public bool ValidTicTacToe(string[] board) { StringBuilder firstline = new StringBuilder(board[0]); StringBuilder secondline = new StringBuilder(board[1]); StringBuilder thirdline = new StringBuilder(board[2]); //最土的办法,三个StringBuilder放进来 CountNumber(firstline); CountNumber(secondline); CountNumber(thirdline); //计数,实现在下方 for(int i=0;i<3;i++) { if(firstline[i] == secondline[i] && secondline[i] == thirdline[i] && firstline[i] == 'X') { xLine++; } else if(firstline[i] == secondline[i] && secondline[i] == thirdline[i] && firstline[i] == 'O') { oLine++; } } //分别统计列成线的次数 if( (firstline[0] == secondline[1] && secondline[1] == thirdline[2] && firstline[0] == 'X') || (firstline[2] == secondline[1] && secondline[1] == thirdline[0] && firstline[2] == 'X') ) { xLine++; } else if( (firstline[0] == secondline[1] && secondline[1] == thirdline[2] && firstline[0] == 'O') || (firstline[2] == secondline[1] && secondline[1] == thirdline[0] && firstline[2] == 'O') ) { oLine++; } //分别统计对角线成线的次数 if(xNumber - oNumber < 0 || xNumber-oNumber > 1) { return false; } else if(xLine !=0) { if(xLine == oLine) { return false; } else if(xNumber - oNumber != 1) { return false; } } else if(oLine != 0) { if(xLine == oLine) { return false; } else if(xNumber - oNumber != 0) { return false; } } return true; //判断 } public void CountNumber(StringBuilder str) { if(str[0] == str[1] && str[1] == str[2] && str[0] == 'X') { xLine++; } else if(str[0] == str[1] && str[1] == str[2] && str[0] == 'O') { oLine++; } //分别统计行成线的次数 for(int i = 0;i < 3;i++) { if(str[i] == 'X') { xNumber++; } else if(str[i] == 'O') { oNumber++; } } //统计出现的次数 } }
我的思路很直接
读完题之后我想我应该要掌握四个数据:
- x出现的次数
- o出现的次数
- x成线的次数
- o成线的次数
最简单的方法就是用StringBuilder去遍历然后记录x和o出现的次数
同时手动再去验证行、列、对角线上连成线的可能
x和o分开判断
最后就是最关键的一步
你要如何才能知道这个3*3的图是不是符合条件的图
也就是什么时候返回false什么时候返回true的问题
第一层:先分为有人胜利的情况和没人胜利的情况
没人胜利的情况:
因为x先手,所以x必定要和o的个数相等,或者最多只能比o多一个
而且x出现的次数必须大于等于0,换言之,如果x的值为0那么o的值也必须为0
所以这里的判定条件很直接,x-o小于0或者x-o大于1就返回false
有人胜利的情况:
第二层:x胜利了和o胜利了两种情况
x胜利的情况:
x赢了那自然o不能赢,所以x成线的次数一定不和o相等,相等就说明o也赢了
这自然是不可能的
同时x赢的时候一定会比0多一个,因为x是先手,先手赢o就不能落子了
所以o一定会比x少一个
y胜利的情况:
和x类似,o成线的次数不能和x相等
同时o赢得时候一定是和x的个数相等的,因为x先手