2017-04-01 125 views
0

隨機點我需要幫助,我有我的朋友來幫我調試此代碼,並且我們發現代碼停止在代碼上的隨機點,有時在第一個循環,有時在最後一個循環等等。代碼只是製作一個應用了所有規則的9x9數獨板。當我分別測試每個模塊時,它工作並打印出了一個出色的數獨板,但是這裏的問題在於某種程度上被卡住了。 幫助將不勝感激。雖然循環卡在代碼

int[,] helpblock = new int[10, 10]; 
int[,] helplines = new int[10, 10]; 
int[,] helpcols = new int[10, 10]; 
for (int i = 0; i < 10; i++) { 
    for (int j = 0; j < 10; j++) { 
     helplines[i, j] = 0; 
     helpcols[i, j] = 0; 
     helpblock[i, j] = 0; 
    } 
} 

Random rnf = new Random(); 
int help1; 
for (int i = 0; i < 9; i++) { 
    for (int j = 0; j < 9; j++) { 
     help1 = rnf.Next(1, 10); 
     if (i == 0 || i == 1 || i == 2) { 
      if (j == 0 || j == 1 || j == 2) { 
       if (helplines[i, help1] != 0 || helpblock[0, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[0, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 
       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[0, help1]++; 
      } else if (j == 3 || j == 4 || j == 5) { 
       if (helplines[i, help1] != 0 || helpblock[1, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[1, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 
       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[1, help1]++; 
      } else if (j == 6 || j == 7 || j == 8) { 
       if (helplines[i, help1] != 0 || helpblock[2, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[2, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 
       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[2, help1]++; 
      } 
     } else if (i == 3 || i == 4 || i == 5) { 
      if (j == 0 || j == 1 || j == 2) { 
       if (helplines[i, help1] != 0 || helpblock[3, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[3, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 
       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[3, help1]++; 
      } else if (j == 3 || j == 4 || j == 5) { 
       if (helplines[i, help1] != 0 || helpblock[4, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[4, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 

       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[4, help1]++; 
      } else if (j == 6 || j == 7 || j == 8) { 
       if (helplines[i, help1] != 0 || helpblock[5, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[5, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 

       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[5, help1]++; 

      } 
     } else if (i == 6 || i == 7 || i == 8) { 
      if (j == 0 || j == 1 || j == 2) { 
       if (helplines[i, help1] != 0 || helpblock[6, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[6, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 

       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[6, help1]++; 
      } else if (j == 3 || j == 4 || j == 5) { 
       if (helplines[i, help1] != 0 || helpblock[7, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[7, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 

       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[7, help1]++; 
      } else if (j == 6 || j == 7 || j == 8) { 
       if (helplines[i, help1] != 0 || helpblock[8, help1] != 0 || helpcols[j, help1] != 0) { 
        while (helplines[i, help1] != 0 || helpblock[8, help1] != 0 || helpcols[j, help1] != 0) { 
         System.Threading.Thread.Sleep(1); 
         help1 = rnf.Next(1, 10); 
        } 
       } 

       map[i, j] = help1; 
       helplines[i, help1]++; 
       helpcols[j, help1]++; 
       helpblock[8, help1]++; 
      } 
     } 
    } 
} 

PrintSudoku(map); 
+1

在C# – EliKatz

+0

請註明您所使用的語言進行編程。 – Rajesh

+1

瞭解如何使用調試器。它會準確顯示發生了什麼,特別是當它「有時」發生時。還有,爲什麼只使用9x9時分配10x10數組? –

回答

1

這不是一個真正的答案,但希望它可以幫助您調試程序。裏面你for循環您有if報表一大堆,看起來是這樣的:

if (i == 0 || i == 1 || i == 2) { 
    if (j == 0 || j == 1 || j == 2) { 

它看起來像你使用這個邏輯,以確定哪些阻礙你的,因爲這是一個數組,你正在使用第一個索引的硬編碼值。

不要這樣做,請考慮使用基於當前行和列值的公式計算塊。

網格目前看起來是這樣的:

| 0 1 2 | 3 4 5 | 6 7 8 | 
--+-------+-------+-------- 
0 |  |  |  | 
1 | [0] | [1] | [2] | 
2 |  |  |  | 
--+-------+-------+-------- 
3 |  |  |  | 
4 | [3] | [4] | [5] | 
5 |  |  |  | 
--+-------+-------+-------- 
6 |  |  |  | 
7 | [6] | [7] | [8] | 
8 |  |  |  | 
--------------------------- 

什麼,你可能會注意到的是,如果你把行號和3做一個整數除法,你會得到Block行數(0,1 ,或2)。將此數字乘以3會得到每行中的第一個塊(0,3和6)。現在,如果我們將當前列和整數除以3,我們將得到當前塊列(0,1或2)。添加「塊行」到「塊列」,那麼將會給我們的塊索引:

int block = ((row/3) * 3) + (column/3); 

(請注意,它看起來像你可以簡化這個,因爲行被分成三部分,然後乘以三,但請記住,整數除法捨去,所以2/3 == 0,而不是.6667

通過這種方式計算塊,您可以大幅減少你必須走過的行數。

此外,使用一些更有意義的變量名將有助於提高可讀性。

我將你的代碼簡化爲我認爲完全一樣的東西。也許這會幫助你分析:

int[,] blocks = new int[10, 10]; 
int[,] rows = new int[10, 10]; 
int[,] columns = new int[10, 10]; 

for (int i = 0; i < 10; i++) 
{ 
    for (int j = 0; j < 10; j++) 
    { 
     rows[i, j] = 0; 
     columns[i, j] = 0; 
     blocks[i, j] = 0; 
    } 
} 

Random rnd = new Random(); 
int randomNumber; 

for (int row = 0; row < 9; row++) 
{ 
    for (int column = 0; column < 9; column++) 
    { 
     int block = ((row/3) * 3) + (column/3); 
     randomNumber = rnd.Next(1, 10);      

     while (rows[row, randomNumber] != 0 || 
      blocks[block, randomNumber] != 0 || 
      columns[column, randomNumber] != 0) 
     { 
      System.Threading.Thread.Sleep(1); 
      randomNumber = rnd.Next(1, 10); 
     } 

     map[row, column] = randomNumber; 
     rows[row, randomNumber]++; 
     columns[column, randomNumber]++; 
     blocks[block, randomNumber]++; 
    } 
} 

玩這個當然,以後,我感興趣的問題。下面是我想出瞭解決這個問題,這是一個很值得窮舉法:

  1. 開始用數字1-9可用於每個行,列,並阻止
  2. 從可用列表數字爲一個單元格,隨機分配其中一個,一次一個單元格
  3. 從該行,列和塊的可用數字中刪除該數字
  4. 如果我們遇到沒有有效數字的情況可用於單元格,重置所有內容並重試。

請注意,這可能會運行,永遠不會完成,但在我的測試中,它通常會在少於400次嘗試(從用戶的角度來看相對較快)中找到解決方案。

我做的不同之處在於,我不是使用數組來存儲行/列/塊信息,而是決定使用存儲行/列/塊索引作爲關鍵字的Dictionary<int, List<int>>,以及每個關鍵字的值是該索引的可用數字的List

然後在我們的循環中,我只將當前行,列和塊的剩餘可用數字交叉到List。然後我在該列表中選擇一個隨機索引並將該值分配給單元格(並將其從該行,列和塊中的可用項目中移除)。

我還添加了一些日誌記錄來找出在找到解決方案之前失敗了多少次。

下面的代碼,這也打印在最後的解決方案:

static void Main() 
{ 
    int[,] map = new int[9, 9]; 
    var blocks = new Dictionary<int, List<int>>(); 
    var rows = new Dictionary<int, List<int>>(); 
    var columns = new Dictionary<int, List<int>>(); 

    // initialize lists of available numbers 
    for (int i = 0; i < 9; i++) 
    { 
     blocks.Add(i, new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); 
     rows.Add(i, new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); 
     columns.Add(i, new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); 
    } 

    Random rnd = new Random(); 
    int failCount = 0; 

    // For each row 
    for (int row = 0; row < 9; row++) 
    { 
     // For each column in this row 
     for (int column = 0; column < 9; column++) 
     { 
      // Calculate block based on current row and column 
      int block = ((row/3) * 3) + (column/3); 

      // Get set of available numbers for this cell by getting the intersection 
      // of available numbers for the row, column, and block 
      var availableItems = 
       rows[row].Intersect(
        columns[column].Intersect(
         blocks[block])).ToList(); 

      // If we reach a point where there are no availableItems, then this is 
      // not a valid Sudoku pattern. Reset everything and try again 
      if (availableItems.Count == 0) 
      { 
       failCount++; 
       Console.WriteLine($"Failed {failCount} times. Trying again..."); 

       // Reset to the first cell 
       row = 0; 
       column = 0; 
       block = 0; 

       // Initialize data 
       for (int i = 0; i < 9; i++) 
       { 
        blocks[i] = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
        rows[i] = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
        columns[i] = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
       } 
       availableItems = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
      } 

      // Grab a number from the available numbers by choosing a random index 
      var randomNumber = availableItems[rnd.Next(0, availableItems.Count)]; 

      // Update our map with this item 
      map[row, column] = randomNumber; 

      // Remove this item from our lists 
      rows[row].Remove(randomNumber); 
      columns[column].Remove(randomNumber); 
      blocks[block].Remove(randomNumber); 
     } 
    } 

    // Print our Sudoku map: 
    Console.WriteLine(new string('-', 25)); 

    for(int i = 0; i < 9; i++) 
    { 
     Console.Write("|"); 

     for (int j = 0; j < 9; j++) 
     { 
      Console.Write($" {map[i, j]}"); 
      if ((j + 1) % 3 == 0) Console.Write(" |"); 
     } 

     Console.WriteLine(); 

     if ((i + 1) % 3 == 0) Console.WriteLine(new string('-', 25)); 
    } 

    Console.Write("\nDone!\nPress any key to exit..."); 
    Console.ReadKey(); 
} 

輸出繼電器:

enter image description here

+0

謝謝你,幫助我 – EliKatz

1

這些循環看起來致命的:

while (helplines[i, help1] != 0 || helpblock[5, help1] != 0 || helpcols[j, help1] != 0) { 
    System.Threading.Thread.Sleep(1); 
    help1 = rnf.Next(1, 10); 
} 

如果help1新值不會改變while條件false,它會永遠循環下去。

+0

我會試着進一步研究一下 – EliKatz

+0

此外,如果沒有任何數組項都等於零,這也將永遠循環。 –

+1

@RufusL它比這更糟糕。它將永遠循環,如果*任何*的項目是非零(無論多少爲零) – Bohemian