/* * @(#)Arithmetic24.java Version 1.0 98/03/12 * * Copyright (c) 1998 by Huahai Yang * * Use at your own risk. I do not guarantee the fitness of this * software for any purpose, and I am not responsible for * any damage you do to yourself or others by using this software. * This file may be distributed freely, provided its contents * are not tampered with in any way. * */ import java.awt.*; import java.applet.*; import java.awt.event.*; import java.util.*; /** * Main class of Arithmetic24 applet. Draws basic interface and * coordinates among playing board, clock and score keeper. * @see DraggingArea * @see Clock * @see ScoreKeeper * @version 1.0 * @author Huahai Yang */ public class Arithmetic24 extends Applet implements ActionListener, ItemListener, Observer { Button noSolutionButton, doneButton; Label feedBackLabel; Clock clock; Choice difficultyLevel; ScoreKeeper score; DraggingArea playingBoard; // time limit final int BEGINNER_TIME = 120, INTERMEDIATE_TIME = 90, EXPERT_TIME = 60; SoundList soundList; String correctSound = "well_done.au", wrongSound = "missed.au", badExpSound = "Hah.au", timeOutSound = "bell.au", fillSlotSound = "click2.au", clickDeckSound = "click1.au"; /** * Sets up basic layout of applet and prepare sound files */ public void init() { setSize(600, 400); playingBoard = new DraggingArea(); Panel panel1 = new Panel(), panel2 = new Panel(); difficultyLevel = new Choice(); difficultyLevel.addItem("Beginner"); difficultyLevel.addItem("Intermediate"); difficultyLevel.addItem("Expert"); difficultyLevel.addItemListener(this); difficultyLevel.setEnabled(true); panel1.add(difficultyLevel); clock = new Clock(BEGINNER_TIME); clock.setActionCommand("timeout"); clock.addActionListener(this); panel1.add(clock); feedBackLabel = new Label("Goal: compute 24. Click deck to start."); feedBackLabel.setFont(new Font("Helvetica", Font.BOLD, 16)); feedBackLabel.setForeground(Color.blue); panel1.add(feedBackLabel); score = new ScoreKeeper(); panel1.add(score); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; gridbag.setConstraints(panel1, c); add(panel1); c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = 4; gridbag.setConstraints(playingBoard, c); add(playingBoard); panel2.setLayout(gridbag); c.gridwidth = GridBagConstraints.RELATIVE; c.ipadx = 15; c.ipady = 10; c.insets = new Insets (5, 20, 5, 20); noSolutionButton = new Button(); noSolutionButton.setActionCommand("no solution"); noSolutionButton.setLabel("No Solutions."); noSolutionButton.setFont(new Font("Dialog", Font.PLAIN, 14)); noSolutionButton.setForeground(new Color(255)); noSolutionButton.addActionListener(this); gridbag.setConstraints(noSolutionButton, c); panel2.add(noSolutionButton); doneButton = new Button(); doneButton.setActionCommand("done"); doneButton.setLabel("I got a solution!"); doneButton.setFont(new Font("Dialog", Font.PLAIN, 14)); doneButton.setForeground(new Color(16711935)); doneButton.addActionListener(this); gridbag.setConstraints(doneButton, c); panel2.add(doneButton); c.gridheight = GridBagConstraints.RELATIVE; gridbag.setConstraints(panel2, c); add(panel2); startLoadingSounds(); } //init /** * Start asynchronous sound loading. */ void startLoadingSounds() { soundList = new SoundList(this, getCodeBase()); soundList.startLoading(clickDeckSound); soundList.startLoading(fillSlotSound); soundList.startLoading(timeOutSound); soundList.startLoading(badExpSound); soundList.startLoading(correctSound); soundList.startLoading(wrongSound); } //startLoadingSounds /** * Starts applet by starting dragging thread * @see DraggingArea */ public void start() { playingBoard.start(); } // start /** * Stop applet by stopping dragging thread * @see DraggingArea */ public void stop() { clock.stop(); playingBoard.stop(); } // stop /** * Called before retrieve the solution. In the case that * the solution is not available yet, progarm will wait here, * so enhance the solution thread's priority to minimize the * waiting time */ private void beginWaitSolution() { feedBackLabel.setText("I am thinking..."); playingBoard.cardDeck.setThreadPriority(Thread.NORM_PRIORITY); } //beginWaitSolution /** * reset solution thread's priority */ private void endWaitSolution() { playingBoard.cardDeck.setThreadPriority(Thread.MIN_PRIORITY); } //endWaitSolution /** * Handles playing status changes * @see PlayingStatus * @see DraggingArea */ public void update(Observable observable, Object status) { if(observable instanceof PlayingStatus) { switch( ((Integer)status).intValue() ) { case PlayingStatus.DEALED: clock.start(); noSolutionButton.setEnabled(true); doneButton.setEnabled(true); difficultyLevel.setEnabled(false); feedBackLabel.setText("Drag cards and operaters."); break; case PlayingStatus.WAITING: noSolutionButton.setEnabled(false); doneButton.setEnabled(false); difficultyLevel.setEnabled(true); break; case PlayingStatus.ROUND_OVER: //TO DO: record user score playingBoard.stop(); feedBackLabel.setText("You got " + score.getScore() + " points. Lets play again."); score.resetScore(); playingBoard.start(); noSolutionButton.setEnabled(false); doneButton.setEnabled(false); break; } // switch } // if } // update for observer /** * Handles action events fired by buttons and clock * @see Clock */ public void actionPerformed(ActionEvent e) { double timePassed = (double)clock.getTime() / clock.getTimeLimit(); String command = e.getActionCommand(); if(command == "no solution") { beginWaitSolution(); if( playingBoard.currentSolution() == null ) { score.updateScore(ScoreKeeper.NO_NO, timePassed); soundList.playClip(correctSound); feedBackLabel.setText("Correct."); } // if no solution else { soundList.playClip(wrongSound); feedBackLabel.setText("Let me show you a solution."); score.updateScore(ScoreKeeper.HAS_NO, timePassed); playingBoard.beginAnimation(); } // else if has solution endWaitSolution(); } // if press "no solution" else if(command == "done") { Expression userDid; double value; if(playingBoard.isFullExpression()) { userDid= new Expression(playingBoard.userCreatedExpression()); } // if else { soundList.playClip(badExpSound); feedBackLabel.setText("Bad expression, try again."); return; } // else try { value = userDid.getValue(); } // try catch(IllegalExpressionException exception) { soundList.playClip(badExpSound); feedBackLabel.setText("Bad expression, try again."); return; } //catch if( value == 24.0 ) { soundList.playClip(correctSound); feedBackLabel.setText("Right!"); score.updateScore(ScoreKeeper.HAS_RIGHT, timePassed); } // if equals 24 else { beginWaitSolution(); soundList.playClip(wrongSound); if( playingBoard.currentSolution() == null ) { feedBackLabel.setText("No solution, you are wrong."); score.updateScore(ScoreKeeper.NO_HAS, timePassed); } // if no solution else { feedBackLabel.setText("Wrong, here is a correct solution."); score.updateScore(ScoreKeeper.HAS_WRONG, timePassed); playingBoard.beginAnimation(); } // else has solution endWaitSolution(); } // else not equals 24 } // else if press "done" else { soundList.playClip(timeOutSound); score.updateScore(ScoreKeeper.TIME_OUT, 1); if( playingBoard.currentSolution() != null ) { feedBackLabel.setText("Time out, here is a solution."); playingBoard.beginAnimation(); } //if else { feedBackLabel.setText("Time out, there is no solution."); } //else } // else timeout clock.stop(); playingBoard.cardDeck.enableClick(); playingBoard.setStatus(PlayingStatus.WAITING); } // actionPerformed /** * Handles difficultyLevel choice event */ public void itemStateChanged(ItemEvent e) { String select = new String(difficultyLevel.getSelectedItem()); if(select.equals("Beginner")) { clock.setTimeLimit( BEGINNER_TIME ); score.setLevelWeight( ScoreKeeper.BEGINNER ); } // if else if( select.equals("Intermediate") ) { score.setLevelWeight( ScoreKeeper.INTERMEDIATE ); clock.setTimeLimit( INTERMEDIATE_TIME ); } // else if else { score.setLevelWeight( ScoreKeeper.EXPERT ); clock.setTimeLimit( EXPERT_TIME ); } // else } // itemStateChanged } //Arithmetic24