//hanoi2ok.java, by tsaiwn@csie.nctu.edu.tw
// <applet code = hanoi2ok.class  width=500 height=320>
import java.io.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class hanoi2ok extends Applet implements ActionListener,
                                     KeyListener {
  static boolean isApplet = true, shouldDie = false;
  public static void main(String xxx[ ]) {
     isApplet = false;
     new hanoi2ok( );
  }

 TextArea tx;
 TextField tf;
 Button bStart = new Button("Start"), bStop= new Button("Stop");
 PrintStream cout=null;
 BufferedReader br = null;

 public hanoi2ok( ) {
    prepareIO( ); shouldDie = false;
    main( );
 }

 void prepareIO( ){
    cout = System.out;
    if(!isApplet) {  // Java application
       try{
           br = new BufferedReader(
                  new InputStreamReader(System.in) );
       }catch(Exception e) { System.exit(38); }
       return;
    }//if(!isApplet
    tx= new TextArea(" Tower of Hanoi, by tsaiwn@csie.nctu.edu.tw", 
                 12,58,TextArea.SCROLLBARS_BOTH);
    tx.append("\r\n");
    add("Center", tx);
    tx.setForeground(Color.blue);
    tx.setFont(new Font("",Font.BOLD,18) );
    bStart.setFont(new Font("",Font.BOLD,15) );
    bStart.setForeground(Color.blue);
    bStop.setFont(new Font("",Font.BOLD,16) );
    bStop.setForeground(Color.red);
    Panel p = new Panel( ); 
    tf = new TextField(2);  
    p.setBackground(Color.yellow);
    p.add(tf); p.add(bStart); p.add(bStop);
    bStart.addActionListener(this); bStop.addActionListener(this);
    tf.addKeyListener(this);
    add("South", p);
    setVisible(true);
 }// prepareIO(

// hanoi.c  -- Hanoi tower, @CopyLeft by tsaiwn@csie.nctu.edu.tw
//Hanoi Tower(河內之塔) -- 神奇的 Recursive -- 自己叫自己 !
//關於 Hanoi Tower, 請用 http://gogle.com 打入 "hanoi tower"  查詢
//注意用雙引號夾住如 "hanoi tower" 查到的才是你要的 :-)
//或是直接看這  http://en.wikipedia.org/wiki/Tower_of_Hanoi
///
//void moveOne(int px, int py, int ); //3rd parameter is the disk#
void hanoi(int n, int pa, int pc, int pb) {
    if(n==0 || shouldDie) return;    // there is no disk
    hanoi(n-1, pa, pb, pc);  // 先幫我把上面 n-1 disks 搬走
    moveOne(pa, pc, n);   /// move the n-th disk from pa to pc
    hanoi(n-1, pb, pc, pa); // move n-1 disks from pb to pc
} // hanoi


//#include <stdio.h>
void moveOne(int px, int py, int n ) {  // the n-th disk
   String p123[ ] = {"th", "st", "nd", "rd"}; // -th, Fir-st, Seco-nd, -rd
   String pABC[ ] = {"A", "B", "C"}; // A B C
   int k = n%10;
   if(k!=1  && k!=2 && k!=3) k = 0;  // -th
   cout.printf("Move %d-%s disk from %c  to  %c \n", n,p123[k], px, py);
   if(isApplet){
      tx.append( "\t  Move " + n + "-" + p123[k] + " disk from "  + 
           pABC[px-'A'] +  " to " + pABC[py-'A'] + "\r\n");
   }//if
}//moveOne

int getInt( ) {   // static char buf[99];
   if(isApplet) return 0;
   String buf = null;
   int ans=0;
   // fgets(buf, sizeof(buf), stdin); ans=atoi(buf);
   try {
      buf = br.readLine( );
      ans = Integer.parseInt(buf);
   }catch(Exception e) { ans = 3; }
    // 如果把 ans = 3; 改為 ans = 64; 你認為會做多久? ? ?
   return ans;  //若一秒只能搬一個動作, 則需約 600 billion(六千億) years
}
int main( ) {
    int n=0; 
    cout.print(" n=? ");
    n = getInt( );  // read an int into n
    hanoi(n, 'A', 'C', 'B'); // move n disks on peg 'A' to peg 'C'
    return 0;
}//main(

public void actionPerformed(ActionEvent e) {
  if(e.getSource( ) == bStop) { shouldDie = true; return; }  // Stop
  int n = 3;
  String t = tf.getText( );
  try { if(t!=null) t = t.trim( );
     n = Integer.parseInt( t );
  }catch(Exception ee){ n = 3; tf.setText(" 3");
     tf.setForeground(Color.red);
  }
  shouldDie = false;
  new YY(this, n).start( );  /// <======= 弄個小弟去 hanoi(n,... 
}//actionPerformed(
 public  void keyPressed(java.awt.event.KeyEvent ea){
    bStart.setBackground(Color.red);
    char c = ea.getKeyChar( );
    if( Character.isDigit(c) ) {
        //c is a digit 
    }else{ if(c != KeyEvent.VK_BACK_SPACE)
       Toolkit.getDefaultToolkit().beep();     // 叫一聲 
    }
 } // keyPresses or keyDown
 public  void keyReleased(java.awt.event.KeyEvent eb){
    bStart.setBackground(Color.white);
    //bStart.setForeground(Color.red);
 }// keyReleased or keyUp
 public  void keyTyped(java.awt.event.KeyEvent ec){ }//keyTyped
} // class

class YY extends Thread {
   static boolean isMoving=false;  // shared variable
   hanoi2ok him = null;  int n=0;     /// <======
  YY(hanoi2ok uu, int n){ him = uu;   this.n = n; }    /// <======
  public void run( ) {
       if(isMoving) return; else isMoving = true;
       him.tx.setForeground(Color.red);
       him.tx.append("\n------\r\n\tDoing Hanoi "+n+" ...\r\n\n");
       try{Thread.sleep(568);}catch(Exception e3){ }
       him.tx.setForeground(Color.blue);
       him.hanoi(n, 'A', 'C', 'B');     /// <======
       him.tx.append("\n\t === Hanoi " + n + " done. ===\r\n");
       isMoving=false;   /// <======
  }// run(
}// class YY
