【问题标题】:Tic Tac Toe - Detecting win, lose, or drawTic Tac Toe - 检测输赢或平局
【发布时间】:2013-02-22 09:58:33
【问题描述】:

这是一个井字游戏发生器。仅计算机与计算机,与通常的播放器与计算机略有不同。我的大部分代码都是为此编写的,但我遇到的问题是有时当我生成游戏时,整个棋盘都填满了,会有一行 X 和一行 O,它会作为平局出现.有时会生成两行X或两行O,并且游戏不会在第一行连续3个之后停止……有什么见解吗?谢谢。

namespace TicTacToe
{
    public partial class Form1 : Form
    {
        private Random rn = new Random();

        const int SIZE = 9;
        char[] cell = new char[SIZE];
        char firstPlayer = ' ', secondPlayer = ' ';

        private void button1_Click(object sender, EventArgs e)
        {
            //Clear the labels and starting values

            for (int i = 0; i < SIZE; i++)
            {
                cell[i] = ' ';
            }
            label10.Text = "";

            //Pick X or O to go first
            switch (rn.Next(2))
            {
                case 0: firstPlayer = 'O'; secondPlayer = 'X'; break;
                case 1: firstPlayer = 'X'; secondPlayer = 'O'; break;
            }

            //Get five non-repeating numbers from 0 to 8
            int[] positions = new int[5];
            positions[0] = rn.Next(9);
            for (int i = 1; i < 5; i++)
            {
                int temp = rn.Next(9);
                for (int j = 0; j < i; j++)
                {
                    if (temp == positions[j])
                    {
                        i--;
                        break;
                    }
                    else
                    {
                        positions[i] = temp;
                    }
                }
            }

            //Set each position found to have first players letter
            for (int i = 0; i < 5; i++)
            {
                cell[positions[i]] = firstPlayer;
            }

            for (int i = 0; i < SIZE; i++)
            {
                if (cell[i] != firstPlayer)
                {
                    cell[i] = secondPlayer;
                }
            }
            //Place cell values into the labels
            label1.Text = cell[0].ToString();
            label2.Text = cell[1].ToString();
            label3.Text = cell[2].ToString();
            label4.Text = cell[3].ToString();
            label5.Text = cell[4].ToString();
            label6.Text = cell[5].ToString();
            label7.Text = cell[6].ToString();
            label8.Text = cell[7].ToString();
            label9.Text = cell[8].ToString();

            //Check for a winner
            switch(checkWinner())
            {
                case 'T' : label10.Text = "It's a tie!"; break;
                case 'O' : label10.Text = "O Wins!"; break;
                case 'X' : label10.Text = "X Wins!"; break;
                default: label10.Text = "This will never appear"; break;
            }
        }

        private char checkWinner()
        {
            //return either 'T' for tie, 'O' for O wins, and 'X' for X wins
            char winner = ' ';
            int winning_line = 0;
            //check for a row win
            if(cell[0].Equals(cell[1]) && cell[0].Equals(cell[2]))
            {
                winning_line++;
                winner = cell[0];
            }
            if (cell[3].Equals(cell[4]) && cell[3].Equals(cell[5]))
            {
                winning_line++;
                winner = cell[3];
            }
            if (cell[6].Equals(cell[7]) && cell[6].Equals(cell[8]))
            {
                winning_line++;
                winner = cell[6];
            }

            //check for column wins
            if (cell[0].Equals(cell[3]) && cell[0].Equals(cell[6]))
            {
                winning_line++;
                winner = cell[0];
            }
            if (cell[1].Equals(cell[4]) && cell[1].Equals(cell[7]))
            {
                winning_line++;
                winner = cell[1];
            }
            if (cell[2].Equals(cell[5]) && cell[2].Equals(cell[8]))
            {
                winning_line++;
                winner = cell[2];
            }
            //check for diagonal winner
            if (cell[0].Equals(cell[4]) && cell[0].Equals(cell[8]))
            {
                winning_line++;
                winner = cell[0];
            }
            if (cell[2].Equals(cell[4]) && cell[2].Equals(cell[8]))
            {
                winning_line++;
                winner = cell[2];
            }

            if (winning_line == 0 || winning_line > 1)
            winner = 'T';

            return winner;
        }

