草庐IT

java - 递归:如何尝试整数 1 到 9 的不同组合,以及(部分)反向序列以在出错时重新开始?

coder 2024-03-14 原文

语言: Java

目标: 一般:解决数独游戏

特定的:创建一个递归方法 solve() :

  • 检查数字是否与行、列或框中的其他数字冲突
  • 如果不是这种情况,则在给定的空白处填充 [1-9] 之间的整数,然后移至下一个空白处
  • (部分或全部)如果空格不能被 [1-9] 之间的整数填充而不冲突,则反转进度。然后重试,直到所有空格都被填满(并且数独已解决)。

问题: 循环尝试填写整数 n 但总是会先尝试最小的数字。 如果我要使用递归,整数将始终相同。

问题: 1.如何让代码填写1到9之间的数字,包括1到9。

  1. 您如何使用递归来部分或完全清除进度并尝试不同的数字。

  2. (extra) 到目前为止,我已经构建了部分解决数独问题的代码(直到无法填充空白方 block ),但现在它甚至没有填充第一个方 block ,尽管它之前已经填充了。这不是我的主要问题,但如果有人注意到这个问题,请指出,我将不胜感激。

审阅: 我正在阅读有关递归的类(class)资料,但找不到正确的信息。

免责声明: 方法 printMatrix 之外的所有 println 命令都用于测试

这里是有问题的方法:

       // prints all solutions that are extensions of current grid
      // leaves grid in original state
void solve() {
//local variables
int[] currentSquare;
int currentRow;
int currentColumn;
boolean checkConflict;
currentSquare = new int[2];

//saftey limit for testing
int limit;
limit = 0;

while(findEmptySquare() != null){

  currentSquare = findEmptySquare().clone();
  currentRow = currentSquare[0];
  currentColumn = currentSquare[1];
  //System.out.println(" column c:"+currentColumn+" row r:"+currentRow); //column c5 r 3

  if(currentSquare[0] != -1){

    for(int n = 1; n <= ms; n++){
      checkConflict = givesConflict(currentRow, currentColumn, n);
      if(checkConflict == false){
        grid[currentRow][currentColumn] = n;
      }//end if
    }//end for
  }//end if
  else{
    System.out.println("solve: findEmptySquare was -1");
    break;
  }

  //Safety limit
  limit++;
  if (limit > 20){
    System.out.println("break");
    break;
  }//end if

}//end while
}

下面是查找空方 block 的方法:

// finds the next empty square (in "reading order")
// returns array of first row then column coordinate
// if there is no empty square, returns .... (FILL IN!)
int[] findEmptySquare() {
int[] rowcol;
int[] noMoreCells;
rowcol = new int[2];
noMoreCells = new int[2];
noMoreCells[0] = -1;
noMoreCells[1] = -1;

for(int r = 0; r < ms; r++){
  for(int c = 0; c < ms; c++){
    if(grid[r][c] == 0){
      if(r != rempty || c != cempty){ //check that the location of empty cell is not the same as last one
        rempty = r;
        cempty = c;
        rowcol[0] = r; // 0 for row
        rowcol[1] = c; // 1 for column
        //System.out.println(" column c:"+rowcol[1]+" row r:"+rowcol[0]); //column c5 r 3
        return rowcol;
      }//end if
      else{
        System.out.println("findEmptySquare: found same empty square twice");
        return noMoreCells;
      }//end else
    }//end if
  }//end for
}//end for

System.out.println("findEmptySquare: no more empty cells");
return null;  //no more empty cells
}

如有必要,整个代码(缩进很乱,因为我不得不在 stackoverflow 上手动添加空格):

 // Alain Lifmann. Date: 26/9/2015
// Description of program: runs sudoku game
import java.util.*;

class Sudoku {
  int ms = 9; //maze Size
  int rempty; //keeping track of empty squares, row nr. (array)
  int cempty; //keeping track of empty squares, column nr. (array)
  int SIZE = 9;     // size of the grid
  int DMAX = 9;     // maximal digit to be filled in
  int BOXSIZE = 3;  // size of the boxes 
  int[][] grid;     // the puzzle grid; 0 represents empty

