/** MyApplet14: Basic GUI Components and the Game 3-Nim ** ** 3-Nim is a version of the game Nim, in which there ** are several sticks (counters) laying on a table, ** and on each turn a player must take at least one, ** but no more than three sticks. There are two players ** alternating turns, and the player who takes the last ** stick is the loser. So, the goal of the game is to ** force your opponent to take the last stick. ** ** Assignment: Play the game until you think you have ** a winning strategy and then study the program and ** try to understand how everything works. ** ** Also, take a look at the MyApplet14.html webpage ** file for displaying this applet. **/ import java.applet.Applet; import java.awt.*; public class MyApplet14 extends Applet { private Choice randomPlayChoice; // Specify GUI layout items. private List startCountersList; private Choice playFirstChoice; private Button startGameButton; private Checkbox[] chooseNumberBox; private Label computerMoveLabel; private Label numberLeftLabel; private Label gameOverLabel; private int startCounters; // Specify global integer variables. private int numLeft; private boolean computerRandom; // Specify global boolean (true/false) variables. private boolean humanFirst; public void init() { add(new Label("How do you want the computer to play?")); // Add label to GUI layout. randomPlayChoice = new Choice(); // Create drop-down menu Choice list (randomPlayChoice). randomPlayChoice.addItem("Randomly"); randomPlayChoice.addItem("Intelligently"); randomPlayChoice.select(0); add(randomPlayChoice); // Add drop-down menu Choice list to GUI layout. add(new Label("How many sticks to start with?")); // Add label to GUI layout. startCountersList = new List(5, false); // Create scrollable List (startCountersList). startCountersList.addItem("10"); startCountersList.addItem("11"); startCountersList.addItem("12"); startCountersList.addItem("13"); startCountersList.addItem("14"); startCountersList.addItem("15"); startCountersList.addItem("16"); startCountersList.addItem("17"); startCountersList.addItem("18"); startCountersList.addItem("19"); startCountersList.addItem("20"); startCountersList.select(0); add(startCountersList); // Add scrollable List to GUI layout. add(new Label("Do you want to play first?")); // Add label to GUI layout. playFirstChoice = new Choice(); // Create drop-down menu Choice list (playFirstChoice). playFirstChoice.addItem("Yes"); playFirstChoice.addItem("No"); playFirstChoice.select(0); add(playFirstChoice); // Add drop-down menu Choice list to GUI layout. startGameButton = new Button("Start game"); // Create Button (StartGameButton). add(startGameButton); // Add Button to GUI layout. add(new Label("Select the number of sticks to take:")); // Add label to GUI layout. CheckboxGroup chooseNumberGroup = new CheckboxGroup(); // Create CheckboxGroup (chooseNumberGroup). chooseNumberBox = new Checkbox[3]; // Create a list of three Checkboxes (chooseNumberBox) chooseNumberBox[0] = new Checkbox("One stick", chooseNumberGroup, false); // and group them together in chooseNumberGroup. chooseNumberBox[1] = new Checkbox("Two sticks", chooseNumberGroup, false); chooseNumberBox[2] = new Checkbox("Three sticks", chooseNumberGroup, false); for (int boxNum = 0; boxNum < 3; ++boxNum) // Add three Checkboxes to GUI layout. { add(chooseNumberBox[boxNum]); chooseNumberBox[boxNum].disable(); } computerMoveLabel = new Label(" "); // Create three labels, numberLeftLabel = new Label(" "); // initially all blank. gameOverLabel = new Label(" "); add(computerMoveLabel); // Add three labels to GUI layout, which add(numberLeftLabel); // will be filled in appropriately add(gameOverLabel); // during the play of the game. } private void startGame() // This method is called by the user action detection { // method (below), which starts the game. startCounters = Integer.parseInt(startCountersList.getSelectedItem()); // Get the chosen value of startCounters (sticks) numLeft = startCounters; // and set numLeft = startCounters. computerRandom = (randomPlayChoice.getSelectedItem() == "Randomly"); // These two boolean variables are assigned the humanFirst = (playFirstChoice.getSelectedItem() == "Yes"); // same truth value as the statement in parentheses. for (int boxNum = 0; boxNum < 3; ++boxNum) { chooseNumberBox[boxNum].enable(); // Enable chooseNumberBoxes, but make them chooseNumberBox[boxNum].setState(false); // unselected. } numberLeftLabel.setText(" There are " + numLeft + " sticks left."); // Echo back the chosen number of counters (sticks). gameOverLabel.setText(" ");// Clear game over text--needed // if this is the 2nd time (or more) // the game is played. if (humanFirst) // If humanFirst = true, prompt user to move. computerMoveLabel.setText(" The computer is waiting for your move. "); // Otherwise, the computer should move first, else // so, call the computerMove() method. computerMove(); } private void computerMove() // This method is called by the user action detection { // method (below), or by the startGame() method (above). int numTake, maxTake; if (numLeft == 0) // If numLeft is 0 and computerMove() is called, then { // the user took the last one and lost the game. numberLeftLabel.setText(" There are 0 sticks left. "); gameOverLabel.setText(" Game over. You lose! "); chooseNumberBox[0].disable(); chooseNumberBox[1].disable(); chooseNumberBox[2].disable(); return; } if (!computerRandom && (numLeft - 1) % 4 != 0) // If the computer is supposed to play intelligently and { // the user didn't leave one more than a mulitple of four, if (numLeft % 4 == 0) numTake = 3; // then the computer chooses a winning position. else numTake = numLeft % 4 - 1; // Note that in the else clause: numLeft % 4 = 2 or 3. } else // Otherwise, either the computer is supposed to play { // randomly or doesn't have a winning position. if (numLeft >= 3) maxTake = 3; // In either case, the computer just plays randomly. else maxTake = numLeft; numTake = (int)(maxTake * Math.random() + 1); } numLeft -= numTake; // Adjust numLeft and the report computerMoveLabel.setText(" The computer takes " + numTake + " stick(s). "); // the computer's move to the numberLeftLabel.setText(" There are " + numLeft + " stick(s) left. "); // user. if (numLeft < 3) // If necessary disable some or chooseNumberBox[2].disable(); // all of the chooseNumberBoxes. if (numLeft < 2) chooseNumberBox[1].disable(); if (numLeft == 0) { chooseNumberBox[0].disable(); gameOverLabel.setText(" Game over. You win! "); // Report that the user won the game. } } public boolean action(Event event, Object object) // Detect user action from the GUI (the game starts here). { if (event.target == startGameButton) // If the user clicks the startGameButton, startGame(); // then call the startGame() method. else if (event.target == chooseNumberBox[2]) // Otherwise, if the user makes a move, { // then update the numLeft variable, and numLeft -= 3; // call the computerMove() method. computerMove(); } else if (event.target == chooseNumberBox[1]) { numLeft -= 2; computerMove(); } else if (event.target == chooseNumberBox[0]) { numLeft -= 1; computerMove(); } return true; } }