java - 在 Java 中创建数独

标签 java creation sudoku

我正在创建一个程序来发明一个新的数独游戏。我最初计划这样做的方法是发明一个新的谜题,然后删除随机数。但是,我使用的算法(见下文)创建一个新拼图最多可能需要 5 分钟才能完成。谁有更快的解决方案?

创建算法


    for (int x = 0; x < boardWidth; x++) //boardWidth is the number of fillable squares wide and high the board is. (9 for a standard Sudoku board)
    {
      for (int y = 0; y < boardWidth; y++)
      {
        int errorCount = 0;
        do
        {
          boardVals[y][x] = (byte)(rand.nextInt(boardWidth) + 1);
          errorCount++;
          if (errorCount > Math.pow(boardWidth, 4)) //If the square has been tried to be filled up to boardWidth^4 times (6,561 for a standard Sudoku board), it clears the board and starts again.
          {
            resetBoard();
            x = 0; y = 0; break;
          }
        }while (!boardIsOK()); //boardIsOK() is a method that checks to see if the board is solvable, ignoring unfilled squares.
      }
    }

方法:


  private boolean boardIsOK()
  {
    for (int i=0; i < boardWidth; i++)
    {
      if (!setIsOK(getRow(i)))
      {
        return false;
      }
      if (!setIsOK(getCol(i)))
      {
        return false;
      }
    }
    for (int x=0; x < boardSegs; x++)
    {
      for (int y=0; y < boardSegs; y++)
      {
        if (!areaIsOK(getSquare(x,y)))
        {
          return false;
        }
      }
    }
    return true;
  }



  private byte[] getRow(int index)
  {
    return boardVals[index];
  }

  private byte[] getCol(int index)
  {
    byte[] b = new byte[boardWidth];
    for (int i=0; i < boardWidth; i++)
      b[i] = boardVals[i][index];
    return b;
  }

  private byte[][] getSquare(int xIndex, int yIndex)
  {
    byte w = (byte)(boardWidth / boardSegs), b[][] = new byte[w][w];
    for (int x=0; x < b.length; x++)
    {
      for (int y=0; y < b[x].length; y++)
      {
        b[y][x] = boardVals[y + (yIndex * w)][x + (xIndex * w)];
      }
    }
    return b;
  }

  private boolean setIsOK(byte[] set)
  {
    for (int i=0; i < set.length - 1; i++)
    {
      for (int j=i + 1; j < set.length; j++)
      {
        if (set[i] == set[j] && set[i] != NULL_VAL && set[j] != NULL_VAL)
        {
          return false;
        }
      }
    }
    return true;
  }

  private boolean areaIsOK(byte[][] area)
  {
    int size = 0;
    for (int i=0; i < area.length; i++)
    {
      size += area[i].length;
    }
    byte[] b = new byte[size];
    for (int x=0, i=0; x < area.length; x++)
    {
      for (int y=0; y < area[x].length; y++, i++)
      {
        b[i] = area[x][y];
      }
    }
    return setIsOK(b);
  }

resetBoard() 只是用 NULL_VAL 填充板。

最佳答案

这里有几种可能的优化方法。首先,您应该为每个单元格添加一些簿记,为 81 个单元格中的每一个单元格设置一组“仍然可能的数字”。当您填充下一个单元格时,不要使用任意随机数,而是从此集合中使用随机数。

不要在 6,561 次尝试失败后停下来。当 81 组中的一组变空时停止。在这种情况下,您不应该扔掉电路板重新开始,而是向后退一步,为前一个单元格尝试另一个值。尝试做一个完整的backtracking算法。

关于java - 在 Java 中创建数独,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4477288/

相关文章:

linux - 创建自定义 Linux 发行版的最简单方法

java - 文件已创建但返回 false

c - 使用回溯解决数独错误

c++ - 在 C++ 中解决数独问题

java - 如何在执行程序服务中获取队列中的任务数?

java - 唯一约束 - 键已存在于多对多中

java - 谁能告诉我为什么这在 Eclipse 中有效但在命令提示符中不起作用?

Javascript寄生构造函数似乎无法向对象添加函数,为什么

java - 如何修复: Sudoku solver Stack overflow problem

java - 消息 "operations coalesced during safepoint"的含义