        public int i { get; set; }
    }
}

【问题讨论】:

  • 你的对角线有一个错误,你正在检查0 == 4 == 8,还有2 == 4 == 8(instead of 6)
  • 如果您想锻炼,我会考虑尝试将您的所有游戏逻辑与您的 UI 分开。您可以为游戏本身、玩家、每个获胜规则等创建类。然后您可以更轻松地使用 AI 和其他东西。不过只是一个建议......
  • 如果可以的话,我会投票赞成乔博的评论。如果你创建一个处理游戏的类,你可以把它放在不同的 UI 中,例如一种用于计算机与计算机,或者另一种用于播放器与播放器或播放器与计算机。

标签: c# arrays tic-tac-toe


【解决方案1】:
if (winning_line == 0 || winning_line > 1)

如果有两条线,它将 r 端口平局。如果你想在划线时停下来,你需要在每一步之后检查赢家,而不是在整个棋盘都填满之后。

【讨论】:

  • 是的,如果您每次放置符号时都检查,您只需检查最后放置符号的行。
  • @SteveP - 我对此很陌生,因为这是我正在阅读的书推荐的初学者练习。如果您能进一步帮助我理解每条语句后的检查,将不胜感激。我明白你在说什么,只是在将它们放在一起时遇到问题......谢谢。
  • 基本上,要模拟一个真实的游戏,您需要获取当前位置,将玩家移动应用到该位置,然后检查该移动是否赢得了游戏。您可以优化获胜检查,因为任何获胜行都必须包含刚刚进行的移动。
  • 我已经盯着这个看了好几个小时了,很伤心,我知道。我放弃了。
【解决方案2】:

第二个对角线获胜者检查应该是 6 而不是 8。

您当前正在检查:
X O O
O X O
O O X

和:
O O X
O X O
O O X

显然最后一个 x 应该在左边。

另外,正如其他人发布的那样。制作两条线不应导致平局。一个玩家甚至可以单独制作两条线,导致平局。
更改函数以在找到获胜行时立即返回结果,并在每次移动后检查。

【讨论】:

    【解决方案3】:

    这行得通:你需要摆脱...

    如果(获胜线 == 0 || 获胜线 > 1)

    用这三段代码替换那行代码:

        if (winnerX == " X ")
        {
            theWinner = winnerX;
        }
        if (winnerO == " O ")
        {
            theWinner = winnerO;
        }
        if(winnerX == " X " && winnerO == " O ")
        {
            winnerT = " T ";
            theWinner = winnerT;
        }
    

    所以我所做的是改变了几件事。我没有使用“winning_line++;”一点代码。 相反,我为每个 if 语句检查做了类似的事情。

        if (cell[2, 0].Equals(cell[1, 1]) && cell[2, 0].Equals(cell[0, 2]))
            {
                if (cell[2, 0] == 0)
                {
                    winnerX = " X ";
                }
    
                else if (cell[2, 0] == 1)
                {
                    winnerO = " O ";
                }
            }
    

    所以我有 4 个字符串正在使用,一个用于跟踪 X 是否有获胜线,对于 O 也是如此。然后我有一个获胜者字符串来跟踪平局。它仅用于代替您的旧领带检查 if 语句的位置。

    如果您决定使用字符串而不是整数,也需要更改您的 switch 语句,即

        switch (checkWinner())
            {
                case " X ": 
                    textBox1.Text = "X Wins!";
                    break;
                case " O ":
                    textBox1.Text = "O Wins!";
                    break;
                case " T ": 
                    textBox1.Text = "It's a tie!";
                    break;
            }
    

    【讨论】:

      【解决方案4】:

      你好,你应该有一个函数,给定一个网格和一个新棋子,告诉你游戏是否结束。 那么如果游戏结束了,你就知道最后一个棋子是赢家。

      我认为 Marthyi 的开源项目 MikMak 有一个完美的实现,请参阅

      bool IsFinished(Grid currentState, Pawn newPawn)
      

      在:

      https://github.com/Marthyi/MikMak/blob/master/MikMakSolution/Morpion/MorpionManager.cs

      祝你好运!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-28
        • 1970-01-01
        • 2013-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多