1

所以这是交易,我正在尝试比较本地资源中的图像XO,如果它们在winCondition数组中相同,则向他们获胜的用户发送消息。

我发现的问题b1.Image是没有给我适当的比较。这是比较的:

+  b1.Image  {System.Drawing.Bitmap}  System.Drawing.Image  {System.Drawing.Bitmap}

当我希望它改为比较图像名称时。

其中一个问题是,什么时候turnNumber = 5,它说我赢了,而我没有。我相信这是由于b1.Image problem. 一旦我单击另一个方块,它就会再次检查是否获胜。

我想在游戏完成后禁用按钮,但是我不知道该怎么做。

会不会很简单:

   foreach (Button btnEnabled in buttonArray)
   {
       btnEnabled.Enabled = false;
   }

这是代码,再次感谢您的帮助。我已经为此苦苦挣扎了几天。

namespace BGreinAssignment2
{
    public partial class frmTicTacToe : Form
    {
        //Global variables
        private bool player1Turn = false;
        private bool player2Turn = true;

        private int[,] winCondition = 
        {
            {0,1,2}, //Horizontal top
            {3,4,5}, //Horizontal Middle
            {6,7,8}, //Horizontal Bottom
            {0,3,6}, //Vertical Left
            {1,4,7}, //Vertical Middle
            {2,5,8}, //Vertical Right
            {0,4,8}, //Diagonal Top Left to Bottom Right or Vice-Versa
            {2,4,6}  //Diagonal Top Right to Bottom Left or Vice-Versa
        };
        private Button[] buttonArray;
        private int turnNumber = 0;

        public frmTicTacToe()
        {
            InitializeComponent();
        }

        //Creates the button array for checks and sets X to go first.
        private void frmTicTacToe_Load(object sender, EventArgs e)
        {
            //Creates button array for checking if image is there/check for beginning of game
            buttonArray = new Button[9] {btnTopLeft, btnTopMid, btnTopRight, btnMidLeft, btnMid, btnMidRight, btnBotLeft, btnBotMid, btnBotRight};

            //Sets player 1 to go first to satisfy the "X always goes first"
            player1Turn = true;
            player2Turn = false;
        }

        /// <summary>
        /// Checks the buttons if the images don't create a win condition through the winCheck method,
        /// displays message box to user with "Draw!" break is included so it doesn't say "Draw!" for each button it checks.
        /// </summary>
        private void drawCheck()
        {
            foreach (Button checkDraw in buttonArray)
            {
                if (checkDraw.Image != null)
                {
                    MessageBox.Show("Draw!");
                    break;
                }
            }
        }

        /// <summary>
        /// Checks the win condition to see if the images are the same. If they are, it will show a message box with the winner.
        /// </summary>
        /// <param name="btnChecks">Creates an array to check the button images</param>
        /// <returns>If there is a winner, returns true and shows message box</returns>
        private bool winCheck(Button[] btnChecks)
        {
            bool win = false;
            for (int i = 0; i < 8; i++)
            {
                int a = winCondition[i, 0], b = winCondition[i, 1], c = winCondition[i, 2];

                Button b1 = btnChecks[a], b2 = btnChecks[b], b3 = btnChecks[c];

                if (b1.Image == null || b2.Image == null || b3.Image == null)
                {
                    continue;
                }

                if (b1.Image == b2.Image && b2.Image == b3.Image)
                {
                    win = true;
                    MessageBox.Show("Game over. " + b1.Image + " Wins!");
                }
            }
            return win;
        }

        //If player chooses top left square
        private void btnTopLeft_Click(object sender, EventArgs e)
        {
            if (btnTopLeft.Image == null)
            {
                if (player1Turn == true)
                {
                    if (turnNumber == 0)
                    {
                        btnTopLeft.Image = BGreinAssignment2.Properties.Resources.tic_tac_toe_X;
                        player1Turn = false;
                        player2Turn = true;
                        turnNumber++;
                    }
                    else
                    {
                        btnTopLeft.Image = BGreinAssignment2.Properties.Resources.tic_tac_toe_X;
                        player1Turn = false;
                        player2Turn = true;
                        turnNumber++;
                        if (turnNumber >= 5)
                        {
                            winCheck(buttonArray);
                        }
                        if (turnNumber == 9)
                        {
                            drawCheck();
                        }
                    }
                }
                else
                {
                    btnTopLeft.Image = BGreinAssignment2.Properties.Resources.tic_tac_toe_O;
                    player1Turn = true;
                    player2Turn = false;
                    turnNumber++;
                    if (turnNumber <= 5)
                    {
                        winCheck(buttonArray);
                    }
                    if (turnNumber == 9)
                    {
                        drawCheck();
                    }
                }
            }
            else
            {
                MessageBox.Show("This space has already been selected");
            }
        }

        //Excluded rest of code (just button clicks, repeats of same for 9 squares)

        /// <summary>
        /// Resets the game for the player.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPlayAgain_Click(object sender, EventArgs e)
        {
            //For each button, set image to null then reset turn counter and set turn to player 1.
            foreach (Button btnSpaces in buttonArray)
            {
                btnSpaces.Image = null;
            }
            turnNumber = 0;
            player1Turn = true;
            player2Turn = false;
        }
    }
}
4

1 回答 1

1

正如您所发现的,Image直接比较 s 不是答案。我没有对此进行测试,但我怀疑这是因为每个图像可能具有非常不同的属性,尽管是从相同的资源加载的。例如,如果一个按钮只有 20 像素正方形,而另一个是 50 像素,则HeightWidth属性将不同。有关其他一些属性,请参阅文档

正如@John3136 所说,处理此问题的更好方法是将模型与绘图分开。这可以像使用Tag每个按钮上的属性来存储“O”或“X”一样简单。您将像现在一样检查所有内容,除了您要比较b1.Tag == b2.Tag && b2.Tag == b3.Tag. 一个更好但更复杂的方法是有一系列的东西来代表你的游戏板。与任何编程问题一样,有很多可能的方法可以做到这一点——char[9]虽然string[]或者bool?[]可以工作,但最简单的方法是创建一个枚举并存储它的数组,或者上述任何数组的数组。(还List<>而不是一个数组,最终)。在任何一种情况下,您都必须在更新图像的同时更新模型,但随后您将进行更简单的比较来测试胜利。


关于禁用按钮,您是完全正确的 - 但这里有一个问题要问您。如果有人点击了另一个玩家已经点击的按钮,会发生什么?当然,您可以提醒用户,但它看起来仍然是一个有效的选择。为什么不一点击就禁用它呢?


我还打算走得更远一点,给你一个关于“ //Excluded rest of code (just button clicks, repeats of same for 9 squares)”行的提示。如果你要重复相同的代码两次以上(有些人会说不止一次),你最好创建一个函数,它将任何能区分它的东西作为参数。例如,你可以有

    //If player chooses top left square
    private void btnTopLeft_Click(object sender, EventArgs e)
    {
        DoClick(btnTopLeft);
    }

    //If player chooses top center square
    private void ptnTopCenter_CLick(object sender, EventArgs e)
    {
        DoClick(btnTopCenter);
    }

    private void DoClick(Button button)
    {
      // Manipulate button appropriately
    }

这并没有做任何您不知道如何做的事情 - 您已经在调用其他函数,并在参数中传递按钮(请参阅 参考资料winCheck())。这只是一种思维方式,可以减少您需要编写的代码量,从而减少您需要修复任何给定错误的地方。

于 2012-10-04T02:23:46.693 回答