      // a challenge-sudoku from the web
  int[][] somesudoku = new int[][] {         
{ 0, 6, 0,   0, 0, 1,    0, 9, 4 },    //original      
  // { 0, 0, 0,   0, 0, 1,    0, 9, 4 }, //to get more solutions
{ 3, 0, 0,   0, 0, 7,    1, 0, 0 }, 
{ 0, 0, 0,   0, 9, 0,    0, 0, 0 }, 

{ 7, 0, 6,   5, 0, 0,    2, 0, 9 }, 
{ 0, 3, 0,   0, 2, 0,    0, 6, 0 }, 
{ 9, 0, 2,   0, 0, 6,    3, 0, 1 }, 

{ 0, 0, 0,   0, 5, 0,    0, 0, 0 }, 
{ 0, 0, 7,   3, 0, 0,    0, 0, 2 }, 
{ 4, 1, 0,   7, 0, 0,    0, 8, 0 }, 
  };

  // a test-sudoku from oncourse
  int[][] testsudoku = new int[][] {         
{ 1, 2, 3,   4, 5, 6,    7, 8, 9 },      
{ 4, 5, 6,   7, 8, 9,    1, 2, 3 },
{ 7, 8, 9,   1, 2, 3,    4, 5, 6 }, 

{ 2, 1, 4,   3, 6, 5,    8, 9, 7 },
{ 3, 6, 5,   8, 9, 7,    2, 1, 4 },
{ 8, 9, 7,   2, 1, 4,    3, 6, 5 },

{ 5, 3, 1,   6, 4, 2,    9, 7, 8 },
{ 6, 4, 2,   9, 7, 8,    5, 3, 1 },
{ 9, 7, 8,   5, 3, 1,    6, 4, 2 },
  };

  // a test-sudoku modified to be incomplete
  int[][] testsudoku2 = new int[][] {         
{ 0, 0, 3,   0, 5, 6,    7, 8, 0 },      
{ 0, 5, 0,   7, 0, 0,    1, 0, 3 },
{ 7, 0, 0,   1, 0, 3,    4, 5, 6 }, 

{ 2, 1, 4,   3, 6, 5,    8, 0, 7 },
{ 3, 0, 5,   8, 0, 7,    0, 1, 0 },
{ 0, 9, 7,   0, 1, 4,    3, 0, 5 },

{ 0, 0, 0,   6, 4, 2,    9, 7, 8 },
{ 0, 4, 2,   9, 7, 8,    0, 0, 1 },
{ 0, 0, 0,   5, 3, 1,    0, 4, 0 },
  };

  int solutionnr = 0; //solution counter

  // ----------------- conflict calculation --------------------

  // is there a conflict when we fill in d at position r,c?
  boolean givesConflict(int r, int  c, int d) {
if(rowConflict(r, d) == true){
  return true;
}//end if
if(colConflict(c, d) == true){
  return true;
}//end if
if(boxConflict(r, c, d) == true){
  return true;
}//end if     
return false;
  }//end givesConflict


  boolean rowConflict(int r, int d) {
    for(int i = 0; i < ms; i++){
  if(d == grid[r][i]){
    //System.out.println("rowconflict r:"+r+" d:"+d);
    return true;
  }//end if
    }//end for

    return false; //no conflict
  }

  boolean colConflict(int c, int d) {
    for(int i = 0; i < ms; i++){
  if(d == grid[i][c]){
    //System.out.println("column conflict c:"+c+" d:"+d);
    return true;
  }//end if
    }//end for

    return false; //no conflict
  }

  boolean boxConflict(int rr, int cc, int d) { //test 5,3,1
int rs; // Box-row start point
int cs; // Box-column start point
rs = rr - rr%3;
cs = cc - cc%3;
//System.out.println("box start is row "+rs+" , column "+cs);

for(int r = rs; r < rs + 3; r++ ){
  for(int c = cs; c < cs + 3; c++){

    if(d == grid[r][c]){
      //System.out.println("r:"+r+" c:"+c);
      return true;
    }//end if

  }//end for
}//end for

    return false; //no conflict
  }

  // --------- solving ----------

