【问题标题】:Towers of Hanoi Program - counter河内塔计划 - 柜台
【发布时间】:2015-04-04 21:32:23
【问题描述】:

我正在做一个河内塔程序 - 在 1 号钉子上有 3 个钉子和一堆圆盘,按从大到小的顺序排列(底部最大,顶部最小)。您现在要做的是将所有磁盘从 peg 1 移动到 peg 3,您可以将 peg 2 用作其他磁盘的存储空间。到目前为止,我已经正确放置了磁盘(每个磁盘都被正确移动),现在我需要创建一个计数器变量,以显示用户输入的特定数量的磁盘需要多少次移动。例如,3 个圆盘至少需要 7 步。

https://www.mathsisfun.com/games/towerofhanoi.html

你可以看到我已经注释掉了一些 Moves++,但是无论我把计数器放在哪里,它似乎都不起作用。

public class TowerOfHanoi

    {//open class

    public void Answer(int numOfDisks, String Peg1, String Peg2, String Peg3, int Moves)
    {//open public void Answer

        Moves++;

        if (numOfDisks == 1)
        {//open if

            //Moves++;      
            System.out.println("\nNumber of Moves so far: " + Moves + "\nMove disk on Peg " + Peg1 + " to Peg " + Peg3);

        }//close if

        else
        {//open else

            //Moves++;
            Answer(numOfDisks - 1, Peg1, Peg3, Peg2, Moves);
            System.out.println("\nNumber of Moves so far: " + Moves + "\nMove disk on Peg " + Peg1 + " to Peg " + Peg3);
            //Moves++;
            Answer(numOfDisks - 1, Peg2, Peg1, Peg3, Moves);

         }//close else

    }//close public void Answer

    public static void main (String[]args)
    {//open main

        TowerOfHanoi TOH = new TowerOfHanoi();  
        String numOfDisks = JOptionPane.showInputDialog(null, "Enter a number!");
        int NumberOfDisks = Integer.parseInt(numOfDisks);
        System.out.println("\nNumber of disks chosen: " + NumberOfDisks);
        int Moves = 0;
        TOH.Answer(NumberOfDisks, "1", "2", "3", Moves);

    }//close main

}//close TowerOfHanoi class

【问题讨论】:

  • 你试过调试了吗?
  • 它并没有太大帮助,只是知道将柜台变量放在哪里
  • 有3个磁盘[D1,D2,D2],开始时D1在最上面,D1每2次移动,D2每4次移动,D3每8次移动......加减1。你需要2^3-1 移动 3 个磁盘。如果你能计算,为什么要计算?对于 N 个磁盘,您需要 2^N-1 次移动。
  • 请向我们展示预期和实际输出的示例。
  • 我运行你的程序,如果你选择 3 作为数字,它有 7 个输出。所以到目前为止的最终移动数应该是7。?

标签: java counter joptionpane towers-of-hanoi


【解决方案1】:

每次移动时增加移动,即在两个 println 语句中的每一个前面,因为它们代表正在移动。 接下来,您需要从您的 Answers 方法中返回 Moves。将return Moves 放在方法的末尾。当您调用该方法时,请执行Moves = Answer(numOfDisks - 1, Peg1, Peg3, Peg2, Moves);

【讨论】:

  • 他已经在每次调用后通过递增计数每一步。
【解决方案2】:

您面临的一个问题是您正在使用递归并将移动计数器推入Answer 的新调用中而没有返回任何内容。返回时移动计数器将恢复其先前的值。

这可以通过返回值来解决,或者通过引入成员变量从我的角度来看更好的解决方案。从参数列表中删除它,并使用公共成员。然后您可以在代码末尾添加 TOH.moves。

然后,您将获得一致的计数,并且可以使用该展示位置,但无需仔细查看您的代码,这似乎是正确的。

