Java 计算给定数独游戏的解的数量?

Java 计算给定数独游戏的解的数量?,java,algorithm,math,puzzle,sudoku,Java,Algorithm,Math,Puzzle,Sudoku,我正在开发一款基于网络的数独游戏,允许用户定制自己的数独板。我需要一种方法来告诉用户他组装的电路板有多少种可能的解决方案。数独游戏拥有唯一解决方案的最小条目数为17。我需要为少于17个条目的数量找到解决方案的数量 以下是我的方法: public long numberOfSolutions (Board myBoard) { this.board = myBoard; this.tempBoard = new Board(); long num = 0; tem

我正在开发一款基于网络的数独游戏,允许用户定制自己的数独板。我需要一种方法来告诉用户他组装的电路板有多少种可能的解决方案。数独游戏拥有唯一解决方案的最小条目数为17。我需要为少于17个条目的数量找到解决方案的数量

以下是我的方法:

public long numberOfSolutions (Board myBoard) {
    this.board = myBoard;
    this.tempBoard = new Board();
    long num = 0;

    tempBoard.copy(board);
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (board.getCell(i,j).equals(0)) {
                for(int k=1;k<10;k++){
                    board.setCell(i, j, k, true);
                    if(isCorrect() && solvable()){
                        num++;
                    }
                    board.copy(tempBoard);
                }
            }
        }
    }
    return num;
}
所以基本上,对于每个空单元格,我插入1-9之间的数字,并尝试解决每个数字的游戏。如果成功,则增加解决方案的数量。但这并不能得到所有可能组合的数量,而是每个可以插入的电池的数量之和


有什么办法可以计算吗?

答案可能是:不要那样做

数独解题很难,所以可能需要一段时间才能解决一个问题,更不用说计算解题的数量了


即使您尝试计算计数,它也可能非常大。一块没有任何内容的数独板上有答案。

答案可能是:不要那样做

数独解题很难,所以可能需要一段时间才能解决一个问题,更不用说计算解题的数量了


即使您尝试计算计数,它也可能非常大。一个没有任何内容的数独板上有答案。

我不会说太多Java,但下面是递归方法的基本描述:

如果电路板有错误,即同一行、同一列或同一框中有两个相同的数字,则解决方案为零。如果没有错误且电路板已满,则有一种解决方案。如果没有错误,但电路板未满,则选择最早的空单元,并对该单元中包含1、2、…、9的电路板的解决方案数求和


这不是最好的方法,但它完成了任务,而且我相信,一旦代码实际出现在屏幕上,就会有一些优化等待进行。

我不会说太多Java,但下面是递归方法的基本描述:

如果电路板有错误,即同一行、同一列或同一框中有两个相同的数字,则解决方案为零。如果没有错误且电路板已满,则有一种解决方案。如果没有错误,但电路板未满,则选择最早的空单元,并对该单元中包含1、2、…、9的电路板的解决方案数求和


这不是最好的方法,但它完成了任务,而且我确信,一旦代码实际出现在您的屏幕上,就会有一些优化等待进行。

