5

这是游戏板,只是为了让您了解它的外观(此板将扩展为 7x6)

我想要做的是在考虑到对角线连击的情况下,当 2 种颜色连续出现类似于游戏“连接四”时检测出获胜者。但是我想在不使用蛮力枚举的情况下做到这一点..

这是我制作的程序背后的代码我不是在寻求解决方案我只需要一些关于有效算法的帮助

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        private Button[] btns;
        private Button[] btns2;

        public Form1()
        {
            InitializeComponent();

            btns = new Button[] { button2, button3 };
            btns2 = new Button[] { button4, button5 };


        }

        private void Form1_Load(object sender, EventArgs e)
        {

            foreach (var btn in btns)
            {
                btn.Enabled = false;
                btn.BackColor = Color.LightCyan;
            }

            foreach (var btn in btns2)
            {
                btn.Enabled = false;
                btn.BackColor = Color.LightCyan;
            }
        }
        public int state;
        int cc = 0;
        private void button1_Click(object sender, EventArgs e)
        {
            foreach (var btn in btns)
            {
                  {
                    if (!btn.Enabled)
                    {
                        btn.Enabled = true;

                        if (cc == 0)
                        {
                            cc = 1;
                            btn.BackColor = Color.Red;
                        }
                        else
                        {
                            cc = 0;
                            btn.BackColor = Color.Yellow;
                        }
                        return;
                    }

                }
            }       
        }

        private void button6_Click(object sender, EventArgs e)
        {
            foreach (var btn in btns2)
            {
                if (!btn.Enabled)
                {
                    btn.Enabled = true;

                    if (cc == 0)
                    {
                        cc = 1;
                        btn.BackColor = Color.Red;
                    }
                    else
                    {
                        cc = 0;
                        btn.BackColor = Color.Yellow;

                    }

                    return;
                }
            }
        }
    }
}
4

2 回答 2

10

首先,为了效率和理智,我会将板子的状态保持在二维数组中。

其次,为了检测获胜状态,假设您以(大概)空棋盘开始游戏,您只能在按钮更改状态时进入获胜状态。如果按钮更改状态使您进入获胜状态,则该按钮必须参与该获胜状态(即它必须是您行的一部分)。

所以......你不需要蛮力整个董事会。您只需要确定刚刚更改状态的按钮是否是一行的一部分。换句话说,只查看上方、下方、左侧和右侧的按钮(也许是对角线,如果您包括对角线,您的问题就不清楚),看看它们是否与您更改的颜色相同. 如果其中任何一个是,那么这是一个胜利状态。这就是使用 2D 阵列将使您的生活更轻松的地方。如果( x , y )处的按钮发生变化,则只需检查 ( x-1 , y )、( x+1 , y )、( x , y-1 ) 和 ( x , y+1),(可能还有对角线)当然要确保进行适当的边界检查。

将其扩展到连续 3 个、4 个或更多并不困难,除非您需要记住您可能位于一排的中间而不是一端或另一端。

连续 2 个未优化的伪代码(注意,我已切换到指南针点以避免左上、右上等,因为我觉得它有点笨拙):

// cell is the cell that last changes, it has an x and y property and a color property
// board is a member variable, a 2D array of cells. Note [0,0] is the upper-left (NW) corner of the board.
// boardHeight and boardWidth are member variable with the dimensions of the board
// board[boardWidth-1, boardHeight-1] is the lower-right (SE) corner of the board
// returns true for a win, false otherwise
function checkWin(cell) returns bool {
    // check west
    if (cell.x > 0 && board[cell.x - 1, cell.y].color == cell.color)
        return true;
    // check northwest
    if (cell.x > 0 && cell.y > 0 && board[cell.x-1, cell.y-1].color == cell.color)
        return true;
    // check north
    if (cell.y > 0 && board[cell.x, cell.y-1].color == cell.color)
        return true;
    // check northeast
    if (cell.y > 0 && cell.x < boardWidth && board[cell.x+1, cell.y-1].color == cell.color)
        return true;
    // checking the other directions is left as an exercise for the reader, hopefully you get the point
    return false;
}

如果你做的不止2个,我会考虑一个递归函数来计算左、右、上、下和诊断的匹配单元格的数量

// k is the number of cells in a row for a win
function checkWin(cell) returns bool {
    // check west / east
    int count = checkWest(cell);
    if (count > k)
         return true;
    count += checkEast(cell);
    if (count > k)
         return true;
    // check nw / se
    count = checkNW(cell);
    if (count > k)
         return true;
    count += checkSE(cell);
    if (count > k)
         return true;
    // and so on, checking N/S and NE/SW
    return false;
}

function checkWest(cell) returns int {
    // base case, check the boundaries!
    if (cell.x == 0)
        return 0;
    // base case, the cell next to this one doesn't match
    if (board[cell.x-1,cell.y].color != cell.color)
        return 0;
    // recursion, check the next cell in the line
    return 1 + checkWest(board[cell.x-1,cell.y]);
 }
于 2012-10-29T19:10:19.617 回答
1

对于一个n by m棋盘和一个连续的获胜组合k

int n, m, k;
byte[,] color = new byte[n, m]; // for two colors, a 0 would correspond to blue, 1 would be red, or however you like

for (int i = 0; i <= n - k; i++) // don't check all the way to the right because there's no room to win
{
    for (int j = 0; j <= m - k; j++) // don't check all the way down because there's no room to win
    {
        // Check here for a win. Check for a win to the right, down right, and down
    }
}
于 2012-10-29T19:10:53.233 回答