【问题标题】:Generate valid sudoku puzzle in C在 C 中生成有效的数独谜题
【发布时间】:2018-12-05 15:04:27
【问题描述】:

我尝试在 C 中生成一个有效的数独谜题,当我编译时,什么都没有发生,我认为有一个无限循环,但我不知道它来自哪里!我想我需要帮助!在我的推理中,我尝试: 随机取任意数字 1-9。 检查放入单元格是否安全。(行、列和框) 如果安全,请将其放置并递增到下一个位置,然后转到步骤 1。 如果不安全,则不递增转到步骤 1。 矩阵完全填充后,删除 k 号。元素随机完成游戏。 这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include <math.h>

#define N 9 // row and col 
#define SRN 3 // square and row
#define K 20 //missing digits 

int mat[N][N];

bool unUsedInBox(int rowStart, int colStart, int num) {
  for (int i = 0; i < SRN; i++)
    for (int j = 0; j < SRN; j++)
      if (mat[rowStart + i][colStart + j] == num)
        return false;

  return true;
}

int randomGenerator(int num) {
  srand(time(NULL));
  return (int) ( rand() % num ) + 1;
}

bool unUsedInRow(int i, int num) {
  for (int j = 0; j < N; j++)
    if (mat[i][j] == num)
      return false;
  return true;
}

// check in the row for existence 
bool unUsedInCol(int j, int num) {
  for (int i = 0; i < N; i++)
    if (mat[i][j] == num)
      return false;
  return true;
}

bool CheckIfSafe(int i, int j, int num) {
  return (unUsedInRow(i, num) &&
    unUsedInCol(j, num) &&
    unUsedInBox(i - i % SRN, j - j % SRN, num));
}

void fillBox(int row, int col) {
  int num;
  for (int i = 0; i < SRN; i++) {
    for (int j = 0; j < SRN; j++) {
      do {
        num = randomGenerator(N);
      }
      while (!unUsedInBox(row, col, num));

      mat[row + i][col + j] = num;
    }
  }
}

void fillDiagonal() {
  for (int i = 0; i < N; i = i + SRN)
    fillBox(i, i);
}

bool fillRemaining(int i, int j) {
  if (j >= N && i < N - 1) {
    i = i + 1;
    j = 0;
  }
  if (i >= N && j >= N)
    return true;

  if (i < SRN) {
    if (j < SRN)
      j = SRN;
  } else if (i < N - SRN) {
    if (j == (int)(i / SRN) * SRN)
      j = j + SRN;
  } else {
    if (j == N - SRN) {
      i = i + 1;
      j = 0;
      if (i >= N)
        return true;
    }
  }

  for (int num = 1; num <= N; num++) {
    if (CheckIfSafe(i, j, num)) {
      mat[i][j] = num;
      if (fillRemaining(i, j + 1))
        return true;

      mat[i][j] = 0;
    }
  }
  return false;
}

void removeKDigits() {
  int count = K;
  while (count != 0) {
    int cellId = randomGenerator(N * N);

    int i = (cellId / N);
    int j = cellId % 9;
    if (j != 0)
      j = j - 1;

    if (mat[i][j] != 0) {
      count--;
      mat[i][j] = 0;
    }
  }
}

void fillValues() {
  // Fill the diagonal of SRN x SRN matrices 
  fillDiagonal();

  // Fill remaining blocks 
  fillRemaining(0, SRN);

  // Remove Randomly K digits to make game 
  removeKDigits();
}

void printSudoku() {
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++){
        printf("%d",mat[i][j]);
        printf(" ");
    }
      printf("\n");
  }
  printf("\n");
}

int main() {
  fillValues();
  printSudoku();
}

【问题讨论】:

  • 首先,只调用srand一次
  • 或者干脆不要使用默认的随机数,这很糟糕。
  • 我认为有一个无限循环,但我不知道它是从哪里来的! - 这是调试器可以提供帮助的地方。
  • 我投票结束这个问题,因为 OP 需要使用调试器:ericlippert.com/2014/03/05/how-to-debug-small-programs
  • 在 OP 成功使用调试器并找出程序循环的位置后,为什么会发生这种情况是合适的,但这将是一个单独的问题。

标签: c arrays algorithm sudoku


【解决方案1】:

可能无限循环是由以下原因引起的:

int randomGenerator(int num) {
  srand(time(NULL));
  return (int) ( rand() % num ) + 1;
}

因为srand 被调用来生成每个“随机”数字,所以会一遍又一遍地生成相同的数字。由于该数字已经在使用中,循环while (!unUsedInBox(row, col, num)); 将永远循环(或至少直到time(NULL) 返回一个新值)。所以每一秒(大约time的结果)都会有一个步骤的进展,然后需要再经过一秒,等等,似乎是无限的。

(见某程序员老兄的评论)

【讨论】:

  • 次要:(unsigned) time_t 的分辨率通常为 1 秒而不是 17 毫秒。 , 还是紫外线
猜你喜欢
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 2012-09-10
  • 2020-02-17
  • 2011-09-27
  • 2012-05-05
相关资源
最近更新 更多