  // finds the next empty square (in "reading order")
  // returns array of first row then column coordinate
  // if there is no empty square, returns .... (FILL IN!)
  int[] findEmptySquare() {
int[] rowcol;
int[] noMoreCells;
rowcol = new int[2];
noMoreCells = new int[2];
noMoreCells[0] = -1;
noMoreCells[1] = -1;

    for(int r = 0; r < ms; r++){
      for(int c = 0; c < ms; c++){
    if(grid[r][c] == 0){
      if(r != rempty || c != cempty){ //check that the location of empty cell is not the same as last one
        rempty = r;
        cempty = c;
        rowcol[0] = r; // 0 for row
        rowcol[1] = c; // 1 for column
        //System.out.println(" column c:"+rowcol[1]+" row r:"+rowcol[0]); //column c5 r 3
        return rowcol;
      }//end if
      else{
        System.out.println("findEmptySquare: found same empty square twice");
        return noMoreCells;
      }//end else
    }//end if
  }//end for
    }//end for

    System.out.println("findEmptySquare: no more empty cells");
    return null;  //no more empty cells
      }

  // prints all solutions that are extensions of current
  // leaves grid in original state
  void solve() {
//local variables
int[] currentSquare;
int currentRow;
int currentColumn;
boolean checkConflict;
currentSquare = new int[2];

//saftey limit for testing
int limit;
limit = 0;

while(findEmptySquare() != null){

  currentSquare = findEmptySquare().clone();
  currentRow = currentSquare[0];
  currentColumn = currentSquare[1];
  //System.out.println(" column c:"+currentColumn+" row r:"+currentRow); //column c5 r 3

  if(currentSquare[0] != -1){

    for(int n = 1; n <= ms; n++){
      checkConflict = givesConflict(currentRow, currentColumn, n);
      if(checkConflict == false){
        grid[currentRow][currentColumn] = n;
      }//end if
    }//end for
  }//end if
  else{
    System.out.println("solve: findEmptySquare was -1");
    break;
  }

  //Safety limit
  limit++;
  if (limit > 20){
    System.out.println("break");
    break;
  }//end if

}//end while
  }

  // ------------------------- misc -------------------------

  // print the grid, 0s are printed as spaces
  void printMatrix(){
int ms; //matrix Size
ms = 9;
//layer indication symbols
String end;
String mid;
String cut;
end = "+";
mid = "-";
cut = "";
for(int i = 0; i < 2*ms-1; i++){
  cut = cut + mid;
}//end for

    System.out.println(end+cut+end);
for(int i = 0; i < ms; i++){
  if( i % 3 == 0 && i != 0){
    System.out.println(mid+cut+mid);
  }//end if
  for(int j = 0; j < ms; j++){
    if( j % 3 == 0){
      System.out.print("|");
    }//end if
    else{
      System.out.print(" ");
    }//end else
    if(grid[i][j] != 0){
      System.out.print(grid[i][j]);
    }//end if
    else{
      System.out.print(" ");
    }//end else
  }//end for j
  System.out.print("|");
  System.out.println();
}//end for i
System.out.println(end+cut+end);
  }//end method

  // reads the initial grid from stdin
  void read() {
Scanner sc = new Scanner(System.in);

for (int r=0; r<SIZE; r++) {
  if (r % BOXSIZE == 0) {
    sc.nextLine(); // read away top border of box
  }
  for (int c=0; c < SIZE; c++) {
    if (c % BOXSIZE == 0) {
      sc.next(); // read away left border of box
    }
    String square = sc.next();
    if (".".equals(square)) {
      grid[r][c] = 0;  // empty sqaure
    } else {
      grid[r][c] = Integer.parseInt(square);
    }
    //System.out.print(grid[r][c]);
  }
  sc.nextLine(); // read away right border

}
sc.nextLine(); // read away bottom border
  }

  // --------------- where it all starts --------------------




  void solveIt() {
grid = somesudoku.clone();     // set used grid (before doing anything else)
printMatrix();
solve();
printMatrix();


/* test material
 printMatrix();
 //System.out.println(givesconflict(1,1,3));
 System.out.println(rowConflict(0,1));
 System.out.println(colConflict(0,1));
 System.out.println(boxConflict(0,0,1));
 findEmptySquare();
 */
  }// end solveIt

  public static void main(String[] args) {
new Sudoku().solveIt();
  }
  }

最佳答案

这个问题可以通过回溯来解决。您必须遍历所有可能的选项,但是当您遇到错误的问题时,请从该路径返回。 您可以从此链接找到有关代码的帮助 http://learnfreecodes.blogspot.in/2015/11/sudoku-solver-using-backtracking-in-java.html

关于java - 递归:如何尝试整数 1 到 9 的不同组合,以及(部分)反向序列以在出错时重新开始?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32808915/

有关java - 递归:如何尝试整数 1 到 9 的不同组合,以及(部分)反向序列以在出错时重新开始?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  9. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