0

我正在用 C# 制作一个 15 拼图游戏,它允许用户输入自定义行和列值,最大为 10 x 10 拼图。因此,我在使用 shuffle 方法时遇到了问题。我想做到这一点,所以这个难题总是可以解决的。首先创建一个获胜的谜题,然后将空白空间洗牌。问题是每次调用每个点击事件效率太低。我需要一种方法来调用与空白空间相邻但不是对角线的按钮的单击事件。我还在空白处使用了一个不可见的静态按钮。PuzzlePiece 类继承自 Button。我不太确定该怎么做。我将不胜感激任何帮助。

谢谢

这是我所拥有的:

private void shuffleBoard()
    {
        //5 is just for test purposes
        for (int i = 0; i < 5; i++)
        {
            foreach (Control item in this.Controls)
            {
                if (item is PuzzlePiece)
                {
                    ((PuzzlePiece)item).PerformClick();
                }
            }
        }
    }

 void PuzzlePiece_Click(object sender, EventArgs e)
    {
        PuzzlePiece piece = (PuzzlePiece)sender;

        if (piece.Right == puzzleForm.emptyPiece.Left && piece.Top == puzzleForm.emptyPiece.Top)
        {
            movePiece(piece);
        }
        else if (piece.Left == puzzleForm.emptyPiece.Right && piece.Top == puzzleForm.emptyPiece.Top)
        {
            movePiece(piece);
        }
        else if (piece.Top == puzzleForm.emptyPiece.Bottom && piece.Left == puzzleForm.emptyPiece.Left)
        {
            movePiece(piece);
        }
        else if (piece.Bottom == puzzleForm.emptyPiece.Top && piece.Left == puzzleForm.emptyPiece.Left)
        {
            movePiece(piece);
        }
    }
4

2 回答 2

10

对于 15 块拼图(和类似的滑动拼图游戏),任何拼图排列都是可解的当且仅当它具有偶数奇偶性。

因此,您应该能够随机放置瓷砖。如果奇偶校验是偶数,那么它可以按原样解决。如果奇偶性是奇数,则只需交换两个相邻的瓷砖以反转奇偶性,然后就可以解决了。

有关如何测量奇偶性的详细信息,请参见此处:http ://en.wikipedia.org/wiki/Fifteen_puzzle#Solvability


由于维基百科的文章已更改,因此不再清楚如何计算 15 拼图排列的奇偶性,我将在下面解释:

对于任何瓷砖排列,您可以通过以下方式计算反转:

  1. 计算所有的“倒置”。倒置是从右上角开始,穿过每一行,一直到左下角,编号的牌低于之前的牌的任何时间。第一个瓦片永远不会算作倒置(因为它前面没有瓦片,所以它不能低于该瓦片),并且您不计算空白空间。

  2. 再加上空白处的行号1。

这个总数是安排的计数。如果 Count 为偶数,则该排列具有偶数(或 0)奇偶性。如果计数是奇数,则它具有奇数(或 1)奇偶校验。

将起始排列的奇偶性与目标排列的奇偶性进行比较。如果它们是相同的,那么这个谜题是可解的,否则它是不可解的。由于标准目标排列(空格,1-15 的顺序)有 0 次反转并且空格的行号为 1,所以我们得到一个 Count0 + (1 - 1)或 0,即使如此,目标的奇偶校验也是 0。因此任何也为 0 的起始排列是可解的。

于 2012-10-16T01:18:35.423 回答
2

如果我是你,我会把你的模型从你的 UI 中分离出来。

创建一个名为Puzzle. 该类将保存拼图的状态并对该状态执行所有操作。

您可能会实现MoveLeft, MoveRight, MoveUp&MoveDown方法。要洗牌,您可以通过随机调用这四种方法来执行(相当长的)一系列移动。

您的Puzzle类需要公开足够的状态以供 UI 呈现自身。

这样做可以简化代码并使单元测试更加简单。

于 2012-10-16T01:23:53.523 回答