/** * @author Hank Dolben * @version 2004 Mar 12 * * MarkN: interactive n digit number game * Copyright (c) 2000-2004 by Hank Dolben * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.dolben.MarkN; import java.applet.Applet; import java.awt.Color; import java.awt.BorderLayout; import java.awt.Panel; import java.awt.Button; import java.awt.Checkbox; import java.awt.TextField; import java.awt.event.*; /** * This is an applet that guesses an N digit number. * * A Generator must be supplied in a derived class by overriding * the newGenerator factory method. */ public abstract class Guesser extends Applet { // Derivation Interface /** * makes a guess Generator * * @return the new Generator */ public abstract Generator newGenerator(); private ScoreboardCanvas _scoreboard; // display of guesses and scores private NumberField _target; // target entry field private ScoreField _score; // score entry field private Button _scoreButton; // button to confirm score private Numbah _guess; // the last guess made private Generator _generator; // the guess generator private NumberScrambler _s; // the guess scrambler /** * initializes the applet */ public synchronized void init( ) { /* * for target, set up * a field to enter a number * a "New" button to set a new target * a "Random" button to set a random target * * setup a scoreboard to display guesses and scores * * for guess, set up * a field to enter a score * a "Score" button to give the score * a "Retract" button to undo the last score */ setBackground(Color.white); setLayout(new BorderLayout()); try { Configuration.setPlaces(getParameter("NDNG.PLACES")); Configuration.setDigits(getParameter("NDNG.DIGITS")); } catch ( Exception e ) { System.out.println( e.toString() ); } Button b; Panel north = new Panel(); _target = new NumberField(); north.add(_target); north.add(b = new Button("New")); b.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { retarget(); } } ); north.add(b = new Button("Random")); b.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { random(); } } ); add("North",north); _scoreboard = new ScoreboardCanvas(); add("Center",_scoreboard); Panel south = new Panel(); _score = new ScoreField(); south.add(_score); south.add(_scoreButton = new Button("Score")); _scoreButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { score(); } } ); south.add(b = new Button("Retract")); b.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { retract(); } } ); add("South",south); _guess = new Numbah(); startGuessing(); } /** * the action performed by the "New" button * automatically score and guess the target when given * otherwise just make the first guess, allowing player to score */ private void retarget( ) { startGuessing(); solve(); _scoreboard.repaint(); } /** * the action performed by the "Random" button * automatically score and guess a randomly generated target */ private void random( ) { startGuessing(); _target.setNumber(Numbah.random()); solve(); _scoreboard.repaint(); } /** * the action performed by the "Score" button * make another guess given the score of the last guess */ private void score( ) { _scoreboard.setMessage(""); try { guess( _score.getScore() ); } catch ( Exception e ) { _scoreboard.setMessage("Score must be legit two digits only"); } _scoreboard.repaint(); } /** * the action performed by the "Retract" button * retract the last given score */ private void retract( ) { _scoreButton.setEnabled(true); _generator.retractScore(); _guess = _scoreboard.retractScore(); _scoreboard.setMessage(""); _scoreboard.repaint(); } /** * starts the program's guessing over */ private void startGuessing( ) { Numbah guess; _generator = newGenerator(); _s = new NumberScrambler(); _scoreButton.setEnabled(true); _scoreboard.clear(); scrambledGuess(); _scoreboard.addGuess(_guess); } /** * automatically scores and guesses the given target */ private void solve( ) { if ( _target.getText().length() != 0 ) { try { Numbah target = _target.getNumber(); while ( !guess(target.score(_guess)) ); } catch ( Exception e ) { _scoreboard.setMessage( "Numbah must have "+ Configuration.getPlaces()+" unique digits" ); } } } /** * makes the next guess given the score to the previous guess * unless the score says that the previous guess was correct * don't update the scoreboard if a next guess can't be generated * * @return true when scored guess is correct */ private boolean guess( Score score ) { _generator.tellScore(score); if ( score.correct() ) { _scoreButton.setEnabled(false); _scoreboard.addScore(score); return true; } if ( scrambledGuess() ) { _scoreboard.addScore(score); _scoreboard.addGuess(_guess); } else { _scoreboard.setMessage("Scores are inconsistent"); } return false; } /** * scrambles the next guess to disguise the strategy ;-) */ private boolean scrambledGuess( ) { Numbah plain = new Numbah(); if ( _generator.nextGuess(plain) ) { _guess = (Numbah)plain.clone(); _s.scramble(_guess); return true; } else { return false; } } }