生成随机拉丁方连续循环

时间:2012-03-28 17:59:12

标签: c# latin-square

我正在开发一个程序来生成随机网格,拉丁方格和数独。我正在拉丁广场工作,除了我在一个连续的循环中,几乎所有工作。如果我打破他们,他们工作正常。可能有些小我做错了,我找不到它。你能发现什么是错的吗?

编辑:对于那些不知道拉丁广场是什么的人(如果有人不知道),它通常是一个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;
          }
      }
   }
}

我正在使用名为grid的2D数组。

4 个答案:

答案 0 :(得分:2)

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

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

这个问题一般很难快速解决,但对于sudokus和Latin square的特定情况,它非常简单,可以在C#中轻松完成。您创建一个具有81个节点的“图形”,每个节点与其行和列中的其他节点“连接”。 “颜色”是数字1到9。

在我的五篇系列文章中,我将向您介绍如何创建一个可以解决sudokus的高效图形着色算法。将算法改为生成 sudokus并不困难。

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

答案 1 :(得分: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;
    }

计数++会增加,有时会结束&gt; = 50然后将启动此代码:

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

然后将所有内容设置回0并重启。因此,它引起了无限循环。谢谢大家的帮助!

答案 2 :(得分: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

现在你也可以随意改变行(和/或列)的顺序,它应该仍然有效。

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

答案 3 :(得分:0)

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

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

一旦notSame = false;然后它仍然是你执行其余部分的方式。

列是垂直的,行是水平的,所以这(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和flags)。