/****************************************************************************************** Peggy.java - Peg solitaire game 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. ******************************************************************************************/ import java.applet.* ; import java.awt.* ; import java.net.* ; import java.util.* ; /******** PEGGY ******** main class; initializes applet panel, starts all games, handles peg move events */ public class Peggy extends Applet implements Runnable { // applet info public String getAppletInfo() { return "Peggy 2.0 - Copyright (c) 2002 Robert Kirkland"; } String parameterInfo[][] = { {"bgColor", "integer", "Background color (24-bit RGB hex int)"}, {"title", "string", "Applet title text"}, {"cross", "string", "Cross pattern text"}, {"plus", "string", "Plus pattern text"}, {"fireplace", "string", "Fireplace pattern text"}, {"pyramid", "string", "Pyramid pattern text"}, {"arrow", "string", "Arrow pattern text"}, {"dblarrow", "string", "Double Arrow pattern text"}, {"diamond", "string", "Diamond pattern text"}, {"solitaire", "string", "Solitaire pattern text"}, {"reverse", "string", "Reverse checkbox text"}, {"restart", "string", "Restart button text"}, {"undo", "string", "Undo button text"}, {"solution", "string", "Solution button text"}, {"win", "string", "Win status text"}, {"lose", "string", "Game over status text"}, {"perfect", "string", "Pefect game status text"}, {"done", "string", "Solution done text"} } ; public String[][] getParameterInfo() { return parameterInfo ; } static final Color DF_BG_COLOR=Color.white ; // default background color static final String DF_TITLE ="PEGGY", // default text strings DF_CROSS ="Cross", DF_PLUS ="Plus", DF_FIREPLACE="Fireplace", DF_PYRAMID ="Pyramid", DF_ARROW ="Arrow", DF_DBLARROW ="Double Arrow", DF_DIAMOND ="Diamond", DF_SOLITAIRE="Solitaire", DF_REVERSE ="REVERSE", DF_RESTART ="RESTART", DF_UNDO ="UNDO", DF_SOLUTION ="SOLUTION", DF_WIN ="You win !", DF_LOSE ="Game Over", DF_PERFECT ="Perfect !", DF_DONE ="Done !" ; static final int BOARD_WIDTH=240, BOARD_HEIGHT=240 ; protected String TITLE, CROSS, PLUS, FIREPLACE, PYRAMID, ARROW, DBLARROW, DIAMOND, SOLITAIRE, REVERSE, RESTART, UNDO, SOLUTION, WIN, LOSE, PERFECT, DONE ; private boolean gameOver ; private Point currPt, startPt ; private Board bd ; private BoardCanvas bc ; private ControlPanel cp ; private Image boardImage, pegUpImage, pegDownImage ; private Color BG_COLOR ; private String gameStatus, boardImageFile = "board.gif", pegUpImageFile = "peg_up.gif", pegDownImageFile = "peg_down.gif" ; private Thread solveThread ; public void init() { // --- get applet parameters --- // background color String bgColorString = getParameter("bgColor") ; try { BG_COLOR = bgColorString==null ? DF_BG_COLOR : new Color(Integer.parseInt(bgColorString,16)) ; } catch (NumberFormatException e) { BG_COLOR = DF_BG_COLOR ; System.out.println("ERROR: Invalid bgColor parameter.") ; } // title TITLE = getParameter("title") ; if (TITLE==null) TITLE = new String(DF_TITLE) ; // pattern names CROSS = getParameter("cross") ; if (CROSS==null) CROSS = new String(DF_CROSS) ; PLUS = getParameter("plus") ; if (PLUS==null) PLUS = new String(DF_PLUS) ; FIREPLACE = getParameter("fireplace") ; if (FIREPLACE==null) FIREPLACE = new String(DF_FIREPLACE) ; PYRAMID = getParameter("pyramid") ; if (PYRAMID==null) PYRAMID = new String(DF_PYRAMID) ; ARROW = getParameter("arrow") ; if (ARROW==null) ARROW = new String(DF_ARROW) ; DBLARROW = getParameter("dblarrow") ; if (DBLARROW==null) DBLARROW = new String(DF_DBLARROW) ; DIAMOND = getParameter("diamond") ; if (DIAMOND==null) DIAMOND = new String(DF_DIAMOND) ; SOLITAIRE = getParameter("solitaire") ; if (SOLITAIRE==null) SOLITAIRE = new String(DF_SOLITAIRE) ; // checkbox and buttons text REVERSE = getParameter("reverse") ; if (REVERSE==null) REVERSE = new String(DF_REVERSE) ; RESTART = getParameter("restart") ; if (RESTART==null) RESTART = new String(DF_RESTART) ; UNDO = getParameter("undo") ; if (UNDO==null) UNDO = new String(DF_UNDO) ; SOLUTION = getParameter("solution") ; if (SOLUTION==null) SOLUTION = new String(DF_SOLUTION) ; // status text WIN = getParameter("win") ; if (WIN==null) WIN = new String(DF_WIN) ; LOSE = getParameter("lose") ; if (LOSE==null) LOSE = new String(DF_LOSE) ; PERFECT = getParameter("perfect") ; if (PERFECT==null) PERFECT = new String(DF_PERFECT) ; DONE = getParameter("done") ; if (DONE==null) DONE = new String(DF_DONE) ; // load images MediaTracker tracker = new MediaTracker(this) ; URL url = getCodeBase() ; boardImage = getImage(url,boardImageFile) ; pegUpImage = getImage(url,pegUpImageFile) ; pegDownImage = getImage(url,pegDownImageFile) ; tracker.addImage(boardImage,0) ; tracker.addImage(pegUpImage,1) ; tracker.addImage(pegDownImage,2) ; try { tracker.waitForAll(); } catch (InterruptedException e) {} // initialize applet layout setBackground(BG_COLOR) ; setLayout(new FlowLayout(FlowLayout.CENTER,20,20)) ; bc = new BoardCanvas(boardImage,pegDownImage,pegUpImage,this) ; bc.resize(BOARD_WIDTH,BOARD_HEIGHT) ; cp = new ControlPanel(this) ; Panel p1 = new Panel() ; p1.setBackground(Color.lightGray) ; p1.setLayout(new FlowLayout(FlowLayout.CENTER,5,5)) ; Panel p2 = new Panel() ; p2.setBackground(Color.gray) ; p2.setLayout(new FlowLayout(FlowLayout.CENTER,2,2)) ; p1.add(cp) ; p2.add(p1) ; add(bc) ; add(p2) ; validate() ; newGame() ; } // start me up void newGame() { System.gc() ; gameOver = false ; cp.setReverseEnable(true) ; cp.setUndoEnable(false) ; cp.setAutoSolveEnable(true) ; cp.setStatus(" ") ; // create Board if (cp.isReverse()) bd = new ReverseBoard(cp.getPattern(),bc,this) ; else bd = new NormalBoard(cp.getPattern(),bc,this) ; bc.drawBoard(bd,0,0) ; bc.requestFocus() ; } // handle Reset event void restartGame() { stop() ; newGame() ; } // spawn AutoSolve thread public void startSolveThread() { if (solveThread == null) { solveThread = new Thread(this) ; solveThread.start() ; } } // kill thread public void stop() { if (solveThread != null) { solveThread.stop() ; solveThread = null ; } } // run thread public void run() { gameOver = true ; cp.setReverseEnable(true) ; cp.setUndoEnable(false) ; cp.setAutoSolveEnable(false) ; bd.solve() ; bc.drawBoard(bd,0,0) ; cp.setStatus(DONE) ; } // handle mouse drag event void movePeg(int x,int y) { if (!gameOver && startPt != null) bc.drawBoard(bd,x,y) ; } // handle mouse down event void selectPeg(int x,int y) { if (!gameOver) { currPt = bc.pixelToSquare(x,y) ; if (bd.setStartPeg(currPt)) { startPt = new Point(currPt.x,currPt.y) ; bc.drawBoard(bd,x,y) ; } } } // handle mouse up event void dropPeg(int x,int y) { if (!gameOver && startPt != null) { currPt = bc.pixelToSquare(x,y) ; if (bd.movePeg(startPt,currPt)) { gameStatus = bd.getStatus() ; cp.setReverseEnable(false) ; cp.setUndoEnable(true) ; cp.setAutoSolveEnable(false) ; cp.setStatus(gameStatus) ; if (gameStatus != null) { gameOver = true ; cp.setUndoEnable(false) ; } } bc.drawBoard(bd,0,0) ; startPt = null ; } } // handle Undo event boolean undoMove() { boolean undoEnabled = bd.undoMove() ; bc.drawBoard(bd,0,0) ; bc.requestFocus() ; if (!undoEnabled) cp.setAutoSolveEnable(true) ; return undoEnabled ; } } /******** BOARD ******** base class; controls pegboard layout */ abstract class Board { static final byte NORTH=1 ,EAST=2, SOUTH=3, WEST=4, pegs[] = {6,9,11,16,17,21,24,32}, patterns[][] = { // Cross {0,0,1,1,1,0,0},{0,0,1,1,1,0,0},{1,1,2,1,1,1,1},{1,2,2,2,2,1,1}, {1,1,2,1,1,1,1},{0,0,1,1,1,0,0},{0,0,1,1,1,0,0}, // Plus {0,0,1,1,1,0,0},{0,0,1,2,1,0,0},{1,1,1,2,1,1,1},{1,2,2,2,2,2,1}, {1,1,1,2,1,1,1},{0,0,1,2,1,0,0},{0,0,1,1,1,0,0}, // Fireplace {0,0,1,1,1,0,0},{0,0,1,1,1,0,0},{2,2,2,2,1,1,1},{2,2,2,1,1,1,1}, {2,2,2,2,1,1,1},{0,0,1,1,1,0,0},{0,0,1,1,1,0,0}, // Pyramid {0,0,1,1,2,0,0},{0,0,1,2,2,0,0},{1,1,2,2,2,1,1},{1,2,2,2,2,1,1}, {1,1,2,2,2,1,1},{0,0,1,2,2,0,0},{0,0,1,1,2,0,0}, // Arrow {0,0,1,1,1,0,0},{0,0,2,1,1,0,0},{1,2,2,1,1,2,2},{2,2,2,2,2,2,2}, {1,2,2,1,1,2,2},{0,0,2,1,1,0,0},{0,0,1,1,1,0,0}, // Double Arrow {0,0,1,1,1,0,0},{0,0,2,1,2,0,0},{1,2,2,2,2,2,1},{2,2,2,2,2,2,2}, {1,2,2,2,2,2,1},{0,0,2,1,2,0,0},{0,0,1,1,1,0,0}, // Diamond {0,0,1,2,1,0,0},{0,0,2,2,2,0,0},{1,2,2,2,2,2,1},{2,2,2,1,2,2,2}, {1,2,2,2,2,2,1},{0,0,2,2,2,0,0},{0,0,1,2,1,0,0}, // Solitaire {0,0,2,2,2,0,0},{0,0,2,2,2,0,0},{2,2,2,2,2,2,2},{2,2,2,1,2,2,2}, {2,2,2,2,2,2,2},{0,0,2,2,2,0,0},{0,0,2,2,2,0,0} }, reversePattern[][] = { {0,0,1,1,1,0,0},{0,0,1,1,1,0,0},{1,1,1,1,1,1,1},{1,1,1,2,1,1,1}, {1,1,1,1,1,1,1},{0,0,1,1,1,0,0},{0,0,1,1,1,0,0} }, solutions[][] = { // Cross {3,2,2},{3,4,1},{2,2,2},{5,2,4},{3,1,3}, // Plus {3,2,1},{3,4,1},{5,3,4},{3,3,1},{3,0,3},{1,3,2},{3,2,3},{3,5,1}, // Fireplace {3,2,2},{4,0,3},{4,3,1},{2,0,2},{4,0,3},{5,2,4},{3,1,3},{3,3,4}, {2,1,3},{1,3,2}, // Pyramid {4,3,3},{6,4,4},{4,5,1},{2,3,3},{0,4,2},{2,5,1},{2,3,1},{2,1,2}, {4,3,4},{4,1,3},{5,3,4},{3,3,3},{1,3,2},{3,2,3},{3,5,1}, // Arrow {4,6,1},{2,6,2},{2,5,2},{3,4,2},{4,6,1},{5,4,4},{2,2,1},{2,0,2}, {4,2,4},{4,0,3},{3,4,1},{3,1,3},{1,2,2},{3,3,1},{5,2,4},{3,1,3}, // Double Arrow {2,4,3},{2,6,2},{4,4,4},{4,6,1},{5,4,4},{3,3,2},{3,5,1},{1,4,2}, {2,3,2},{5,3,4},{2,2,1},{2,0,2},{4,2,4},{4,0,3},{3,4,1},{3,1,3}, {1,2,2},{3,3,1},{5,2,4},{3,1,3}, // Diamond {4,4,3},{4,6,4},{2,4,2},{2,6,1},{1,4,2},{3,5,1},{5,4,4},{4,2,3}, {6,3,4},{4,4,1},{2,2,3},{0,3,2},{2,4,1},{2,2,1},{2,0,2},{4,2,4}, {4,0,3},{3,4,1},{3,1,3},{1,2,2},{3,3,1},{5,2,4},{3,1,3}, // Solitaire {3,5,1},{1,4,2},{3,3,3},{3,6,1},{2,6,1},{3,4,4},{5,4,4},{4,6,1}, {3,4,2},{0,4,2},{2,3,3},{0,3,2},{2,2,3},{2,5,1},{0,2,2},{6,4,4}, {4,3,3},{6,3,4},{4,2,3},{4,5,1},{6,2,4},{3,2,2},{4,0,3},{4,3,1}, {2,0,2},{4,0,3},{5,2,4},{3,1,3},{3,3,4},{2,1,3},{1,3,2} } ; static final int ROWS=7, COLS=7, solutionIndex[] = {0,5,13,23,38,54,74,97,128} ; static final Point CENTER_SQUARE = new Point(3,3) ; protected Stack undo ; // LIFO stack holds moves made protected int pegCount, index ; protected int b[][] = new int[COLS][ROWS] ; protected BoardCanvas bc ; protected Peggy main ; boolean isValidPoint(int i,int j) { if (i>=0 && i=0 && j1)&&isEmpty((i-2),j)&&isPeg((i-1),j)) || ((j<(ROWS-2))&&isEmpty(i,(j+2))&&isPeg(i,(j+1))) || ((j>1)&&isEmpty(i,(j-2))&&isPeg(i,(j-1))) ) { return false ; } } } } return true ; } boolean movePeg(Point p1,Point p2) { boolean moveMade = false ; if (isValidPoint(p1)&&isValidPoint(p2)) { if (isEmpty(p2)) { if ( ((p2.x-p1.x)==2)&&(p1.y==p2.y)&&(isPeg(p1.x+1,p1.y)) ) { setEmpty(p1.x+1,p1.y) ; moveMade = true ; } else if ( ((p1.x-p2.x)==2)&&(p1.y==p2.y)&&(isPeg(p1.x-1,p1.y)) ) { setEmpty(p1.x-1,p1.y) ; moveMade = true ; } else if ( ((p2.y-p1.y)==2)&&(p1.x==p2.x)&&(isPeg(p1.x,p1.y+1)) ) { setEmpty(p1.x,p1.y+1) ; moveMade = true ; } else if ( ((p1.y-p2.y)==2)&&(p1.x==p2.x)&&(isPeg(p1.x,p1.y-1)) ) { setEmpty(p1.x,p1.y-1) ; moveMade = true ; } if (moveMade) { undo.push(p1) ; undo.push(p2) ; setPeg(p2) ; pegCount-- ; } } } if (!moveMade) setPeg(p1) ; return moveMade ; } boolean undoMove() { if (!undo.empty()) { Point p2 = (Point)undo.pop() ; Point p1 = (Point)undo.pop() ; if ((p2.x-p1.x)==2) setPeg(p1.x+1,p1.y) ; else if ((p1.x-p2.x)==2) setPeg(p1.x-1,p1.y) ; else if ((p2.y-p1.y)==2) setPeg(p1.x,p1.y+1) ; else if ((p1.y-p2.y)==2) setPeg(p1.x,p1.y-1) ; setPeg(p1) ; setEmpty(p2) ; pegCount++ ; if (!undo.empty()) return true ; } return false ; } void solve() { int start=solutionIndex[index], end=start+pegs[index]-1 ; for (int i=start; i1)&&isEmpty((i-2),j)&&isEmpty((i-1),j)) || ((j<(ROWS-2))&&isEmpty(i,(j+2))&&isEmpty(i,(j+1))) || ((j>1)&&isEmpty(i,(j-2))&&isEmpty(i,(j-1))) ) { return false ; } } } } return true ; } boolean movePeg(Point p1,Point p2) { boolean moveMade = false ; if (isValidPoint(p1)&&isValidPoint(p2)) { if (isEmpty(p2)) { if ( ((p2.x-p1.x)==2)&&(p1.y==p2.y)&&(isEmpty(p1.x+1,p1.y)) ) { setPeg(p1.x+1,p1.y) ; moveMade = true ; } else if ( ((p1.x-p2.x)==2)&&(p1.y==p2.y)&&(isEmpty(p1.x-1,p1.y)) ) { setPeg(p1.x-1,p1.y) ; moveMade = true ; } else if ( ((p2.y-p1.y)==2)&&(p1.x==p2.x)&&(isEmpty(p1.x,p1.y+1)) ) { setPeg(p1.x,p1.y+1) ; moveMade = true ; } else if ( ((p1.y-p2.y)==2)&&(p1.x==p2.x)&&(isEmpty(p1.x,p1.y-1)) ) { setPeg(p1.x,p1.y-1) ; moveMade = true ; } if (moveMade) { undo.push(p1) ; undo.push(p2) ; setPeg(p2) ; pegCount++ ; } } } if (!moveMade) setPeg(p1) ; return moveMade ; } boolean undoMove() { if (!undo.empty()) { Point p2 = (Point)undo.pop() ; Point p1 = (Point)undo.pop() ; if ((p2.x-p1.x)==2) setEmpty(p1.x+1,p1.y) ; else if ((p1.x-p2.x)==2) setEmpty(p1.x-1,p1.y) ; else if ((p2.y-p1.y)==2) setEmpty(p1.x,p1.y+1) ; else if ((p1.y-p2.y)==2) setEmpty(p1.x,p1.y-1) ; setPeg(p1) ; setEmpty(p2) ; pegCount-- ; if (!undo.empty()) return true ; } return false ; } void solve() { byte x=0, y=0, dir=0 ; int start=solutionIndex[index+1]-1, end=start-(pegs[index]-2) ; for (int i=start; i>=end ; i--) { switch (solutions[i][2]) { case NORTH: x = solutions[i][0] ; y = (byte)(solutions[i][1]-2) ; dir = SOUTH ; break ; case EAST: x = (byte)(solutions[i][0]+2) ; y = solutions[i][1] ; dir = WEST ; break ; case SOUTH: x = solutions[i][0] ; y = (byte)(solutions[i][1]+2) ; dir = NORTH ; break ; case WEST: x = (byte)(solutions[i][0]-2) ; y = solutions[i][1] ; dir = EAST ; break ; } autoMove(x,y,dir) ; bc.drawBoard(this,0,0) ; if (i!=end) { try { Thread.currentThread().sleep(700) ; } catch (InterruptedException e) {} } } } void autoMove(byte x,byte y,byte dir) { setEmpty(x,y) ; switch (dir) { case NORTH: setPeg(x,y-1) ; setPeg(x,y-2) ; break ; case EAST: setPeg(x+1,y) ; setPeg(x+2,y) ; break ; case SOUTH: setPeg(x,y+1) ; setPeg(x,y+2) ; break ; case WEST: setPeg(x-1,y) ; setPeg(x-2,y) ; break ; } } } /******** BOARD CANVAS ******** draws the board using double buffer */ final class BoardCanvas extends Canvas { static final int BOARD_X_OFFSET=15, BOARD_Y_OFFSET=15, SQUARE_WIDTH=30, SQUARE_HEIGHT=30, PEG_WIDTH=20, PEG_HEIGHT=20, PEG_X_OFFSET=5, PEG_Y_OFFSET=5 ; private Image bufferImage, boardImage, pegDownImage, pegUpImage ; private Graphics buffer ; private Peggy main ; BoardCanvas(Image bI,Image pdI,Image puI,Peggy main) { boardImage = bI ; pegDownImage = pdI ; pegUpImage = puI ; this.main = main ; } void drawBoard(Board b,int dragX,int dragY) { if (buffer==null) { bufferImage = createImage(main.BOARD_WIDTH,main.BOARD_HEIGHT) ; buffer = bufferImage.getGraphics() ; } // draw the lovely wooden board buffer.drawImage(boardImage,0,0,this) ; // add the pegs for (int i = 0; i < b.COLS; i++) { for (int j = 0; j < b.ROWS; j++) { if (b.isPeg(i,j)) { buffer.drawImage(pegDownImage, (squareToPixelX(i)+PEG_X_OFFSET), (squareToPixelY(j)+PEG_Y_OFFSET),this) ; } } } // add the dragged peg if there is one if (dragX>0 && dragY>0) buffer.drawImage(pegUpImage, dragX-((int)(PEG_WIDTH/2)), dragY-((int)(PEG_HEIGHT/2)),this) ; repaint() ; } public void paint(Graphics g) { update(g) ; } public void update(Graphics g) { g.drawImage(bufferImage,0,0,this) ; } // pixel-square conversions static int squareToPixelX(int i) { return ((i*SQUARE_WIDTH)+BOARD_X_OFFSET) ; } static int squareToPixelY(int j) { return ((j*SQUARE_HEIGHT)+BOARD_Y_OFFSET) ; } static Point pixelToSquare(int x,int y) { x -= BOARD_X_OFFSET ; y -= BOARD_Y_OFFSET ; int remX = x % SQUARE_WIDTH ; int remY = y % SQUARE_HEIGHT ; // if x-y is on top of a peg, return peg position if ( (remX>PEG_X_OFFSET)&&(remX<(PEG_X_OFFSET+PEG_WIDTH)) && (remY>PEG_Y_OFFSET)&&(remY<(PEG_Y_OFFSET+PEG_HEIGHT)) ) { return new Point( (int)(x/SQUARE_WIDTH),(int)(y/SQUARE_HEIGHT) ) ; } else return new Point(-1,-1) ; } // mouse event handlers for canvas - they pass events back to main class public boolean mouseDrag(Event e,int x,int y) { main.movePeg(x,y) ; return true ; } public boolean mouseDown(Event e,int x,int y) { main.selectPeg(x,y) ; return true ; } public boolean mouseUp(Event e,int x,int y) { main.dropPeg(x,y) ; return true ; } } /******** CONTROL PANEL ******** the UI components for the game */ final class ControlPanel extends Panel { static final Font titleFont =new Font("Helvetica", Font.BOLD, 14), textFont =new Font("Helvetica", Font.PLAIN, 12), statusFont=new Font("Helvetica", Font.PLAIN, 11) ; private Label lTitle ; private Button bRestart, bUndo, bSolve ; private Choice cPattern ; private Checkbox cbReverse ; private TextField tfStatus ; private Peggy main ; ControlPanel(Peggy main) { this.main = main ; setLayout(new GridLayout(0,1,0,5)) ; setFont(textFont) ; // TITLE add(lTitle=new Label(main.TITLE,Label.CENTER)) ; lTitle.setFont(titleFont) ; add(new Label(" ",Label.CENTER)) ; // Pattern pulldown add(cPattern=new Choice()) ; cPattern.setForeground(Color.black) ; cPattern.setBackground(Color.white) ; cPattern.addItem(main.CROSS) ; cPattern.addItem(main.PLUS) ; cPattern.addItem(main.FIREPLACE) ; cPattern.addItem(main.PYRAMID) ; cPattern.addItem(main.ARROW) ; cPattern.addItem(main.DBLARROW) ; cPattern.addItem(main.DIAMOND) ; cPattern.addItem(main.SOLITAIRE) ; // Reverse checkbox add(cbReverse=new Checkbox(main.REVERSE)) ; // other buttons add(bRestart=new Button(main.RESTART)) ; add(bUndo=new Button(main.UNDO)) ; add(bSolve=new Button(main.SOLUTION)) ; // STATUS add(tfStatus=new TextField(12)) ; tfStatus.setFont(statusFont) ; tfStatus.setForeground(Color.white) ; tfStatus.setBackground(Color.black) ; tfStatus.setEditable(false) ; validate() ; } int getPattern() { return cPattern.getSelectedIndex() ; } boolean isReverse() { return cbReverse.getState() ; } void setReverseEnable(boolean b) { cbReverse.enable(b) ; } void setUndoEnable(boolean b) { bUndo.enable(b) ; } void setAutoSolveEnable(boolean b) { bSolve.enable(b) ; } void setStatus(String s) { tfStatus.setText(s!=null?s:"") ; } public boolean action(Event e,Object o) { if (main.UNDO.equals(o)) bUndo.enable(main.undoMove()) ; else { if (main.SOLUTION.equals(o)) { setAutoSolveEnable(false) ; main.startSolveThread() ; } else main.restartGame() ; } return true ; } }