Question
Working on a number guessing game in java. 1) You should store prior guesses in a linked list, and the nodes in the list must
Working on a number guessing game in java.
1) You should store prior guesses in a linked list, and the nodes in the list must follow the order of prior guesses. For example, if the prior guesses are 1000, 2111, 3222 in that order, the nodes must follow the same order.
2) You should store the candidate numbers also in a linked list, and the nodes must follow the order of numbers (i.e. from the smallest to the largest).
You store the candidate numbers (i.e. the complement set of the eliminated numbers) in a linked list. The reason is that choosing the next guess is much simpler this way, as you will see below. At the start of the game, you should create the candidate list, which contains all numbers from 1000 to 9999, in that order.
Since any of them is equally likely to be the basenumber, your algorithm simply chooses the first candidate (i.e. the head), 1000, as the initial guess. Therefore the getGuess() method will initially return 1000.
The host compares the guess with the basenumber, and tells the player how many matches there are. The number of matches is passed to the player through the updateGuess method. What this method should do is to examine all candidate numbers, and keep those that have the same number of matches with the players current guess. Why? Lets say the basenumber is 4321, and the initial guess is 1000. The host tells the player there is 0 match. This actually gives the player a lot of information, that is, a number remains a candidate if and only if it has 0 matches with the players current guess (1000). If the match is not 0, that number cannot possibly be the basenumber and hence should be removed from the candidate list.
You should create a new linked list that contains all numbers from the previous linked list except the numbers that should be removed. Specifically, in your updateGuess method, you should create a new candidate list, then traverse the existing candidate list and insert only those numbers that remain candidates to the new list. Finally, the newly created list replaces the old list. This way, you can achieve the effect of removing nodes without actually implementing removal. Note that because the list must preserve the order of the numbers, you should implement insertion at the end of the linked list (not front insertion).
Choosing the next guess now becomes trivial: the first candidate in the list (i.e. the head element) is the next number to guess. Continuing from the above example, 2111 should be at the head of the candidate list and is therefore what getGuess() method should return the next round its called. As the game goes on, the candidate list will quickly shrink, and eventually, the player will find the basenumber.
There are several additional methods you should implement. At any time, we can call int numGuesses() to return the number of guesses taken so far, LLIntegerNode priorGuesses() to return the head of the prior guesses list, and String priorGuessesString() to return the prior guesses as a comma-separated string. You will also need to implement boolean isOver() to indicate whether the game is over and reset() to reset the data structures and variables so we can play again. Once these methods are implemented, you can run PlayGame.java to let the computer play as a player, and run all public JUnit tests to help you check if there are any mistakes in your implementation.
The private JUnit tests will call reset() and isOver() repeatedly to play the game over and over again, so you must ensure that these methods are implemented correctly.
Erroneous Situation: What happens if the host makes a mistake and miscalculates the number of matches? This can lead to a situation where no candidate is left (i.e. all numbers are eliminated). Here is one example: lets say the host tells the player that the basenumber has 3 matches with 1234, but 1 match with 1235. This is impossible because no such number exists that has 3 matches with 1234 but only 1 match with 1235. The updateGuess() method can easily detect this situation when it finds that the candidate list is empty (i.e. no candidate is left). In this situation, it should return false indicating a state of error.
LinkedListGame.java:
package guessme;
/**
* A LinkedList-based implementation of the Guess-A-Number game
*/
public class LinkedListGame {
// TODO: declare data members as necessary
private LLIntegerNode head;
/********************************************************
* 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
head = new LLIntegerNode(1000,null);
}
// 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 "";
}
}
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
private int info;
private LLIntegerNode link;
public LLIntegerNode(int info,LLIntegerNode link) {
this.info = info;
this.link = link;
}
public int getInfo(){
return info;
}
public LLIntegerNode getLink(){
return link;
}
public void setInfo(int a){
info = a;
}
public void setLink (LLIntegerNode link){
this.link = link;
}
}
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();
}
}
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());
}
}
LinkedListGamePublicTest.java:
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());
}
}
I finished the LLIntegerNode.java but I am not sure what to do next.
Would rate, thanks.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started