每日一题——794. 有效的井字游戏

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先手

发表评论

您的电子邮箱地址不会被公开。