力扣-有效的井字游戏

ohye / 2023-08-06 / 原文

1.问题描述

用字符串数组作为井字游戏的游戏板 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

2.说明:

游戏板 board 是长度为 3 的字符串数组,其中每个字符串 board[i] 的长度为 3。

 board[i][j] 是集合 {" ", "X", "O"} 中的一个字符。

输入说明:输入三行,每行三个字符,每个字符都属于集合 {" ", "X", "O"} 

输出说明:输出结果:true或false

3.范例

输入:

XOX
O O
XOX

输出:

true

4.思路

根据象棋规则,第一个玩家总是放“X”,第二个玩家总是放“O”,因此游戏中的"X"数量一定大于等于"O"的数量;且不能存在两个获胜者,因此不可能出现3个“X”在同一行/列和3个“O”在同一行/列,因此若第一个玩家获胜,则一定是“X”数量比“O”数量多1个,而若第二玩家获胜,则“X”数量一定等于“O”的数量。

因此,在合法的象棋游戏上,只有三种结果:没有任何玩家获胜,第一玩家获胜,第二玩家获胜,可以通过检测两个玩家象棋数检验是否有效,同时需要检验两个玩家同时获胜的非法情况。

5.代码

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
using namespace std;
class Solution
{
public:
    bool validTicTacToe(vector<string> &board)
    {
        int xcount=0,ocount=0;
        for(string &row:board)
            for(char c:row)
            {
                xcount = (c=='X')? (xcount+1):xcount;
                ocount = (c=='O')? (ocount+1):ocount;
            }
        return !((ocount!=xcount&&ocount!=xcount - 1)||//先放x,后放o,则x数量一定>o数量,符合规则的话,一定xcount-1==ocount
                 (ocount!=xcount-1&&win(board,'X'))||//若x赢,则ocount一定==xcount-1
                 (ocount!=xcount&&win(board,'O')));//若o赢,则ocount一定==xcount
    }
    bool win(vector<string> &board,char c)
    {
        for(int i=0;i<3;++i)
        {
            if((c==board[i][0]&&c==board[i][1]&&c==board[i][2])||  //
               (c==board[0][i]&&c==board[1][i]&&c==board[2][i]))   //
                return true;
        }
        return ((c==board[0][0]&&c==board[1][1]&&c==board[2][2])||//斜对角
                (c==board[0][2]&&c==board[1][1]&&c==board[2][0]));
    }
};
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    vector<string> board;
    string aRow;
    for(int i=0; i<3; i++)
    {
        getline(cin,aRow);
        board.push_back(aRow);
    }
    bool res=Solution().validTicTacToe(board);
    cout<<(res?"true":"false")<<endl;
    return 0;
}