import java.applet.*; import java.awt.*; import java.util.Random; import java.lang.Math; /** *

This is a simple applet that lets someone play the classic three door * game from Let's Make a Deal. A prize is hidden behind one door. The * player chooses one by clicking on it. Another door is then revealed * to hold a booby prize. The player can then choose to keep either what's * behind the door she selected or the other unopened door.

* *

This applet keeps track of the win & loss statistics for the two * strategies of play (stay with selected door/switch to other door). It * also has autoplay capability, so you can quickly see how the resulting * statistics.

* *

There are three parameters that can be set in the APPLET tag:

* * * * @author Mark L. Irons * @version 1.0 * @date 18-11-1998 */ public class LetsMakeADealApplet extends Applet implements ImageCanvasEventHandler { Random randomizer = new Random(); int gamesPlayed = 0; int maxGamesPlayed = 100000; int numAutoplayGames = 300; int StayWinCount = 0; int StayLoseCount = 0; int SwitchWinCount = 0; int SwitchLoseCount = 0; int prizeDoor = -1; // door with prize int selectedDoor = -1; // first door player selects int fakeDoor = -1; // kept closed, no prize int numDoors = 3; // default value Label StayWinLabel = new Label(); Label StayLoseLabel = new Label(); Label SwitchWinLabel = new Label(); Label SwitchLoseLabel = new Label(); DoorCanvas Door[] = null; Button ResetButton = new Button("Reset"); Button AutoplayButton = new Button("Autoplay"); Label prizeLabel = new Label(""); /** * Reads parameters from APPLET tag, loads images, lays out components, * initializes game. */ public void init() { // get applet parameters with some elementary sanity checks String s = getParameter("doors"); if (s != null) { int d = (new Integer(s)).intValue(); if ( d > 2 ) { numDoors = d; } } s = getParameter("autoplayGames"); if (s != null) { int games = (new Integer(s)).intValue(); if (games > 0) { numAutoplayGames = games; } } s = getParameter("resetValue"); if (s != null) { int play = (new Integer(s)).intValue(); if ( play > numAutoplayGames ) { maxGamesPlayed = play; } } // set background color setBackground(Color.white); // set layout setLayout(new BorderLayout()); // load images MediaTracker tracker = new MediaTracker(this); Image UnknownDoorImg = getImage(getDocumentBase(), "UnknownDoor.gif"); tracker.addImage(UnknownDoorImg,0); Image SelectedDoorImg = getImage(getDocumentBase(), "SelectedDoor.gif"); tracker.addImage(SelectedDoorImg,0); Image BadDoorImg = getImage(getDocumentBase(), "BadDoor.gif"); tracker.addImage(BadDoorImg,0); try { tracker.waitForID(0); } catch (InterruptedException iex) { System.out.println("How to choose / with no choices?\nCan't load needed images; applet stopped."); stop(); } // create and lay out doors Panel doorPanel = new Panel(); doorPanel.setLayout(new FlowLayout(FlowLayout.CENTER,15,15)); Door = new DoorCanvas[numDoors]; for (int i = 0; i < numDoors; i++) { Door[i] = new DoorCanvas(this,UnknownDoorImg,SelectedDoorImg,BadDoorImg); doorPanel.add(Door[i]); } this.add("Center",doorPanel); // layout statistics updateStats(); Panel statsPanel = new Panel(); statsPanel.setLayout(new FlowLayout(FlowLayout.CENTER,15,10)); statsPanel.add(StayWinLabel); statsPanel.add(StayLoseLabel); statsPanel.add(SwitchWinLabel); statsPanel.add(SwitchLoseLabel); // layout stats, reset & autoplay Panel scoringPanel = new Panel(); scoringPanel.setLayout(new GridLayout(2,1,5,2)); scoringPanel.add(statsPanel); Panel otherButtonPanel = new Panel(); otherButtonPanel.setLayout(new FlowLayout(FlowLayout.CENTER,20,2)); otherButtonPanel.add(ResetButton); otherButtonPanel.add(AutoplayButton); scoringPanel.add(otherButtonPanel); this.add("South",scoringPanel); // layout prize label Panel prizeLabelPanel = new Panel(); prizeLabelPanel.setLayout(new FlowLayout(FlowLayout.RIGHT,5,5)); prizeLabelPanel.add(prizeLabel); this.add("North",prizeLabelPanel); // initialize initGame(); paint(getGraphics()); } public void paint(Graphics g) { } /** * Initializes game. Chooses a door to hide prize behind, resets * everthing else. */ public void initGame() { // choose prize door prizeDoor = Math.abs(randomizer.nextInt()) % numDoors; // display it prizeLabel.setText("prizeDoor: "+(new Integer(1+prizeDoor)).toString()); // reset everything else selectedDoor = -1; for (int i = 0; i < numDoors; i++) { Door[i].setUnselected(); } } public void updateStayWin() { StayWinLabel.setText("Stay/Win: "+(new Integer(StayWinCount)).toString()); } public void updateStayLose() { StayLoseLabel.setText("Stay/Lose: "+(new Integer(StayLoseCount)).toString()); } public void updateSwitchWin() { SwitchWinLabel.setText("Switch/Win: "+(new Integer(SwitchWinCount)).toString()); } public void updateSwitchLose() { SwitchLoseLabel.setText("Switch/Lose: "+(new Integer(SwitchLoseCount)).toString()); } /** * Updates all statistics */ public void updateStats() { updateStayWin(); updateStayLose(); updateSwitchWin(); updateSwitchLose(); } /** * Clears all counters and resets game */ public void clearEverything() { StayWinCount = 0; StayLoseCount = 0; SwitchWinCount = 0; SwitchLoseCount = 0; gamesPlayed = 0; updateStats(); initGame(); paint(getGraphics()); } /** * Marks given door as selected. Reveals what's behind bad door(s). * * @param door player's intially selected door */ public void chooseFirstDoor(int door) { // mark selected door selectedDoor = door; Door[selectedDoor].setSelected(); // reveal bad doors if (selectedDoor == prizeDoor) { // pick fake door, open all doors but prize & fake fakeDoor = Math.abs(randomizer.nextInt()) % (numDoors-1); if (fakeDoor >= selectedDoor) fakeDoor++; for (int i = 0; i < numDoors; i++) { if ((i != selectedDoor) && (i != fakeDoor)) { Door[i].setBad(); } } } else { // reveal all doors but prize door for ( int i = 0; i < numDoors; i++ ) { if ((i != selectedDoor) && (i != prizeDoor)) { Door[i].setBad(); } } fakeDoor = selectedDoor; } paint(getGraphics()); } /** * Decides what to do when the player selects a door. * * @param door player's selected door */ public void gameLogic(int door) { if (selectedDoor == -1) { chooseFirstDoor(door); } else { if (Door[door].isBad()) { // can't select already opened door, do nothing } else { // compute win, and if it's a switch if (selectedDoor == door) { // stay if (prizeDoor == door) { StayWinCount++; updateStayWin(); } else { StayLoseCount++; updateStayLose(); } } else { // switch if (prizeDoor == door) { SwitchWinCount++; updateSwitchWin(); } else { SwitchLoseCount++; updateSwitchLose(); } } gamesPlayed++; if (gamesPlayed > maxGamesPlayed) { clearEverything(); } initGame(); paint(getGraphics()); } } } /** * Plays the game automatically */ public void autoPlay() { for ( int i = 0; i < numAutoplayGames; i++ ) { // start new game initGame(); // choose first door int firstDoor = Math.abs(randomizer.nextInt()) % numDoors; chooseFirstDoor(firstDoor); // choose either selected door or other door if ((Math.abs(randomizer.nextInt()) % 2) == 0) { gameLogic(prizeDoor); } else { gameLogic(fakeDoor); } } } /** * This method is a callback that's called when the player * clicks a door. It determines which door was clicked, * then passes that information to gameLogic.

* * I know, it breaks encapsulation. So sue me.

* * @param source door that was clicked */ public void imageCanvasEvent(ImageCanvas source) { for ( int i = 0; i < numDoors; i++ ) { if (source == Door[i]) { gameLogic(i); } } } /** * Deal with all other interface interaction (except doors) */ public boolean action(Event event, Object arg) { if (event.target == ResetButton) { clearEverything(); return true; } if (event.target == AutoplayButton) { autoPlay(); return true; } else return super.action(event,arg); } } // class LetsMakeADealApplet