Leetcode 第 794 题(Valid Tic-Tac-Toe State)

Leetcode 第 794 题(Valid Tic-Tac-Toe State)

A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to reach this board position during the course of a valid tic-tac-toe game.

The board is a 3 x 3 array, and consists of characters " ", "X", and "O". The ” ” character represents an empty square.

Here are the rules of Tic-Tac-Toe:

  • Players take turns placing characters into empty squares (” “).
  • The first player always places “X” characters, while the second player always places “O” characters.
  • “X” and “O” characters are always placed into empty squares, never filled ones.
  • The game ends when there are 3 of the same (non-empty) character filling any row, column, or diagonal.
  • The game also ends if all squares are non-empty.
  • No more moves can be played if the game is over.
Example 1:
Input: board = ["O  ", "   ", "   "]
Output: false
Explanation: The first player always plays "X".

Example 2:
Input: board = ["XOX", " X ", "   "]
Output: false
Explanation: Players take turns making moves.

Example 3:
Input: board = ["XXX", "   ", "OOO"]
Output: false

Example 4:
Input: board = ["XOX", "O O", "XOX"]
Output: true

这道题的难度是 Medium。其实写起来难度并不大,但是一次就写好还是挺难的。主要是各种情况都要考虑到,而且还有几种特殊情况。

我的解法是先统计 “X” 和 “O” 的数量。如果 X > O + 1 或者 X < O 那都肯定是不能出现的状态。

之后统计 “X” 和 “O” 各出现了几次获胜状态。当 X 比 O 多一个子时才能出现 X 获胜的情况。X 和 O 子相同时只能出现 O 获胜的情况。

计算子数的函数如下:

/**
 * @brief count 计算 X 和 O 各有多少个子
 * @param board
 * @param x 返回 X 的子数
 * @param o 返回 O 的子数
 */
void count (vector<string>& board, int &x, int &o)
{
    x = 0; o = 0;
    for(int i = 0; i < 3; i ++)
    {
        for(int j = 0; j < 3; j++)
        {
            char t = board[i][j];
            if(t == 'X') x++;
            if(t == 'O') o++;
        }
    }
}

计算出现了多少种获胜情况的代码如下:

void cross(vector<string>& board, int &x, int &o)
{
    x = 0; o = 0;
    char buf[4];
    buf[3] = 0;
    buf[0] = board.at(0).at(0);
    buf[1] = board.at(1).at(1);
    buf[2] = board.at(2).at(2);
    if(strcmp(buf, "XXX") == 0) x++;
    if(strcmp(buf, "OOO") == 0) o++;

    buf[0] = board.at(0).at(2);
    buf[1] = board.at(1).at(1);
    buf[2] = board.at(2).at(0);
    if(strcmp(buf, "XXX") == 0) x++;
    if(strcmp(buf, "OOO") == 0) o++;

}

void col(vector<string>& board, int &x, int &o)
{
    x = 0; o = 0;
    for(int i = 0; i < 3; i ++)
    {
        char buf[4];
        buf[3] = 0;
        buf[0] = board.at(0).at(i);
        buf[1] = board.at(1).at(i);
        buf[2] = board.at(2).at(i);
        if(strcmp(buf, "XXX") == 0) x++;
        if(strcmp(buf, "OOO") == 0) o++;
    }
}

void row(vector<string>& board, int &x, int &o)
{
    x = 0; o = 0;
    for(int i = 0; i < 3; i ++)
    {
        if(board.at(i) == "XXX") x++;
        if(board.at(i) == "OOO") o++;
    }
}

/**
 * @brief win
 * @param board
 * @param x 返回 X 有多少种获胜条件
 * @param o 返回 O 有多少种获胜条件
 */
void win(vector<string>& board, int &x, int &o)
{
    x = 0;
    o = 0;
    int x_count, o_count;
    row(board, x_count, o_count);
    x += x_count;
    o += o_count;

    col(board, x_count, o_count);
    x += x_count;
    o += o_count;

    cross(board, x_count, o_count);
    x += x_count;
    o += o_count;
}

把这几个判断合到一起就可以了。

bool validTicTacToe(vector<string>& board)
{
    int x_stone, o_stone;
    count(board, x_stone, o_stone);
    if(o_stone > x_stone) return false;
    if(x_stone > o_stone + 1)  return false;

    int x_count = 0, o_count = 0;
    win(board, x_count, o_count);

    if(x_count > 0 && x_stone == o_stone) return false;
    if(o_count > 0 && x_stone > o_stone) return false;
    return true;
}

至此这个代码就完成了。其中计算出现了多少次获胜条件的代码写的比较 Naive。还可以优化一下,大家可以试着改一改。

猜你喜欢

转载自blog.csdn.net/liyuanbhu/article/details/79594836
今日推荐