1

我正在开发一个生成随机网格、拉丁方格和数独的程序。我正在研究拉丁方格,除了我处于连续循环中之外,几乎所有这些都可以正常工作。如果我把它们分开,它们就可以正常工作。可能有一些小事情我做错了,我找不到它。你能看出哪里不对吗?

编辑:对于那些不知道拉丁方是什么的人(如果有人不知道),它通常是一个 9x9 网格,在行和列中都没有重复。

更新:我在 if(notSame) 语句之前发现了 notSame 等于 true 的问题。它总是等于 true,所以不会完成检查行。现在,当我运行时,它不再处于连续循环中,而是行没有重复,但列仍然存在。

更新#2:我现在重做了很多列的编码。我的教授要求我改变一些事情,但它仍然让我陷入一个连续的循环。

int row = 0, col = 0, count = 0;
bool notSame = true;
// setting up rows and columns
for (row = 0; row < grid.GetLength(0); row++)
{
   for (col = 0; col < grid.GetLength(1); col++)
   {

       grid[row, col] = rnd.Next(1, 10);

       //for loop to check rows for repeats
       for (int c = 0; c < col; c++)
       {
           // if there is repeat go back a column and set bool = false
           if (grid[row, col] == grid[row, c])
           {
               col--;
               count++;
               notSame = false;
               break;
            }

            //notSame = true;
        }

     // if bool = true loop to check columns for repeats
     if (notSame)
     {

         for (int r = 0; r < row; r++)
         {
         // if repeat then go back row
            if (grid[row, col] == grid[r, col])
            {
                notSame = false;
                count++;
                break;
             }

          }
          if (notSame == false && count <= 50)
          {
               row--;
               //break;
          }
          else if (notSame == false && count > 50)
          {
               count = 0;
               col = 0;
               row = 0;
               break;
          }
      }
   }
}

我正在使用一个称为网格的二维数组。

4

4 回答 4

2

我不知道你的编码错误在哪里。但是你的算法不是很有效。

拉丁方格和数独实际上都是“图形着色”问题的特例。也就是说,给定一堆任意“连接”在一起的“节点”,找到一种方法为每个节点着色,以使连接的两个节点都不具有相同的颜色。

这个问题通常很难快速解决,但对于数独和拉丁方格的特定情况,它非常简单,可以在 C# 中轻松完成。您创建一个包含 81 个节点的“图”,每个节点都“连接”到其行和列中的其他节点。“颜色”是数字 1 到 9。

在我的五部分系列文章中,我将向您介绍如何创建可以解决数独问题的高效图形着色算法。调整算法来生成数独并不难。

http://blogs.msdn.com/b/ericlippert/archive/tags/graph+colouring/

于 2012-03-28T18:25:27.893 回答
2

我的问题是检查行时的额外计数。计数总是会超过 50,因此会导致无限循环。澄清:

grid[row, col] = rnd.Next(1, 10);

   //for loop to check rows for repeats
   for (int c = 0; c < col; c++)
   {
       // if there is repeat go back a column and set bool = false
       if (grid[row, col] == grid[row, c])
       {
           col--;
           count++;
           notSame = false;
           break;
        }

        //notSame = true;
    }

count++ 会增加,有时会以 > = 50 结束,然后会启动此代码:

 else if (notSame == false && count > 50)
      {
           count = 0;
           col = 0;
           row = 0;
           break;
      }

然后导致所有内容都设置回 0 并重新启动。因此,它造成了无限循环。感谢大家的帮助!

于 2012-04-29T20:49:51.330 回答
1

我认为生成拉丁方格的最简单方法是从已知拉丁方格开始。说:

1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3

这很容易通过行的循环排列生成任何大小,然后只需将网格 (1,2,3,4) 中的每个值分配给随机生成的另一个值。例如,您可以简单地将数字 1、2、3、4 的列表打乱并得到,比如说 2、4、3、1。现在只需将正方形中的 1 替换为随机列表中的第一个条目,将 2 替换为第二个条目,依此类推即可:

2 4 3 1
4 3 1 2
3 1 2 4 
1 2 4 3

现在,如果您愿意,您也可以打乱行(和/或列)的顺序,它应该仍然有效。

编辑:实际上,考虑到这一点,从第一个方块开始然后洗牌列和行可能是最简单的。无需进行替换部分。

于 2012-03-28T18:28:36.330 回答
0

对您正在迭代的变量进行显式递减是不可以的。那可能是你的问题。这听起来像是一个使用回溯来避免它的好地方:)

编辑:我看到了很多我不知道从哪里开始的问题。这个算法永远不会给你你需要的东西。首先,当您开始填充它时,它可能会导致死锁问题,并且您无法将数字添加到特定的行/列。假设您在第 5 行有 12345,然后在第 6 列有数字 6 7 8 9 .. 好吧,你不能在第 5 行第 6 列添加数字;)看到问题了吗??除此之外,您的代码还有几个问题:在迭代时更改迭代变量是一个大问题,应该避免。

一旦不一样=假;然后在您执行的其余部分保持这种状态。

列是垂直的,行是水平的,所以这个 (1,2) 是第 1 行第 2 列 .. 您正在检查第一阶段的行.. 和第二阶段的列..

// if bool = true loop to check columns for repeats
     if (notSame)
     {

         for (int r = 0; r < row; r++)
         {
             // if repeat then genereate new random and go back row
             if (grid[row, col] == grid[r , col])
             {
                 grid[row, col] = rnd.Next(1, 10);

这本身就有问题..如果您更改那里的号码,您应该和以前一样检查过!

告诉你老师来这里读这个;)..我不知道还有什么可以帮助你的,这个算法是完全错误的,需要彻底重构(是的,你可以使用迭代来做到这一点,但不是,您需要使用 while 和标志)。

于 2012-03-28T18:07:01.753 回答