【讨论】:

    【解决方案3】:

    为了将最底部(第 n 个)磁盘从 p1 移动到 p3,您首先需要将第 n-1 个磁盘从 p1 移动到 p2(并清理)。然后将 p1 移动到 p3,然后将其余部分从 p2 移动到 p3。

    从这个文字描述中,很明显,您只是在“将 p1 移动到 p3”部分中真正进行了移动。这是你应该增加移动计数器的地方。

    为了以紧凑的形式展示这一点,这里有一个非常简短的 towers of hanoi 版本(认为这是你的 java 程序的快速原型;)它还展示了如何使用函数的返回值来获取 - 这里移动列表 - 在你的情况下,你的柜台。

    let rec hanoi n p1 p2 p3 acc =
        match n with
        | 0 -> acc
        | _ -> 
            hanoi (n-1) p1 p3 p2 acc
            @ [p1,p3]                   // this is where a move is added
            @ hanoi (n-1) p2 p1 p3 acc 
    
    hanoi 3 1 2 3 [] |> List.length
    

    为了便于查看,这里只计算版本:

    let rec hanoi1 n p1 p2 p3 acc =
        match n with
        | 0 -> acc
        | _ -> 
            hanoi1 (n-1) p1 p3 p2 acc
            + 1                   // this is where a move is added
            + hanoi1 (n-1) p2 p1 p3 acc 
    
    hanoi1 3 1 2 3 0
    

    【讨论】:

      【解决方案4】:

      我的两分钱: 您可以尝试迭代程序,这样处理计数器会更容易。你可以take a look here,有一个基于this iterative program 的河内塔的可视化,它被证明可以用最少的步骤解决问题。

      我知道它不在 JAVA 中,但您会发现移植程序并不太难。

      【讨论】:

        【解决方案5】:

        河内解的非迭代塔

        import java.util.Arrays;
        
        public class TowerOfHanoi {
        
            private static int SIZE = 5;
        
            private class stack {
        
                stack(int size) {
                    dataElements = new int[size];
                }
                int[] dataElements;
        
                int top = -1;
        
                private void push(int element) {
                    dataElements[++top] = element;
                }
        
                private int pop() {
                    if(top==-1) {
                        return -1;
                    }
                    int topEle = dataElements[top];
                    dataElements[top]=0;
                    top --;
                    return topEle;
                }
        
                private int top() {
                    if(top==-1) {
                        return -1;
                    }
                    return dataElements[top];
                }
        
                private boolean isEmpty() {
                    return top == -1;
                }
            }
        
            public static void main(String[] args) {
                towerOfHanoi(SIZE);
            }
        
            private static void towerOfHanoi(int number) {
                initialize(number);
                if(number % 2 == 0) {
                    solveEven(number);
                } else {
                    solveOdd(number);
                }
            }
        
            private static int recentMoved = -1;
        
            private static stack source = new TowerOfHanoi().new stack(SIZE);
            private static stack intermediate = new TowerOfHanoi().new stack(SIZE);
            private static stack destination = new TowerOfHanoi().new stack(SIZE);
        
            private static void solveEven(int number) {
        
                while(destination.top < number-1) {
                    if(!movePlates(source, intermediate, destination)) {
                        if(!movePlates(intermediate,destination,source)) {
                            if(!movePlates(destination, source, intermediate)){
                                continue;
                            }
                        }
                    }
                }
        
            }
        
        
        
            private static boolean movePlates(stack from , stack dest1 ,stack dest2) {
                boolean movedPlate = false;
                if(from.top()== recentMoved) {
                    return movedPlate;
                }
                if((!from.isEmpty()) && from.top()<(dest1.top()==-1?10000:dest1.top())) {
                    dest1.push(from.pop());
                    recentMoved=dest1.top();
                    movedPlate = true;
                }
                else if((!from.isEmpty()) && from.top()<(dest2.top()==-1?10000:dest2.top())){
                    dest2.push(from.pop());
                    recentMoved=dest2.top();
                    movedPlate = true;
                }
                if(movedPlate)
                    display();
                return movedPlate;
            }
        
            private static void display() {
                Arrays.stream(source.dataElements).forEach(System.out::print);
                //.stream().fl.forEach(System.out::print);
                System.out.print("\t");
                Arrays.stream(intermediate.dataElements).forEach(System.out::print);
                System.out.print("\t");
                Arrays.stream(destination.dataElements).forEach(System.out::print);
                System.out.print("\n");
            }
        
        
            private static void initialize(int number) {
                for(int i=number;i>0;i--) {
                    source.push(i);
                }
            }
        
            private static void solveOdd(int number) {
                while(destination.top < number-1) {
                    if(!movePlates(source, destination, intermediate)) {
                        if(!movePlates(destination,intermediate,source)) {
                            if(!movePlates(intermediate, source, destination)){
                                continue;
                            }
                        }
                    }
                }
        
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-07
          相关资源
          最近更新 更多