【问题标题】:Java: Remembering a result from a previous step in a recursive methodJava:在递归方法中记住上一步的结果
【发布时间】:2013-01-22 22:40:10
【问题描述】:

我正在开发一个 Boggle 游戏,有人告诉我搜索单词的最佳方法是使用递归。我正在尝试使用 searchWord 方法来搜索单词。如果找到第一个字母,该方法会调用自身并删除第一个字母。当长度 == 0(找到单词)或 false(未找到字母)时,该方法返回 true。问题有时令人难以置信,一个“骰子”周围有多次相同的字母......为了解决这个问题,我需要计算那个字母,如果它不止一次,它应该搜索那个字母的下一个出现(搜索同一个词,不丢首字母)。我需要一种方法来记住该字母和多个字母所围绕的字母的索引,以便在找不到字母时可以使用它来检查是否还有其他可能性。由于它是一种递归方法,我不知道如何将它们放入变量中,因为只要方法调用自身,它们就会被更改......

希望大家帮忙!方法如下:

public boolean searchWord(String word, int i, int j) {
    boolean res;
    if (word.length() == 0) {
        res = true;
    } else {
        String theWord = word.toUpperCase();
        int[] indexes = searchLetter(Character.toString(theWord.charAt(0)), i, j);
        if (indexes[0] > -1) {
            res = searchWord(theWord.substring(1), indexes[0], indexes[1]);
        } else if(countLetter(Character.toString(/*The value that has to be memorized*/), /*index 1 that has been memorized*/, /*index 2 that has been memorized*/) > 1) {
            res = searchWord(theWord, i, j);
        } else {
            res = false;
        }
    }
    return res;
}

注意:是的,我使用的是奇怪的字符串,因为字符可能是更好的选择,但我可以稍后更改。

【问题讨论】:

    标签: java arrays recursion boggle


    【解决方案1】:

    原则上,您可以将任何此类值作为附加参数传递。这样,参数/调用堆栈就充当了您的堆栈。

    【讨论】:

      【解决方案2】:

      只需在您的方法中添加另一个参数。例如,您可以创建一个仅包含字母和 int 的对象。由于Java在进行递归调用时只传递对该对象的引用(但不复制对象本身),所以参数将始终指向同一个对象。您可能想使用 Java 的 pair 类(如果我没记错的话,它是在地图中使用的)。

      【讨论】:

      • 但我不能只做广告String previous = word 对吧?因为这会改变每个电话?因为我真的不明白你的意思:s
      • 向我们展示你的优雅代码,Dan。随意包含 LISP 版本。
      【解决方案3】:

      目标:查看 Boggle 板上是否存在单词

      假设:

      • 每个位置(即立方体)每个单词只能使用一次

      • 每个字母必须相邻 (垂直、水平或对角线)

      这是我对使用递归执行此操作的伪代码的尝试(其中 boggle 板是一个二维字符数组 - 在调用此方法之前应该已经填充了字符):

      // searches for a single occurence of a word on the boggle board
      boolean searchWord(String word, char[][] board)
          for each position on the board (x,y)
              boolean[][] visited = new boolean[width][height] // all false
              if (searchWord(x,y,board,visited))
                  return true
          return false
      
      // searches a position on the board
      boolean searchWord(String word, int x, int y, char[][] board, boolean[][] visited)
          if x and y are valid (0 >= x < width and 0 >= y < height)
              if visited[x][y] == false
                  visited[x][y] = true
                  if the letter at x,y equals the 1st char of the search word
                      if word.length() == 1
                          return true
                      else
                          for each surrounding position (x2, y2)
                              if searchWord(word.substring(1),x2,y2,board,visited)
                                  return true
          return false
      

      正如您所见,递归是寻路(查找难以理解的单词)的不错选择。您只需要传递当前状态(在本例中为 visited 数组),就可以知道您已经到过哪里了。

      我已经使用参数来存储状态,但如果你真的需要,你可以使用实例变量。我建议使用参数,因为它符合函数式编程范式,并且不太可能遭受意想不到的副作用。

      这里不需要显式使用堆栈。当值具有scope(如Java 中的局部变量)并且应该以特定顺序访问时,堆栈非常有用,这在这里并没有真正的帮助。仅供参考,通过使用递归,无论如何你都在使用 Java 的调用堆栈,如果你不小心,你可以永远递归,你会得到一个 StackOverflowException ;)

      【讨论】:

      • 听起来不错!我不太确定我应该用你的代码做什么,虽然我想尝试一下,但我不确定在“每个周围位置”之类的地方填写什么:s
      【解决方案4】:

      您应该重写它以使用堆栈。递归几乎总是用堆栈更好地完成。然后,您可以存储有关上下文的一些信息,并将需要更多处理的内容推送到堆栈中,并在您准备好处理它们时将其弹出。

      【讨论】:

      • 我给我的老师发了邮件,他说最好用递归来完成,虽然这很困难。我还没有真正了解堆栈,或者我真的不明白你的意思。我还是个初学者(在校只有 3-4 个月的 java):s
      • 好的。那么让我帮助递归。递归的问题是您没有存储您所在位置的任何帧。堆栈是一种使用 LIFO(后进先出)的数据结构:将事物压入堆栈,然后将它们弹出。例如,如果你编写一个解析器,堆栈允许你维护尽可能多的上下文信息,这些信息是关于你在 AST(抽象语法树)中构造的每个节点的。
      • 出于多种原因,Rob 的抱怨通常不属实。首先,在许多情况下,就代码的清晰性而言,递归是更优雅的方式。其次,与使用堆栈时实例化多个对象相比,进行方法调用非常便宜(是的,调用推送也是方法调用)。
      • 是的,传递东西要优雅得多,以降低对象的成本,感谢 Neaderthal 先生的参与。你在教他所有正确的东西。
      • 我不知道如何解决这个问题,我变得非常绝望。两天来我一直在思考如何检测多个边界字母以及如何从二维数组中获取所有可能性。我真的不知道该怎么办,我在浪费时间该死的!这是一个项目,但显然我选择了错误的游戏:/
      猜你喜欢
      • 2014-05-03
      • 1970-01-01
      • 2023-03-28
      • 2017-07-07
      • 2018-10-29
      • 2023-03-14
      • 2023-03-31
      • 2018-02-18
      • 1970-01-01
      相关资源
      最近更新 更多