也许几年前我保存的东西可能会让您了解以下内容,,,在这种情况下,如果givens允许,具有最多候选项的单元格而不是被选择最少的单元格似乎可以确保多个解决方案,然后在计数等于2时停止。否则,尽可能地解决这个难题,并且只有在空单元格足够少的情况下,才可能进行计数。由于它是html代码,我不确定您是否能看到它,但它在这里:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <HTML>
    <HEAD>
    <TITLE>Sudoku Solver</TITLE>
    <META name="Keywords" content="Sudoku, Simple, javascript, puzzle">
    <META name="Description" content="Simple Sudoku Solver, written in JavaScript">
    <script type="text/javascript">
    function Board() {
     this.cells=new Array();
     for (var i=0; i<81; ++i)
      this.cells[i]=0;
    }

    function CopyBoard(dest, src) {
     for (var i=0; i<81; ++i)
      dest.cells[i]=src.cells[i];
    }
    function CountConstraints(val) {
     var cc=0;
     for (var i=1; i<=9; ++i)
      if (((1<<i) & val)!=0) ++cc;
     return cc;
    }
    function MostConstrained() {
     var max=-1, maxp=-1;
     for (var i=0; i<81; ++i) {
      if ((this.cells[i] & 1)==0) {
       v=CountConstraints(this.cells[i]);
       if (v>=max) {
        max=v;
        maxp=i;
       }
      }
     }
     return maxp;
    }

    Board.prototype.mostConstrained=MostConstrained;

    function AllOptions(val) {
     var cc=new Array;
     var n=0;
     for (var i=1; i<=9; ++i)
      if (((1<<i) & val)==0) cc[n++]=i;
     return cc;
    }

    function SetValue(pos, val) {
      var x=pos%9;
      var y=Math.floor(pos/9);
      var x0=Math.floor(x/3)*3;
      var y0=Math.floor(y/3)*3;
      var add=(1<<val);
      for (var k=0; k<9; ++k) {
        this.cells[x+k*9]|=add;
        this.cells[k+y*9]|=add;      
        this.cells[x0+(k%3)+9*(y0+Math.floor(k/3))]|=add;}
      this.cells[pos]=1023-(1<<val);
    }
    Board.prototype.setValue=SetValue;

    function CellText(d) {
     if (d&1) {
      for (var i=1; i<=9; ++i)
       if ((d | (1<<i))==1023) return ""+i;
      return "_";
     }
     else {
      return "?"+AllOptions(d);
     }
    }
    function AsHTML() {
     var ans="";
     for (var y=0; y<9; ++y) {
      ans=ans+"<tr>"
      for (var x=0; x<9; ++x) {
       ans=ans+"<td class=sol>"+CellText(this.cells[x+y*9])+"<\/td>";
      }
      ans=ans+"<\/tr>";
     }
     return "<table border=1>"+ans+"<\/table>"
    }
    Board.prototype.asHTML=AsHTML; 

    function IsOK() {
     for (var i=0; i<81; ++i) {
      if ((this.cells[i] & 1022)==1022) {
        return false;
      }
     }
     return true;
    }  

    function IsSolved() {
     for (var i=0; i<81; ++i) {
      if ((this.cells[i] & 1)==0) return false;
     }
     return true;
    }

    Board.prototype.isSolved=IsSolved;
    Board.prototype.isOK=IsOK;

    var theOne=new Board();
    var numSol;

    function SearchSolutions() {
        while (this.isOK()) {
            if (this.isSolved()) {
                if (1<++numSol) return this;
                CopyBoard(theOne,this);return null;}
            var p=this.mostConstrained();
            if (p<0) return null;
            var l=AllOptions(this.cells[p]);
            if (l.length<1) return null;
            for (var i=1; i<l.length; ++i) {
                var nb=new Board();
                CopyBoard(nb, this);
                nb.setValue(p, l[i]);
                nb=nb.searchSolutions();
                if (nb) return nb;}
            this.setValue(p, l[0]);}
        return null;
    }
    Board.prototype.searchSolutions=SearchSolutions;

    function DrawInput() {
     var ans="";
     for (var y=0; y<9; ++y) {
      ans=ans+"<tr>"
      for (var x=0; x<9; ++x) {
       ans=ans+"<td class=sol><input size=1 type=text id='C"+(x+y*9)+"'><\/td>";
      }
      ans=ans+"<\/tr>"
     }
     document.write("<table border=1>"+ans+"<\/table>");
    }
    function solve_click() {
        var theSec=new Board();
        numSol=0;
        for (var i=0; i<81; ++i) {
        var v=document.getElementById("C"+i).value
        if (v>="1" && v<="9") theSec.setValue(i, parseInt(v));}
        var rsp=theSec.searchSolutions();
        var ans="<p>No solution<\/p>";
        if (numSol==1) ans="<p>Valid Sudoku - One and only one solution !<\/p>"+theOne.asHTML();
        if (numSol==2) ans="<p>Invalid Sudoku - More than one solution !<\/p>"+theOne.asHTML()+"<p><\/p>"+rsp.asHTML();
        document.getElementById("answer").innerHTML=ans;
    }

    </SCRIPT>

    <STYLE type=text/css>
    .sol {
        WIDTH: 1em; HEIGHT: 1em
    }
    </STYLE>
    </HEAD>
    <BODY>
    <h1>Sudoku Solver</h1>
    <a href="solverabout.html"><span style="font-size: smaller">(about)</span></a>

    <div>
    <script type="text/javascript">
     DrawInput();
    </script>
    <input type="button" value="Solve" onclick="solve_click();">
    </div>
    <div id="answer"></div>
    </BODY>
    </HTML>

