Question: I am working on a number guessing game in java. The goal of this game is to guess a 4-digit number according to the game
I am working on a number guessing game in java.
The goal of this game is to guess a 4-digit number according to the game rules. There are a host and a player. The project is designed such that the computer can be either the host or the player. The game works as follows:
The host picks a 4-digit number (i.e. any number between 1000 and 9999). Lets call this the base number. In the following example, let's pick 5432 as the base number.
The player takes a guess, for example, 1234.
The host tells the player how many digits of the guess number match the base number. A match is defined as the same digit in the same position. For example, 1234 and 5432 have 1 match (at position 3); 2345 and 5432 have 0 match even though its the same set of digits, none matches in the exact same position.
Based on the number of matches, the player performs some update and takes another guess, say 5533.
The host again tells the player the number of matches. This time, 5533 and 5432 have 2 matches.
Repeat steps 4 and 5 until the game is over. The game is over when the host tells the player that all 4 digits are matched. Therefore the player has found the base number.
The game must use linkedlists to store information such as all the candidates (possible numbers) and the prior guesses
Here is the LinkedListGame.java I work on as all code should be written down in this class as well as the LLIntegerNode.java where an implementation of a custom LinkedList is written:
LinkedListGame.java:
package guessme;
/** * A LinkedList-based implementation of the Guess-A-Number game */ public class LinkedListGame {
// TODO: declare data members as necessary /******************************************************** * NOTE: for this project you must use linked lists * implemented by yourself. You are NOT ALLOWED to use * Java arrays of any type, or any class in the java.util * package (such as ArrayList). *******************************************************/ /******************************************************** * NOTE: you are allowed to add new methods if necessary, * but DO NOT remove any provided method, and do NOT add * new files (as they will be ignored by the autograder). *******************************************************/ // LinkedListGame constructor method public LinkedListGame() { // TODO } // Resets data members and game state so we can play again public void reset() { // TODO } // Returns true if n is a prior guess; false otherwise. public boolean isPriorGuess(int n) { // TODO return false; } // Returns the number of guesses so far. public int numGuesses() { // TODO return 0; } /** * Returns the number of matches between integers a and b. * You can assume that both are 4-digits long (i.e. between 1000 and 9999). * The return value must be between 0 and 4. * * A match is the same digit at the same location. For example: * 1234 and 4321 have 0 match; * 1234 and 1114 have 2 matches (1 and 4); * 1000 and 9000 have 3 matches (three 0's). */ public static int numMatches(int a, int b) { // TODO return 0; } /** * Returns true if the game is over; false otherwise. * The game is over if the number has been correctly guessed * or if no candidate is left. */ public boolean isOver() { // TODO return false; } /** * Returns the guess number and adds it to the list of prior guesses. * The insertion should occur at the end of the prior guesses list, * so that the order of the nodes follow the order of prior guesses. */ public int getGuess() { // TODO: add guess to the list of prior guesses. return 0; } /** * Updates guess based on the number of matches of the previous guess. * If nmatches is 4, the previous guess is correct and the game is over. * Check project description for implementation details. * * Returns true if the update has no error; false if no candidate * is left (indicating a state of error); */ public boolean updateGuess(int nmatches) { // TODO return true; } // Returns the head of the prior guesses list. // Returns null if there hasn't been any prior guess public LLIntegerNode priorGuesses() { // TODO return null; } /** * Returns the list of prior guesses as a String. For example, * if the prior guesses are 1000, 2111, 3222, in that order, * the returned string should be "1000, 2111, 3222", in the same order, * with every two numbers separated by a comma and space, except the * last number (which should not be followed by either comma or space). * * Returns an empty string if here hasn't been any prior guess */ public String priorGuessesString() { // TODO return ""; } }
Here is LLIntegerNode.java:
package guessme;
/** * This class defines a linked list node storing an integer. * Use primitive type int (do not use wrapper class Integer) * You must provide the following methods: * - a constructor * - a setInfo method and a getInfo method * - a setLink method and a getLink method */ public class LLIntegerNode { // TODO
}
Here is the PlayGame.java:
package guessme;
import javax.swing.JOptionPane;
public class PlayGame { // Computer as the player of the game public static void main(String[] args) { LinkedListGame gamer = new LinkedListGame();
JOptionPane.showMessageDialog(null, "Think of a number between 1000 and 9999. Click OK when you are ready...", "Let's play a game", JOptionPane.INFORMATION_MESSAGE); int guess=0, nmatches=0; while(!gamer.isOver()) { // take guess guess = gamer.getGuess(); String userInput = JOptionPane.showInputDialog("I guess your number is " + guess + ". How many digits are matched?"); if (userInput == null) System.exit(0); try { nmatches = Integer.parseInt(userInput.trim()); } catch(Exception exception) { JOptionPane.showMessageDialog(null, "Invalid. Please enter a number between 0 and 4", "Warning", JOptionPane.WARNING_MESSAGE); continue; } // the number of matches must be between 0 and 4 if (nmatches < 0 || nmatches > 4) { JOptionPane.showMessageDialog(null, "Invalid. Please enter a number between 0 and 4", "Warning", JOptionPane.WARNING_MESSAGE); continue; } // update based on user input if(gamer.updateGuess(nmatches)==false) { JOptionPane.showMessageDialog(null, "Something is wrong. I don't think your number exists...", "Mistake", JOptionPane.INFORMATION_MESSAGE); System.exit(0); } } System.out.println("I got it. Your number was "+guess+"."); System.out.println("I did it in "+gamer.numGuesses()+" rounds. Here is the list of my guesses:"); System.out.println(gamer.priorGuessesString()); } }
Here is the HostGame.java:
package guessme;
import java.util.Random; import java.util.Scanner;
public class HostGame { // Computer as the host of the game public static void main(String[] args) { Random rnd = new Random(); Scanner conIn = new Scanner(System.in);
int groundtruth = rnd.nextInt(9000)+1000; System.out.println("I have thought of a number for you to guess. Let's play!"); int nguesses = 0; while(true) { // take guess System.out.print("What's your guess? Input a 4-digit integer: "); int guess; try { guess = conIn.nextInt(); } catch(Exception e) { conIn.nextLine(); System.out.println("Invalid input!"); continue; } if(guess<1000 || guess>9999) { System.out.println("Your number is out of range!"); continue; } nguesses ++; int nmatches = LinkedListGame.numMatches(guess, groundtruth); if(nmatches==4) { System.out.print("You have won! "); break; } else { System.out.println("Almost there. Number of matches: "+nmatches); } } System.out.println("The number I had was "+groundtruth); System.out.println("You got it in "+nguesses+" rounds."); conIn.close(); } }
Lastly, here are the Junit tests I used:
package guessme;
import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Test;
public class LinkedListGamePublicTest {
private LinkedListGame gamerA, gamerB; @Before public void before() { gamerA = new LinkedListGame(); gamerB = new LinkedListGame(); } @Test(timeout = 1000) public void testReset() { gamerA.getGuess(); gamerA.updateGuess(0); gamerA.reset(); assertEquals("numGuesses after reset", 0, gamerA.numGuesses()); assertFalse("isOver after reset", gamerA.isOver()); assertEquals("priorGuesses after reset", null, gamerA.priorGuesses()); assertEquals("priorGuessesString after reset", "", gamerA.priorGuessesString()); } @Test(timeout = 1000) public void testFirstGuessAndUpdate() { gamerA.reset(); assertEquals("test first guess", 1000, gamerA.getGuess()); assertEquals("test first guess", 1, gamerA.numGuesses()); assertEquals("test first guess", 1000, gamerA.priorGuesses().getInfo()); assertEquals("test first guess", null, gamerA.priorGuesses().getLink()); assertEquals("test first guess", "1000", gamerA.priorGuessesString()); gamerA.updateGuess(0); assertFalse("isOver after first update", gamerA.isOver()); } @Test(timeout = 1000) public void testIsOver() { gamerA.reset(); gamerB.reset(); assertFalse("gameB not over yet", gamerB.isOver()); assertEquals("gameB 1st guess", 1000, gamerB.getGuess()); gamerB.updateGuess(4); assertTrue("gameB is over", gamerB.isOver()); assertFalse("gameA not over yet", gamerA.isOver()); } @Test(timeout = 1000) public void testIsPriorGuess() { gamerA.reset(); int g1 = gamerA.getGuess(); assertTrue("is prior guess", gamerA.isPriorGuess(g1)); assertFalse("not prior guess", gamerA.isPriorGuess(9999)); gamerA.updateGuess(0); int g2 = gamerA.getGuess(); assertTrue("is prior guess", gamerA.isPriorGuess(g2)); assertFalse("not prior guess", gamerA.isPriorGuess(9999)); } @Test(timeout = 1000) public void testNumGuesses() { gamerB.reset(); assertEquals("number of guesses shold be 0", 0, gamerB.numGuesses()); assertEquals("number of guesses shold be 0", 0, gamerB.numGuesses()); gamerB.getGuess(); assertEquals("number of guesses shold be 1", 1, gamerB.numGuesses()); assertEquals("number of guesses shold be 1", 1, gamerB.numGuesses()); gamerB.updateGuess(0); gamerB.getGuess(); assertEquals("number of guesses shold be 2", 2, gamerB.numGuesses()); assertEquals("number of guesses shold be 2", 2, gamerB.numGuesses()); gamerB.updateGuess(4); gamerB.getGuess(); assertEquals("number of guesses shold be 3", 3, gamerB.numGuesses()); assertEquals("number of guesses shold be 3", 3, gamerB.numGuesses()); } @Test(timeout = 1000) public void testUpdateGuessTrivial() { gamerB.reset(); // ground truth number is 1000 assertEquals("gamerB first guess", 1000, gamerB.getGuess()); assertTrue("gamerB first update", gamerB.updateGuess(4)); assertTrue("gamerB game over", gamerB.isOver()); } @Test(timeout = 1000) public void testUpdateGuess() { gamerA.reset(); // ground truth number is 3242 assertEquals("gamerA first guess", 1000, gamerA.getGuess()); assertTrue("gamerA first update", gamerA.updateGuess(0)); assertEquals("gamerA second guess", 2111, gamerA.getGuess()); assertTrue("gamerA second update", gamerA.updateGuess(0)); assertEquals("gamerA third guess", 3222, gamerA.getGuess()); assertTrue("gamerA third update", gamerA.updateGuess(3)); assertEquals("gamerA fourth guess", 3223, gamerA.getGuess()); assertTrue("gamerA fourth update", gamerA.updateGuess(2)); assertEquals("gamerA fifth guess", 3232, gamerA.getGuess()); assertTrue("gamerA fifth update", gamerA.updateGuess(3)); assertEquals("gamerA sixth guess", 3242, gamerA.getGuess()); assertTrue("gamerA sixth update", gamerA.updateGuess(4)); assertTrue("gamerA game over", gamerA.isOver()); } @Test(timeout = 1000) public void testUpdateGuessError() { gamerA.reset(); gamerA.getGuess(); // should be 1000 gamerA.updateGuess(3); gamerA.getGuess(); // should be 1001 assertFalse("state of error", gamerA.updateGuess(1)); // this number does not exist // updateGuess should return false gamerA.reset(); gamerA.getGuess(); // should be 1000 gamerA.updateGuess(3); gamerA.getGuess(); // should be 1001 gamerA.updateGuess(2); gamerA.getGuess(); // should be 1010 assertFalse("state of error", gamerA.updateGuess(1)); // this number does not exist // updateGuess should return false } @Test(timeout = 1000) public void testPriorGuesses() { gamerB.reset(); assertEquals("test prior guesses", null, gamerB.priorGuesses()); int g1 = gamerB.getGuess(); LLIntegerNode pl = gamerB.priorGuesses(); assertEquals("test prior guesses", g1, pl.getInfo()); assertEquals("test prior guesses", null, pl.getLink()); gamerB.updateGuess(1); int g2 = gamerB.getGuess(); pl = gamerB.priorGuesses(); assertEquals("test prior guesses", g1, pl.getInfo()); assertEquals("test prior guesses", g2, pl.getLink().getInfo()); gamerB.updateGuess(2); int g3 = gamerB.getGuess(); pl = gamerB.priorGuesses(); assertEquals("test prior guesses", g1, pl.getInfo()); assertEquals("test prior guesses", g2, pl.getLink().getInfo()); assertEquals("test prior guesses", g3, pl.getLink().getLink().getInfo()); gamerB.updateGuess(3); int g4 = gamerB.getGuess(); pl = gamerB.priorGuesses(); assertEquals("test prior guesses", g1, pl.getInfo()); assertEquals("test prior guesses", g2, pl.getLink().getInfo()); assertEquals("test prior guesses", g3, pl.getLink().getLink().getInfo()); assertEquals("test prior guesses", g4, pl.getLink().getLink().getLink().getInfo()); gamerB.updateGuess(3); pl = gamerB.priorGuesses(); assertEquals("test prior guesses", g1, pl.getInfo()); assertEquals("test prior guesses", g2, pl.getLink().getInfo()); assertEquals("test prior guesses", g3, pl.getLink().getLink().getInfo()); assertEquals("test prior guesses", g4, pl.getLink().getLink().getLink().getInfo()); } @Test(timeout = 1000) public void testPriorGuessesString() { gamerB.reset(); assertEquals("test prior guesses string", "", gamerB.priorGuessesString()); int g1 = gamerB.getGuess(); String g = new String(); g = g+g1; assertEquals("test prior guesses string", g, gamerB.priorGuessesString()); gamerB.updateGuess(1); int g2 = gamerB.getGuess(); g = g+", "+g2; gamerB.updateGuess(2); int g3 = gamerB.getGuess(); g = g+", "+g3; gamerB.updateGuess(3); int g4 = gamerB.getGuess(); g = g+", "+g4; assertEquals("test prior guesses string", g, gamerB.priorGuessesString()); gamerB.updateGuess(4); assertEquals("test prior guesses string", g, gamerB.priorGuessesString()); } }
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
