/****************************************************************************************** Hanoi.java - Tower of Hanoi puzzle Version 2.0 www.mazeworks.com Copyright (c) 2002 Robert Kirkland All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice and this permission notice appear in all copies of the Software and that both the above copyright notice and this permission notice appear in supporting documentation. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of the copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. Added 1/29/2014 By Jerrold Siegel: This is an application version of my applet code which, in turn, was just an update of the original applet code with only one runtime bug found and fixed. One example of a change is BoardCanvas extends Canvas becomes BoardCanvas extends JPanel and paint becomes paintComponent. There is also some relativization eg. bufferImage=Toolkit.getDefaultToolkit().getImage(System.getProperty("user.dir").replace('\\','/')+"/"+"blue.gif"); I also used "disk" rather than "disc" ******************************************************************************************/ import java.io.*; import java.awt.* ; import java.awt.event.*; import java.awt.event.MouseListener; import javax.swing.JFrame; import javax.swing.JPanel; /******** HANOI ******** main class: initializes panel, starts games, runs autosolve thread, handles disc moving events */ public class Hanoi extends JPanel implements Runnable, Serializable { public static final long serialVersionUID = 42123L; public int[][] diskArray=new int[3][50]; //peg - disk public int [][] theDisks= new int[50][3]; //x-y-witdth public int[] dragDisk =new int[4]; public int[] present_peg_count=new int[3]; public String getAppletInfo() { return "Tower of Hanoi 2.0 - Copyright (c) 2002 Robert Kirkland";} String parameterInfo[][] = { {"bgColor", "integer", "Applet background color (24-bit RGB hex int)"}, {"boardBgColor", "integer", "Board background color (24-bit RGB hex int)"}, {"title", "string", "Applet title text"}, {"discs", "string", "Discs label text"}, {"plus", "string", "Discs Plus button text"}, {"minus", "string", "Discs Minus button text"}, {"restart", "string", "Restart button text"}, {"solution", "string", "Solution button text"}, {"speed", "string", "Speed label text"}, {"timer", "string", "Timer label text"}, {"moves", "string", "Moves label text"}, {"instruct", "string", "Instructions status text"}, {"solving", "string", "Solve in progress status text"}, {"finished", "string", "Solve finished status text"}, {"minimum", "string", "Minimum moves status text"}, {"win", "string", "Puzzle solved status text"}, {"perfect", "string", "Minimum moves solution status text"}} ; public String[][] getParameterInfo() { return parameterInfo ;} public Graphics graphics; //Hanoi newContentPane; JFrame frame; Color DF_BG_COLOR=Color.white ; // default background color Color DF_BOARD_BG_COLOR=new Color(0xFFCC99) ; // default background color FFCC99 String DF_TITLE ="Tower of Hanoi"; // default text strings int DF_WIDTH =550; // default text strings int DF_HEIGHT =310; // default text strings String DF_DISCS ="DISCS", DF_PLUS ="+", DF_MINUS ="-", DF_RESTART="RESTART", DF_SOLUTION="SOLUTION", DF_SPEED ="SPEED", DF_TIMER ="TIMER", DF_MOVES ="MOVES", DF_INSTRUCT="Move all discs to the rightmost peg.", DF_SOLVING ="Solving ...", DF_FINISHED="Finished !", DF_MINIMUM ="The minimum number of moves required is", DF_WIN ="Done ! Now try for the minimum number of moves.", DF_PERFECT ="Congratulations !" ; static final Font titleFont=new Font("Helvetica", Font.BOLD, 12), textFont=new Font("Helvetica", Font.PLAIN, 11), monoFont=new Font("Courier", Font.BOLD, 12), statusFont=new Font("Dialog", Font.PLAIN, 12) ; static final int CANVAS_WIDTH=450, CANVAS_HEIGHT=250, TABLE_TOP=225, PEG1=0, PEG2=1, PEG3=2, MIN_DISCS=3, MAX_DISCS=12 ; protected Color BG_COLOR, BOARD_BG_COLOR ; protected String TITLE, DISCS, PLUS, MINUS, RESTART, SOLUTION, SPEED, TIMER, MOVES, INSTRUCT, SOLVING, FINISHED, MINIMUM, WIN, PERFECT ; private boolean gameOver ; private int sourceDisc, sourcePeg, targetPeg ; private String gameStatus ; private Panel cpBack, titlePanel ; private Label titleLabel ; public Board bd ; public BoardCanvas bc ; private StatusPanel sp ; private ControlPanel cp ; private Image boardImage ; private Thread solveThread; private Timer timer ; public void mouseExited(MouseEvent e) { return ;} public void resettimer(){ timer.isRunning=false; } public static void main(String[] args) { new Hanoi(); } public Hanoi(){ super(new BorderLayout()); frame = new JFrame("Tower of Hanoi"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); init(); //The actual Puzzle. frame.setContentPane(this); // frame.setSize(450,250); frame.getContentPane().setBackground(Color.BLUE); //Display the window. frame.pack(); frame.setVisible(true); } public void init() { BG_COLOR = DF_BG_COLOR ; BOARD_BG_COLOR = DF_BOARD_BG_COLOR ; TITLE = DF_TITLE ; DISCS = DF_DISCS; PLUS = DF_PLUS; MINUS = DF_MINUS ; RESTART = DF_RESTART; SOLUTION = DF_SOLUTION; SPEED = DF_SPEED; TIMER = DF_TIMER; MOVES = DF_MOVES; INSTRUCT = DF_INSTRUCT ; SOLVING = DF_SOLVING ; FINISHED = DF_FINISHED ; MINIMUM = DF_MINIMUM ; WIN = DF_WIN; PERFECT = DF_PERFECT ; // load board image MediaTracker tracker = new MediaTracker(this) ; boardImage = Toolkit.getDefaultToolkit().getImage(getClass().getResource("blue.gif")) ; tracker.addImage(boardImage,0) ; try { tracker.waitForID(0); } catch (InterruptedException e) { } setBackground(BG_COLOR) ; setOpaque(true); //content panes must be opaque Panel mainPanel = new Panel() ; mainPanel.setLayout(new BorderLayout(0,0)) ; // BoardCanvas bc = new BoardCanvas(this) ; bc.setSize(new Dimension(CANVAS_WIDTH,CANVAS_HEIGHT)) ; // Title panel titlePanel = new Panel() ; titlePanel.setLayout(new GridLayout(1,1)) ; titlePanel.setBackground(Color.lightGray) ; titlePanel.setFont(titleFont) ; titlePanel.add(titleLabel=new Label(" "+TITLE,Label.LEFT)) ; titleLabel.setForeground(Color.black) ; // Control Panel cpBack = new Panel() ; cpBack.setLayout(new FlowLayout(FlowLayout.CENTER,10,5)) ; cpBack.setBackground(Color.lightGray) ; cp = new ControlPanel(this) ; cpBack.add(cp) ; // Status panel sp = new StatusPanel(this) ; sp.setBackground(Color.lightGray) ; // construct applet panel Panel p1 = new Panel() ; p1.setLayout(new FlowLayout(FlowLayout.CENTER,10,10)) ; mainPanel.add("Center",bc) ; mainPanel.add("North",titlePanel) ; mainPanel.add("East",cpBack) ; mainPanel.add("South",sp) ; p1.add(mainPanel) ; add(p1) ; validate() ; newGame() ; } // startup void newGame() { int discs = cp.getDiscs() ; System.gc() ; gameOver = false ; bd = new Board(discs,this) ; present_peg_count=new int[3]; diskArray=new int [3][50]; theDisks=new int[50][3]; bc.drawBoard(bd,boardImage,0,0,0) ; sp.setMoveCount(0) ; timer=null; timer = new Timer(cp) ; cp.startTime = System.currentTimeMillis() ; if (solveThread == null) sp.setStatus(INSTRUCT) ; bc.requestFocus() ; } // handle Reset event void restartGame() { stop() ; cp.setAutoSolveEnable(true) ; newGame() ; } // kill all threads public void stop() { if (solveThread!=null) { //solveThread.stop() ; solveThread = null ; } if (timer!=null) { timer.isRunning=false; timer = null ; } } // spawn Autosolve thread public void startSolveThread() { stop() ; solveThread = new Thread(this) ; solveThread.start() ; } // run Autosolve thread public void run() { newGame() ; sp.setStatus(SOLVING) ; solve(cp.getDiscs(),PEG1,PEG2,PEG3) ; sp.setStatus(FINISHED) ; gameOver = true ; solveThread = null ; cp.setAutoSolveEnable(true) ; } // here's the famous algorithm void solve(int discs,int source,int aux,int target) { if (discs==0) return ; // base to end recursion solve(discs-1,source,target,aux) ; // recursive call #1 bd.moveDisc(source,target) ; // move disc sp.setMoveCount(bd.getMoveCount()) ; // update display bc.drawBoard(bd,boardImage,0,0,0) ; try { solveThread.sleep(cp.getDelay()) ; } // Autosolve delay catch (InterruptedException e) { } solve(discs-1,aux,source,target) ; // recursive call #2 } // handle mouse drag event void dragDisc(int x,int y) { if (!gameOver&&(sourceDisc!=0)) { dragDisk[0]=sourceDisc;dragDisk[1]=x;dragDisk[2]=y;dragDisk[3]=theDisks[sourceDisc][2]; //System.out.println(dragDisk[0]+" "+dragDisk[1]+" "+dragDisk[2]+" "+dragDisk[3]); bc.drawBoard(bd,boardImage,0,0,0) ; } } // handle mouse down event void selectDisc(int x,int y) { if (!gameOver&&(solveThread==null)) { if ((timer!=null)&&(!timer.isAlive())) timer.start() ; sourcePeg = pixelToPeg(x,y) ; if (bd.isStartPeg(sourcePeg)) { sourceDisc = bd.getTopDisc(sourcePeg) ; dragDisk[0]=sourceDisc;dragDisk[1]=theDisks[sourceDisc][0];dragDisk[2]=theDisks[sourceDisc][1];dragDisk[3]=theDisks[sourceDisc][2]; //System.out.println(dragDisk[0]+" "+dragDisk[1]+" "+dragDisk[2]+" "+dragDisk[3]); bc.drawBoard(bd,boardImage,0,0,0) ; // bc.drawBoard(bd,boardImage,sourceDisc,x,y) ; } } } // handle mouse up event void dropDisc(int x,int y) { dragDisk[0]=0; if (!gameOver&&(sourceDisc!=0)) { targetPeg = pixelToPeg(x,y) ; if (bd.moveDisc(sourceDisc,sourcePeg,targetPeg)) { gameStatus = bd.getBoardStatus() ; sp.setMoveCount(bd.getMoveCount()) ; if (gameStatus==null) sp.setStatus(MINIMUM + " " + bd.getMinMoves() + ".") ; else { gameOver = true ; stop() ; sp.setStatus(gameStatus) ; } } bc.drawBoard(bd,boardImage,0,0,0) ; sourceDisc = 0 ; } } // conversion for mouse down/up events int pixelToPeg(int x,int y) { int peg = -1 ; if ((y>40)&&(y<TABLE_TOP)) { if ((x>50)&&(x<100)) peg = PEG1 ; else if ((x>200)&&(x<250)) peg = PEG2 ; else if ((x>350)&&(x<400)) peg = PEG3 ; } return peg ; } } /******** TIMER ******** controls Timer thread */ class Timer extends Thread { static final int ONE_SECOND=1000 ; // public long startTime; private long rem ; private int hours, min, sec ; private String sMin, sSec, sTime ; private ControlPanel cp ; public boolean isRunning=true; Timer(ControlPanel cp) { this.cp = cp ; cp.setTimer(setTime(0)) ; } // run thread public void run() { cp.startTime = System.currentTimeMillis() ; while (isRunning) { try { Thread.sleep(ONE_SECOND) ; } catch (InterruptedException e) { } if ( cp.isTimerOn()) { cp.setTimer(setTime(System.currentTimeMillis() - cp.startTime)) ; } } } // return h:mm:ss string from milliseconds String setTime(long millisec) { hours = (int)(millisec/3600000) ; rem = millisec - (hours*3600000) ; min = (int)(rem/60000) ; rem = rem - (min*60000) ; sec = (int)(rem/1000) ; sMin = Integer.toString(min) ; if (sMin.length()==1) sMin = "0" + sMin ; sSec = Integer.toString(sec) ; if (sSec.length()==1) sSec = "0" + sSec ; sTime = " " + Integer.toString(hours) + ":" + sMin + ":" + sSec ; return sTime ; } } /******** BOARD ******** controls disc positions, rules for moving discs */ final class Board { public static final long serialVersionUID = 421233L; int PEGS=3, DISC_SIZES[][]={ {68,18},{76,16},{84,14},{92,13},{100,12}, {108,12},{112,11},{116,10},{120,9},{124,9}} ; private int peg[][], pegTop[]=new int[PEGS], discWidth[] ; private int discs, moveCount, minMoves ; private Hanoi main ; // constructor Board(int discs,Hanoi main) { this.discs = discs ; this.main = main ; peg = new int[discs][PEGS] ; // put all the disks on the first peg for (int i=0; i<discs; i++) peg[i][Hanoi.PEG1] = discs-i ; pegTop[Hanoi.PEG1] = discs-1 ; for (int i=1; i<PEGS; i++) pegTop[i] = -1 ; // calculate disc widths discWidth = new int[discs] ; for (int i=discs-1; i>=0; i--) discWidth[i] = DISC_SIZES[discs-Hanoi.MIN_DISCS][0] - (DISC_SIZES[discs-Hanoi.MIN_DISCS][1] * (discs-1-i)) ; moveCount = 0 ; // minimum moves is (2**discs)-1 minMoves = ((int)Math.pow(2.0,discs)) - 1 ; } void setDisc(int d,int p) { peg[++pegTop[p]][p] = d ;} int getDisc(int d,int p) { return peg[d][p] ;} int getTopDisc(int p) { return peg[pegTop[p]--][p] ;} int getPegTop(int p) { return pegTop[p] ;} int getMoveCount() {return moveCount ;} int getMinMoves() {return minMoves ;} int getDiscWidth(int d) { return discWidth[d-1] ;} boolean isStartPeg(int i) { if ((i >= 0)&&(pegTop[i]>=0)) return true ; else return false ; } String getBoardStatus() { String status = null ; if (pegTop[PEGS-1]==(discs - 1)) { status = (moveCount==minMoves) ? main.PERFECT : main.WIN ; } return status ; } // manual move boolean moveDisc(int d,int p1,int p2) { if ((p1>=0)&&(p2>=0)) { // to different peg which is empty or has larger disc if ( (p1!=p2)&&((pegTop[p2]<0)||(peg[pegTop[p2]][p2]>d)) ) { setDisc(d,p2) ; for (int imoveit=0;imoveit<3;imoveit++) { // main.diskArray[p2][main.present_peg_count[p2]][imoveit]= main.diskArray[p1][main.present_peg_count[p1]-1][imoveit]; // main.diskArray[p1][main.present_peg_count[p1]-1][imoveit]=0; } main.present_peg_count[p1]--; main.present_peg_count[p2]++; moveCount++ ; return true ; } } setDisc(d,p1) ; return false ; } // AutoSolve move void moveDisc(int p1,int p2) { setDisc(getTopDisc(p1),p2) ; moveCount++ ; } } /******** BOARD CANVAS ******** */ final class BoardCanvas extends JPanel implements MouseListener,MouseMotionListener { public static final long serialVersionUID = 421232L; static final int PEG_SPACE=75, DISC_HEIGHT=15 ; static final Color COLOR_1=new Color(102,51,0), COLOR_2=new Color(153,102,0), COLOR_3=new Color(204,153,51), COLOR_4=new Color(255,204,0), COLOR_5=new Color(255,255,204) ; private Image bufferImage ; private Graphics buffer ; private Hanoi main ; // constructor BoardCanvas(Hanoi main) { this.main = main ; this.addMouseListener(this); this.addMouseMotionListener(this); } void drawBoard(Board b,Image boardImage,int dragDisc,int dragX,int dragY) { int width=0, disc=0 ; if (buffer==null) { // bufferImage=Toolkit.getDefaultToolkit().getImage("C:/WSWeb/computation/newsrc/src/board.gif"); } // draw board // draw discs for (int p=main.PEG1; p<=main.PEG3; p++) { for (int d=0; d<=b.getPegTop(p); d++) { main.diskArray[p][d]=b.getDisc(d, p); disc = b.getDisc(d,p) ; if (disc!=0) { width = b.getDiscWidth(disc) ; main.theDisks[disc][0]=(((2*p)+1)*PEG_SPACE)-((width/2)); main.theDisks[disc][1]=(main.TABLE_TOP-((d+1)*DISC_HEIGHT)); main.theDisks[disc][2]=width; main.present_peg_count[p]++; } } } if (dragDisc!=0) { width = b.getDiscWidth(dragDisc) ; } repaint() ; } void drawADisc(int x,int y,int width,Graphics g) { g.setColor(COLOR_3) ; g.drawLine(x+4,y,x+width-4,y) ; // 1 g.drawLine(x+2,y+1,x+width-2,y+1) ; // 2 g.drawRect(x,y+7,width,1) ; // 8,9 g.setColor(COLOR_4) ; g.drawLine(x+1,y+2,x+width-1,y+2) ; // 3 g.drawRect(x,y+5,width,1) ; // 6,7 g.setColor(COLOR_5) ; g.drawLine(x+1,y+3,x+width-1,y+3) ; // 4 g.drawLine(x,y+4,x+width,y+4) ; // 5 g.setColor(COLOR_2) ; g.drawRect(x,y+9,width,1) ; // 10,11 g.drawLine(x+1,y+11,x+width-1,y+11) ; // 12 g.setColor(COLOR_1) ; g.drawLine(x+1,y+12,x+width-1,y+12) ; // 13 g.drawLine(x+2,y+13,x+width-2,y+13) ; // 14 g.drawLine(x+4,y+14,x+width-4,y+14) ; // 15 } public void paintComponent(Graphics g) { super.paintComponent(g); update(g) ;} public void update(Graphics g) { bufferImage = Toolkit.getDefaultToolkit().getImage(getClass().getResource("blue.gif")) ; g.drawImage(bufferImage,0,0,this); for (int p=main.PEG1; p<=main.PEG3; p++) { for (int d=0; d<=main.bd.getPegTop(p); d++) { main.bc.drawADisc(main.theDisks[main.diskArray[p][d]][0], main.theDisks[main.diskArray[p][d]][1],main.theDisks[main.diskArray[p][d]][2],g); } if (main.dragDisk[0]!=0) { main.bc.drawADisc(main.dragDisk[1], main.dragDisk[2], main.dragDisk[3], g); } } } // mouse event handlers public void mousePressed(MouseEvent e) { main.selectDisc(e.getX(),e.getY()) ; return ;} public void mouseDragged(MouseEvent e) { main.dragDisc(e.getX(),e.getY()); return ;} public void mouseMoved(MouseEvent e){return;} public void mouseReleased(MouseEvent e) { main.dropDisc(e.getX(),e.getY()) ; return ;} public void mouseExited(MouseEvent e) { return ;} public void mouseEntered(MouseEvent e) { return ;} public void mouseClicked(MouseEvent e) { return;} } /******** CONTROL PANEL ******** main UI components */ final class ControlPanel extends Panel implements ActionListener { public static final long serialVersionUID = 421231L; static final int MAX_DELAY=1000 ; public long startTime = System.currentTimeMillis() ; private Panel discsPanel ; private Button bDiscsMinus, bDiscsPlus, bRestart, bSolve ; private Checkbox cbTimer ; private TextField tfDiscs, tfTimer ; private Scrollbar sbSpeed ; private Hanoi main ; private int discs=Hanoi.MIN_DISCS, delay=200 ; // constructor ControlPanel(Hanoi main) { this.main = main ; setLayout(new GridLayout(9,2,0,3)) ; setFont(Hanoi.textFont) ; // DISCS discsPanel = new Panel() ; discsPanel.setLayout(new BorderLayout(2,0)) ; tfDiscs = new TextField(3) ; tfDiscs.setFont(Hanoi.monoFont) ; tfDiscs.setForeground(Color.black) ; tfDiscs.setBackground(Color.lightGray) ; tfDiscs.setEditable(false) ; setDiscs(discs) ; discsPanel.add("West",bDiscsMinus=new Button(main.MINUS)) ; bDiscsMinus.addActionListener(this); //new1 bDiscsMinus.setFont(Hanoi.monoFont) ; discsPanel.add("Center",tfDiscs) ; discsPanel.add("East",bDiscsPlus=new Button(main.PLUS)) ; bDiscsPlus.addActionListener(this); //new1 bDiscsPlus.setFont(Hanoi.monoFont) ; discsPanel.validate() ; // SPEED sbSpeed = new Scrollbar(Scrollbar.HORIZONTAL, (MAX_DELAY-delay),0,0,(MAX_DELAY-9)) ; sbSpeed.setBackground(Color.lightGray) ; sbSpeed.setBlockIncrement(MAX_DELAY/10) ; sbSpeed.setUnitIncrement(MAX_DELAY/100) ; bSolve = new Button(main.SOLUTION) ; bSolve.addActionListener(this); //new1 bRestart=new Button(main.RESTART); bRestart.addActionListener(this); //new1 // TIMER cbTimer = new Checkbox(" "+main.TIMER) ; cbTimer.setBackground(Color.lightGray) ; tfTimer = new TextField(10) ; tfTimer.setFont(Hanoi.monoFont) ; tfTimer.setForeground(Color.white) ; tfTimer.setBackground(Color.black) ; tfTimer.setEditable(false) ; // construct panel add(new Label(main.DISCS,Label.CENTER)) ; add(discsPanel) ; add(bRestart) ; add(bSolve) ; add(new Label(main.SPEED,Label.CENTER)) ; add(sbSpeed) ; add(cbTimer) ; add(tfTimer) ; validate() ; setPlusMinusEnable() ; cbTimer.setState(true) ; } void setTimerEnable(boolean b) { cbTimer.setEnabled(true) ;} void setAutoSolveEnable(boolean b) { bSolve.setEnabled(true) ;} void setPlusMinusEnable() { if (discs<Hanoi.MAX_DISCS) { bDiscsPlus.setEnabled(true); } if (discs>Hanoi.MIN_DISCS) { bDiscsMinus.setEnabled(true); } } void setDiscs(int i) { String s = Integer.toString(i) ; if (s.length()==1) s = " " + s ; else if (s.length()==2) s = " " + s ; tfDiscs.setText(s) ; } void setTimer(String s) { tfTimer.setText(s) ;} int getDiscs() { return discs ;} int getDelay() { return MAX_DELAY-sbSpeed.getValue();} boolean isTimerOn() { return cbTimer.getState() ;} // handle button clicks public void actionPerformed(ActionEvent e) { if (e.getSource()==bSolve) { setAutoSolveEnable(false) ; main.startSolveThread() ; } else { if ((e.getSource()==bDiscsPlus)&&(discs<Hanoi.MAX_DISCS)) setDiscs(++discs) ; //The one bug Part 1. else if ((e.getSource()==bDiscsMinus)&&(discs>Hanoi.MIN_DISCS)) setDiscs(--discs) ; //The one bug Part 2. setPlusMinusEnable() ; main.restartGame() ; } return ; } // handle scrollbar public void processEvent(AWTEvent e) { System.out.println(e.getSource()); if (e.getSource()==sbSpeed) { System.out.println(delay); delay = MAX_DELAY - sbSpeed.getValue() ; return ; } super.processEvent(e) ; return; } } /******** STATUS PANEL ******** UI components for status messages and move counter */ final class StatusPanel extends Panel { public static final long serialVersionUID = 421234L; private TextField tfStatus, tfMoveCount ; private Hanoi main ; // constructor StatusPanel(Hanoi main) { this.main = main ; setFont(main.statusFont) ; tfStatus = new TextField(60) ; tfStatus.setForeground(Color.white) ; tfStatus.setBackground(Color.black) ; tfStatus.setEditable(false) ; tfMoveCount = new TextField(6) ; tfMoveCount.setFont(main.monoFont) ; tfMoveCount.setForeground(Color.white) ; tfMoveCount.setBackground(Color.black) ; tfMoveCount.setEditable(false) ; add(tfStatus) ; add(tfMoveCount) ; add(new Label(main.MOVES)) ; validate() ; } void setMoveCount(int i) { String s=Integer.toString(i) ; switch (s.length()) { case 1: s = " " + s ; break ; case 2: s = " " + s ; break ; case 3: s = " " + s ; break ; case 4: s = " " + s ; break ; } tfMoveCount.setText(s) ; } void setStatus(String s) { tfStatus.setText(s) ;} }