也许几年前我保存的某个东西可能会让我产生一些想法,它如下,,,其中具有最多候选者的单元格,而不是选择最少的单元格,似乎可以确保不止一个解决方案,如果givens允许,那么停止计数等于2。否则,尽可能地解决这个难题,并且只有在空单元格足够少的情况下,才可能进行计数。由于它是html代码,我不确定您是否能看到它,但它在这里:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <HTML>
    <HEAD>
    <TITLE>Sudoku Solver</TITLE>
    <META name="Keywords" content="Sudoku, Simple, javascript, puzzle">
    <META name="Description" content="Simple Sudoku Solver, written in JavaScript">
    <script type="text/javascript">
    function Board() {
     this.cells=new Array();
     for (var i=0; i<81; ++i)
      this.cells[i]=0;
    }

    function CopyBoard(dest, src) {
     for (var i=0; i<81; ++i)
      dest.cells[i]=src.cells[i];
    }
    function CountConstraints(val) {
     var cc=0;
     for (var i=1; i<=9; ++i)
      if (((1<<i) & val)!=0) ++cc;
     return cc;
    }
    function MostConstrained() {
     var max=-1, maxp=-1;
     for (var i=0; i<81; ++i) {
      if ((this.cells[i] & 1)==0) {
       v=CountConstraints(this.cells[i]);
       if (v>=max) {
        max=v;
        maxp=i;
       }
      }
     }
     return maxp;
    }

    Board.prototype.mostConstrained=MostConstrained;

    function AllOptions(val) {
     var cc=new Array;
     var n=0;
     for (var i=1; i<=9; ++i)
      if (((1<<i) & val)==0) cc[n++]=i;
     return cc;
    }

    function SetValue(pos, val) {
      var x=pos%9;
      var y=Math.floor(pos/9);
      var x0=Math.floor(x/3)*3;
      var y0=Math.floor(y/3)*3;
      var add=(1<<val);
      for (var k=0; k<9; ++k) {
        this.cells[x+k*9]|=add;
        this.cells[k+y*9]|=add;      
        this.cells[x0+(k%3)+9*(y0+Math.floor(k/3))]|=add;}
      this.cells[pos]=1023-(1<<val);
    }
    Board.prototype.setValue=SetValue;

    function CellText(d) {
     if (d&1) {
      for (var i=1; i<=9; ++i)
       if ((d | (1<<i))==1023) return ""+i;
      return "_";
     }
     else {
      return "?"+AllOptions(d);
     }
    }
    function AsHTML() {
     var ans="";
     for (var y=0; y<9; ++y) {
      ans=ans+"<tr>"
      for (var x=0; x<9; ++x) {
       ans=ans+"<td class=sol>"+CellText(this.cells[x+y*9])+"<\/td>";
      }
      ans=ans+"<\/tr>";
     }
     return "<table border=1>"+ans+"<\/table>"
    }
    Board.prototype.asHTML=AsHTML; 

    function IsOK() {
     for (var i=0; i<81; ++i) {
      if ((this.cells[i] & 1022)==1022) {
        return false;
      }
     }
     return true;
    }  

    function IsSolved() {
     for (var i=0; i<81; ++i) {
      if ((this.cells[i] & 1)==0) return false;
     }
     return true;
    }

    Board.prototype.isSolved=IsSolved;
    Board.prototype.isOK=IsOK;

    var theOne=new Board();
    var numSol;

    function SearchSolutions() {
        while (this.isOK()) {
            if (this.isSolved()) {
                if (1<++numSol) return this;
                CopyBoard(theOne,this);return null;}
            var p=this.mostConstrained();
            if (p<0) return null;
            var l=AllOptions(this.cells[p]);
            if (l.length<1) return null;
            for (var i=1; i<l.length; ++i) {
                var nb=new Board();
                CopyBoard(nb, this);
                nb.setValue(p, l[i]);
                nb=nb.searchSolutions();
                if (nb) return nb;}
            this.setValue(p, l[0]);}
        return null;
    }
    Board.prototype.searchSolutions=SearchSolutions;

    function DrawInput() {
     var ans="";
     for (var y=0; y<9; ++y) {
      ans=ans+"<tr>"
      for (var x=0; x<9; ++x) {
       ans=ans+"<td class=sol><input size=1 type=text id='C"+(x+y*9)+"'><\/td>";
      }
      ans=ans+"<\/tr>"
     }
     document.write("<table border=1>"+ans+"<\/table>");
    }
    function solve_click() {
        var theSec=new Board();
        numSol=0;
        for (var i=0; i<81; ++i) {
        var v=document.getElementById("C"+i).value
        if (v>="1" && v<="9") theSec.setValue(i, parseInt(v));}
        var rsp=theSec.searchSolutions();
        var ans="<p>No solution<\/p>";
        if (numSol==1) ans="<p>Valid Sudoku - One and only one solution !<\/p>"+theOne.asHTML();
        if (numSol==2) ans="<p>Invalid Sudoku - More than one solution !<\/p>"+theOne.asHTML()+"<p><\/p>"+rsp.asHTML();
        document.getElementById("answer").innerHTML=ans;
    }

    </SCRIPT>

    <STYLE type=text/css>
    .sol {
        WIDTH: 1em; HEIGHT: 1em
    }
    </STYLE>
    </HEAD>
    <BODY>
    <h1>Sudoku Solver</h1>
    <a href="solverabout.html"><span style="font-size: smaller">(about)</span></a>

    <div>
    <script type="text/javascript">
     DrawInput();
    </script>
    <input type="button" value="Solve" onclick="solve_click();">
    </div>
    <div id="answer"></div>
    </BODY>
    </HTML>

数独解算是NP完全的,但它的n9非常小,所以数独解算器可以在毫秒内运行。@Patashu仍然,对于未确定的网格,可能的解的数量爆炸式增长,所以“不要这样做”是个好建议。@DanielFischer想象一个返回0、1、2、3、4、5或“太多”的解算。这很容易写,也是OP想要做的。@Patashu是的,很好。这可能是OP需要的,但不是他要求的。数独解算是NP完全的,但它有非常小的n9,所以数独解算器可以在毫秒内运行。@Patashu仍然,对于未确定的网格,可能的解的数量激增,所以“不要这样做”是一个很好的建议。@DanielFischer想象一个返回0,1,2,3,4、5或“太多”。这很容易写,也是OP想要做的。@Patashu是的,很好。这可能是OP需要的,但不是他要求的。问题是关于Java…?问题是关于Java。。。?