2017-10-03 3 views
0
public static enum Action { 
    No, LToM, MToL, MToR, RToM 
} 

public static int hanoiProblem2(int num, String left, String mid, String right) { 
    Stack<Integer> lS = new Stack<Integer>(); 
    Stack<Integer> mS = new Stack<Integer>(); 
    Stack<Integer> rS = new Stack<Integer>(); 
    lS.push(Integer.MAX_VALUE); 
    mS.push(Integer.MAX_VALUE); 
    rS.push(Integer.MAX_VALUE); 
    for (int i = num; i > 0; i--) { 
     lS.push(i); 
    } 
    Action[] record = { Action.No }; 
    int step = 0; 
    while (rS.size() != num + 1) { 
     step += fStackTotStack(record, Action.MToL, Action.LToM, lS, mS, left, mid); 
     step += fStackTotStack(record, Action.LToM, Action.MToL, mS, lS, mid, left); 
     step += fStackTotStack(record, Action.RToM, Action.MToR, mS, rS, mid, right); 
     step += fStackTotStack(record, Action.MToR, Action.RToM, rS, mS, right, mid); 
    } 
    return step; 
} 

public static int fStackTotStack(Action[] record, Action preNoAct, 
           Action nowAct, Stack<Integer> fStack, Stack<Integer> tStack, 
           String from, String to) { 
    if (record[0] != preNoAct && fStack.peek() < tStack.peek()) { 
     tStack.push(fStack.pop()); 
     System.out.println("Move " + tStack.peek() + " from " + from + " to " + to); 
     record[0] = nowAct; 
     return 1; 
    } 
    return 0; 
} 

public static void main(String[] args) { 
    int num = 4; 

    // solution 2 
    int steps2 = hanoiProblem2(num, "left", "mid", "right"); 
    System.out.println("It will move " + steps2 + " steps."); 
    System.out.println("==================================="); 

} 

これは、ハノイの塔を解くためのコードです。 3つのスタックを使用して3つのタワーをシミュレートします。 私の質問は、レコード変数を配列として定義するのはなぜですか? アクション[] record = {Action.No}; レコード[0] = nowAct;スタックを使用してハノイの塔を解決する(java)

私は アクションレコード= Action.Noにそれらを変更しようとしました。 record = nowAct; このコードは実行されません。

私は理由を知りません。誰かが理由を説明できると本当に感謝しています。おかげさまで その値がfStackTotStackメソッド内で変更されているため

+1

私が言及するのを忘れてもう一つの条件は、この質問であります。ディスクは、右またはワンステップで右から左に、左から移動することはできません。中から左に、または中から左に左に置く必要があります。 –

+0

'{Action.No}'は1つの要素を含む配列で、 'Action []'と入力します。 'Action.No'と同じではなく、' Action'と入力します。 –

+0

私はそれがレコード[0]を使用したことを意味します。配列から変数に 'レコード'を変更できますか?ありがとうございました。 –

答えて

0

はあなたの例では、recordは配列として定義されます。

最も簡単な説明は、Javaがで変数を渡し、参照ではないためです。オブジェクト参照も値で渡します。例えば

取る、次のコード

public void foo(int bar) { 
    bar += 4; 
    System.out.println("Foo's bar: " + bar); 
} 

public static void main(String[] args) { 
    int bar = 5; 
    new Foo().foo(bar); 
    System.out.println("Main's bar: " + bar); 
} 

これは、印刷されます

Foo's bar: 9 
Main's bar: 5 

foo関数内bar変数は内部とは異なる変数であるためでありますmain機能です。メソッドが呼び出されると、値がコピーされます。

あなたは配列を渡すときに、変数自体はまだ異なります、fooのバーはメインのバーよりも異なるため

public void foo(int[] bar) { 
    bar = new int[]{9}; 
    System.out.println("Foo's bar: " + bar[0]); 
} 

public static void main(String[] args) { 
    int[] bar = {5}; 
    new Foo().foo(bar); 
    System.out.println("Main's bar: " + bar[0]); 
} 

これは、前と同じ結果が得られます。

しかし、オブジェクト参照は、値によって渡されます。つまり、変数は異なりますが、変数が表す値は同じです。したがって、この:

public void foo(int[] bar) { 
    bar[0] += 4; 
    System.out.println("Foo's bar: " + bar[0]); 
} 

public static void main(String[] args) { 
    int[] bar = {5}; 
    new Foo().foo(bar); 
    System.out.println("Main's bar: " + bar[0]); 
} 

以前よりも別の何かを出力します:fooというのbar変数とメインのbar変数は異なる変数でありながら、彼らは同じ基礎となるオブジェクトを指しているため

Foo's bar: 9 
Main's bar: 9 

です。そのため、変数だけでなく、オブジェクトそのものの変更も持続します。上記のあなたの例で

、ラインAction[] record = { Action.No };fStackTotStackメソッドに渡される配列を作成しています。可変record自体が変更されていないので(何record = new Action[] {}どこにも存在しない)、それが指す配列はまだ渡されたものと同じです。つまり、オブジェクト自体(この場合は配列)を変更することができます。

Here is an article that can explain it better than I can.

関連する問題