如何在C#数组中的相同背景色的行中确定5个标签? [英] How to determine 5 labels in a row of the same backcolor in a C# array?

查看:77
本文介绍了如何在C#数组中的相同背景色的行中确定5个标签?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了标签的二维数组[19,19].单击时,用户会根据迭代将标签的颜色更改为黑色或白色.当水平排列五个相同颜色的标签时,我希望弹出一个消息框.无需递归即可完成此操作.任何帮助将不胜感激.

I created a two dimensional array [19,19] of labels. On click a user changes the color of a label to either black or white depending on the iteration. I want a message box to pop up when there are five labels of the same color lined up horizontally. This is to be done without recursion. Any help would be much appreciated.

public partial class Form1 : Form
{
int labelCount = 0;
        int iteration = 0;
        public Label[,] board = new Label[19,19];
        const int WinLength = 5;
        const int BoardWidth = 19;
        const int BoardHeight = 19;
        gamePlay obj = new gamePlay();
    public Form1()
    {
        InitializeComponent();
}

private void labelClick (object sender, EventArgs e)
{
Label x = (Label)sender;

            if (x.BackColor == Color.Transparent)
            {
                if (iteration % 2 == 0)
                {
                    x.BackColor = Color.Black;
                }
                else
                {
                    x.BackColor = Color.White;
                }
                iteration++;
            }
            else
            {

            }

            for (int r = 0; r < BoardHeight; r++)
            {
                for (int c = 0; c < BoardWidth; c++)
                {
                    if (board[r, c] == x)
                    {
                        Color? winner = obj.CheckForWinner(board, r, c);
                        if (winner == Color.Black)
                        {
                            MessageBox.Show("Black is the winner!");
                        }
                        else if (winner == Color.White)
                        {
                            MessageBox.Show("White is the winner!");
                        }
                        // else winner is null, meaning no winner yet. 
                    }
                }
            }

        private int[] FindClickedLabelCoordinates(Label[,] board, Label label)
        {
            for (int r = 0; r < BoardHeight; r++)
            {
                for (int c = 0; c < BoardWidth; c++)
                {
                    if (board[r, c] == label)
                        return new int[] { r, c };
                }
            }
            return null;
        }
}


    class gamePlay
{
        const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;

    private Color? CheckForWinner(Label[,] board, int r, int c)
    {
        Color startColor = board[r, c].BackColor;
        for (int c1 = c - WinLength + 1; c1 <= c; c1++)
        {
            if (c1 >= 0 && c1 < BoardWidth && board[r, c1].BackColor == startColor)
            {
                MessageBox.Show("you win!");
                bool win = true;
                for (int c2 = c1 + 1; c2 < c1 + WinLength; c2++)
                {
                    if (c2 < 0 || c2 >= BoardWidth || board[r, c2].BackColor != startColor)
                    {
                        win = false;
                        break;
                    }
                }
                if (win)
                {

                    return startColor;
                }

            }
        }
        return null;
    }

推荐答案

您实际上不需要递归即可解决此问题;只是几个嵌套循环.既然您说过您只是想从横向赢球入手,那么我将从这里开始.我将使用石头"一词来表示板上已被单击以将其变为黑色或白色的空间.

You actually don't need recursion to solve this; just a couple of nested loops. Since you said you wanted to start just by checking for horizontal wins, I'll start there. I'll use the term "stone" to represent a space on the board that has been clicked to turn it black or white.

如果板上没有石头,我们知道没有胜利的存在.这是游戏的默认状态.仅当将5个相同颜色的宝石放在棋盘上时,胜利才会出现.而且由于一次只能放置一块石头,并且我们将在每次放置之后检查获胜情况,因此最后放置的石头必须是获胜动作的一部分,并且获胜颜色必须是该宝石的颜色.听起来很明显,但这意味着不必每次都检查整个棋盘是否有获胜.我们只需要检查可能涉及到最后一块石头的获胜情况即可.此外,我们不需要分别检查它们是黑色还是白色.我们只需要检查它们是否与上一个动作的颜色相同,无论使用哪种颜色即可.

If there are no stones on the board, we know there is not a win present. That is the default state of the game. A win can only be present once 5 stones of the same color are placed on the board. And since only one stone is placed at a time, and we will be checking for wins after each placement, then the last stone placed must be part of the winning move, and the winning color must be the color of that stone. It sounds obvious, but it means that it is not necessary to check the entire board for a win each time. We only need to check the possible wins that could involve the last stone placed. Furthermore, we don't need to check separately that they are all black or all white; we just need to check that they are all the same color as the last move, whatever color that was.

因此,如果唯一可能的获胜条件是水平,那么我们需要检查哪些正方形?好吧,假设最后一块石头位于行的正中央.我们将该正方形称为x.如果石头是赢的一部分,并且连续赢了5个,那么有5个可能的赢可能是石头的一部分:

So, if the only possible win conditions are horizontal, what squares do we need to check? Well, let's say that the last stone placed was in the very center of a row. Let's call that square x. If the stone was part of a win, and a win is 5 in a row, then there are 5 possible wins that stone could be part of:

  • {x-4, x-3, x-2, x-1, x}
  • {x-3, x-2, x-1, x, x+1}
  • {x-2, x-1, x, x+1, x+2}
  • {x-1, x, x+1, x+2, x+3}
  • {x, x+1, x+2, x+3, x+4}
  • {x-4, x-3, x-2, x-1, x}
  • {x-3, x-2, x-1, x, x+1}
  • {x-2, x-1, x, x+1, x+2}
  • {x-1, x, x+1, x+2, x+3}
  • {x, x+1, x+2, x+3, x+4}

因此,这建议一种算法:

So, that suggests an algorithm:

  1. 获取放置在板上的最后一块石头的行和列.
  2. 获得那块石头的颜色.
  3. 对于5个可能的获胜序列中的每一个:
    a)从序列的最左板空间开始(例如,第一个的x-4)
    b)检查并确认其右边接下来的4个木板空间包含与步骤2中的颜色相同颜色的宝石.
    c)如果序列中的任何空格都没有匹配步骤2的颜色的石头,则不是胜利;我们可以停止检查并立即进入下一个可能的获胜顺序.
    d)如果我们在整个序列中都做到这一点,并且所有空间都有正确颜色的宝石,那么这就是胜利,我们可以退还获胜的颜色.
  4. 如果我们在所有可能的顺序中都没有找到获胜的机会,那么比赛将继续.
  1. Get the row and column of the last stone placed on the board.
  2. Get the color of that stone.
  3. For each of the 5 possible win sequences:
    a) Start at the leftmost board space of the sequence (e.g. x-4 for the first one)
    b) Check that it and the next 4 board spaces to the right of it contain stones of the same color as the color from step 2.
    c) If any space in the sequence does not have a stone matching the color from step 2, it's not a win; we can stop checking and immediately move onto the next possible win sequence.
    d) If we make it through the whole sequence and all the spaces have stones of the correct color, then it's a win and we can return the winning color.
  4. If we go through all possible sequences without finding a win, then the game continues.

但是,还有另外一件事要考虑.如果最后一块石头放在板子的左边缘或右边缘附近怎么办?例如,如果x为2,则分别以x-4x-3开头的前两个可能的获胜序列是无效的,因为它们不在一定范围内!因此,我们需要添加一些检查以确保我们要查看的空间实际上在边界内.

But, there's one more thing to consider. What if the last stone was placed near the left or right edge of the board? For example, if x is 2, then the first two possible win sequences, starting with x-4 and x-3, respectively, are invalid because they are partially off the board! So we'll need to add some checks to make sure that the spaces we want to look at are actually in bounds.

这是上面的算法在代码中的样子. rc参数是最后放置的石头的行和列:

Here is what the above algorithm might look like in code. The r and c parameters are the row and column of the last stone placed:

const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;

private Color? CheckForWinner(Label[,] board, int r, int c)
{
    Color startColor = board[r, c].BackColor;
    for (int c1 = c - WinLength + 1; c1 <= c; c1++)
    {
        if (c1 >= 0 && c1 < BoardWidth && board[r, c1].BackColor == startColor)
        {
            bool win = true;
            for (int c2 = c1 + 1; c2 < c1 + WinLength; c2++)
            {
                if (c2 < 0 || c2 >= BoardWidth || board[r, c2].BackColor != startColor)
                {
                    win = false;
                    break;
                }
            }
            if (win) return startColor;
        }
    }
    return null;
}

这是从点击处理程序中调用上述方法的方式:

Here is how you might call the above method from your click handler:

private void labelClick(object sender, EventArgs e)
{
    // set background color of clicked label here based on whose turn it is

    int[] coords = FindClickedLabelCoordinates(board, (Label)sender);

    Color? winner = CheckForWinner(board, coords[0], coords[1]);
    if (winner == Color.Black)
    {
        MessageBox.Show("Black is the winner!");
    }
    else if (winner == Color.White)
    {
        MessageBox.Show("White is the winner!");
    }
    // else winner is null, meaning no winner yet.

}

private int[] FindClickedLabelCoordinates(Label[,] board, Label label)
{
    for (int r = 0; r < BoardHeight; r++)
    {
        for (int c = 0; c < BoardWidth; c++)
        {
            if (board[r, c] == label)
                return new int[] { r, c };
        }
    }
    return null;
}

希望这足以帮助您入门.

Hopefully that is enough to get you started.

这篇关于如何在C#数组中的相同背景色的行中确定5个标签?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