【问题标题】:Correct declaration of variables in recursive knights tour (Java homework)在递归骑士之旅中正确声明变量(Java 作业)
【发布时间】:2012-05-20 09:45:17
【问题描述】:

我在我学年的最后一个项目(我作为 CS 学生的第一年)的代码中找不到错误。我在执行骑士巡回问题时陷入了递归。这是有问题的文件:https://github.com/sheagunther/tsp161knightstour/blob/master/KnightsTourRecursiveSearch.java

具体来说,我的问题在于这部分代码(从第 265 行开始):

   else{
   for(int i = 0; i < numberOfPossibleNextMoves; i++){
      Cell nextCellToMoveTo = candidateNextMoves.get(i);

      int currentRowStorage = currentRow;
      int currentColumnStorage = currentColumn;
      currentRow = nextCellToMoveTo.row;
      currentColumn = nextCellToMoveTo.column;

      listOfMoves.add(nextCellToMoveTo);
      chessBoard[currentRow][currentColumn] = 1;
      currentMoveNumber++;

      boolean tourFound = findTour();

      if(tourFound){
         return true;
            }
            else{ // Undo the last move just made
               backtrackCount++;
               chessBoard[currentRow][currentColumn] = -1;
               currentRow = currentRowStorage;
               currentColumn = currentColumnStorage;                           
               listOfMoves.remove(nextCellToMoveTo);
               currentMoveNumber--;         
            }
         }
         return false;

findTour() 结束。这是程序的一部分,它测试从当前方格(也称为单元格)的所有可能移动,如果可以从新移动到的方格完成游览,则返回 true。如果不能从广场完成游览,它会进入 else{ 并撤消移动。这就是我认为的问题所在。

现在,按照上面的代码设置,程序陷入了无限递归循环。

注意else{ 声明的这一部分:

chessBoard[currentRow][currentColumn] = -1;
currentRow = currentRowStorage;
currentColumn = currentColumnStorage;

这部分代码将chessBoard中的方块更改为-1,这意味着它未被访问(1 =已访问)。如上所示,新移动的 currentRow 和 currentColumn 用于将方格设置回未访问状态。然后使用 currentRowStorage 和 currentColumnStorage 将这些值重置为先前的跳转值。

如果我将代码更改为

currentRow = currentRowStorage;
currentColumn = currentColumnStorage;
chessBoard[currentRow][currentColumn] = -1;

它成功地找到了一个错误的路线,其中最后 1/3 左右的移动只是在几个方格之间来回跳跃。这是意料之中的,因为它没有正确处理重置过程。

我怀疑我的问题是由于我声明变量的位置。这是我的第一个复杂递归问题,我不确定我是否正确处理了 currentRow/Column 和 currentRow/ColumnStorage 之间的切换。我应该在本地或多或少地声明它们吗?

这里是描述项目的页面:http://cs.usm.maine.edu/~briggs/webPage/c161/projects/KnightsTour.html

这里是要求的相关部分:

如果游览未完成,则 findTour 确定(可能 空)可从骑士到达的空单元列表 当前单元格,并将此列表存储在本地声明的列表中 变量,候选人NextMoves。此列表变量至关重要 声明为方法的本地。如果这个列表是空的,那么有 没有办法延长当前的部分游览,所以 findTour 应该返回 错误的。如果列表不为空,则 findTour 尝试扩展 列表中的每个移动游览如下。它遍历列表, 并且对于列表中的每个单元格,它会下一次移动到该单元格, 更新所有 L(旅行中的移动列表),B(二维数组 董事会的状态(已访问,未访问))、currRow 和 currCol 到 反映这一举动。然后它递归地调用自己,分配 调用本地声明的布尔变量的结果,您 可能会命名为“成功”。如果成功为真,findTour 返回 真的。如果成功为假,findTour 会撤消它刚刚所做的移动,或者 “回溯”,并尝试 CandidateNextMoves 的下一步动作。你会 维护一个静态 int 变量 backtrackCount,该变量已初始化 为 0,并随着移动的每次撤消而递增。

一个注释-我将我的布尔值称为“tourFound”而不是“成功”。

【问题讨论】:

  • 请写到重点,准确而简短。
  • @BhavikAmbani 这个问题实际上写得相当好——不过它可以使用一些格式来提高可读性。
  • @BhavikAmbani 我认为清楚地列出我遇到的问题的细节并尽可能简洁地做到这一点很重要。
  • @BhavikAmbani 您认为这是我的问题,这可能表明您在评论之前甚至没有仔细阅读它。
  • @BhavikAmbani 这不是真的,我读了整本书。我认为这是一个写得很好的问题。

标签: java recursion knights-tour


【解决方案1】:

与无限递归的情况一样,首先要检查的是您计划如何摆脱它的条件。在这种情况下,只有在

if(currentMoveNumber == numberOfMovesOnBoard){
     return true;
  }

检查您的算法和初始化是否会阻止 currentMoveNumber 达到 numberOfMovesOnBoard。

提示:在你进入递归方法之前,你的起始条件是什么?

【讨论】:

  • 太棒了!谢谢你的建议,我去看看。
  • 我发现我的 numberOfMovesOnBoard 偏离了 1。我将它设置为平方数。如果要关闭巡回赛,那是正确的数量-如果骑士回到他跳到的第一个方格,但是由于我的代码现在正在寻找一个开放的解决方案,因此棋盘上的移动数是平方数减 1。这还没有解决问题,但很好解决。向前和向上。
  • 我认为我的问题尚未解决,但它确实成功地找到了 5x5 板的游览。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多