patternjavaMinor
Three-player number-guessing game
Viewed 0 times
threenumberplayergameguessing
Problem
This is a sample exercise tutorial that would be used to test understanding of how simple classes communicate/message and are designed.
Tester class
Player class
Game class
```
public class GuessingGame {
private int numberToGuess;
private boolean keepPlaying;
private int round;
//constructor
GuessingGame(){
//create a random number for players to guess
numberToGuess = (int) (Math.random() * 20);//cast to int
keepPlaying = true;
round = 1;
}
void startGame(){
//create 3 players to play
GuessingGamePlayer p1 = new GuessingGamePlayer();
GuessingGamePlayer p2 = new GuessingGamePlayer();
GuessingGamePlayer p3 = new GuessingGamePlayer();
System.out.println("The number to guess is : " + numberToGuess);
//giving 100 attemps for the computer to guess the correct number
while(keepPlaying && round <= 100){
//get their guess
int p1guess = p1.getPlayerGuess();
int p2guess = p2.getPlayerGuess();
int p3guess = p3.getPlayerGuess();
System.out.println("round " + round);
System.out.println("p1 guessed: " + p1guess);
System.out.println("p2 guessed: " + p2guess);
System.out.println("p3 guessed: " + p3guess);
System.out.println("\n");
if(p1guess == numberToGuess){
p1.areTheyRight = true;
keepPlaying = false;
}else if(p2guess == numberToGuess){
p2.areTheyRight = true;
Tester class
public class GuessingGameTester {
public static void main(String[] args){
//create a new game
GuessingGame g1 = new GuessingGame();
//call the start method
g1.startGame();
}
}Player class
public class GuessingGamePlayer {
boolean areTheyRight = false;
//player random guess
int getPlayerGuess(){
return (int) (Math.random()* 20);
}
}Game class
```
public class GuessingGame {
private int numberToGuess;
private boolean keepPlaying;
private int round;
//constructor
GuessingGame(){
//create a random number for players to guess
numberToGuess = (int) (Math.random() * 20);//cast to int
keepPlaying = true;
round = 1;
}
void startGame(){
//create 3 players to play
GuessingGamePlayer p1 = new GuessingGamePlayer();
GuessingGamePlayer p2 = new GuessingGamePlayer();
GuessingGamePlayer p3 = new GuessingGamePlayer();
System.out.println("The number to guess is : " + numberToGuess);
//giving 100 attemps for the computer to guess the correct number
while(keepPlaying && round <= 100){
//get their guess
int p1guess = p1.getPlayerGuess();
int p2guess = p2.getPlayerGuess();
int p3guess = p3.getPlayerGuess();
System.out.println("round " + round);
System.out.println("p1 guessed: " + p1guess);
System.out.println("p2 guessed: " + p2guess);
System.out.println("p3 guessed: " + p3guess);
System.out.println("\n");
if(p1guess == numberToGuess){
p1.areTheyRight = true;
keepPlaying = false;
}else if(p2guess == numberToGuess){
p2.areTheyRight = true;
Solution
I'd add only a couple of minor things.
The comments are more trouble than they're worth. I understand it's a tutorial, but if they're going to be in there, they should do more--right now they don't add value. Since it's a learning exercise, use those comments to teach them something, including terminology.
But I'd leave them out altogether, and have the corresponding text/lecture do the describing; you will achieve more by writing or talking about them outside of the code.
Secondly, I'd consider keeping the players in an array or a list. If not now, then in "part two". This simplifies the code conceptually, because you can directly represent "for each player, check their guess" in code. If not in "part one", then I'd at least move the guess-getting into another method--you only need to return a boolean, the players hold whether or not it's a right guess.
(IMO the player shouldn't maintain that state, rather the game should.)
Next, I'd refactor more; the
On a more theoretical level, the end conditions as implemented makes a certain assumption about the nature of the game. Asking if anyone can spot a potential "gotcha" with the current implementation might be a good "extra credit" problem.
In real life, what would happen if two players both guessed correctly? In the current implementation, the players are always checked in numerical order. In real life, a typical game would be either who guessed the fastest (which I supposed the player order could be said to represent), or multiple players could win, or...?
To put that into "real life" terms, let's say the guesses are access control votes, or search result weightings, etc. In those cases, a tie does matter. So instead of having a single winner, there would be a collection of "winners". How to decide if there should be a single winner, or a group, depends on the nature of the game.
Lastly, I'd make some of the things more configurable, although perhaps with reasonable defaults. This also mirrors real life a bit more accurately, and I tend towards adding a bit of complexity early, since it can be ignored.
Some of my suggestions are more appropriate for a "second round" implementation, while some make sense for what you have now. Pick and choose, or ignore them all :) I've appended everything in a single blob.
```
public class GuessingGameTester {
public static void main(String[] args){
GuessingGame game = new GuessingGame();
game.startGame();
}
}
public class GuessingGamePlayer {
private int playerNumber;
public GuessingGamePlayer(int playerNumber) {
this.playerNumber = playerNumber;
}
int getGuess(){
return new Random().nextInt(GuessingGame.MAX_GUESSING_NUMBER) + 1;
}
@Override
public String toString() {
return "Player " + playerNumber;
}
}
public class GuessingGame {
private int numberToGuess;
private int roundsToPlay;
private int numberOfPlayers;
private List players;
public static int MAX_GUESSING_NUMBER = 20;
public GuessingGame() {
init(100, 3);
}
public GuessingGame(int roundsToPlay, int numberOfPlayers) {
init(roundsToPlay, numberOfPlayers);
}
public void init(int numberOfRounds, int numberOfPlayers) {
this.roundsToPlay = numberOfRounds;
this.numberOfPlayers = numberOfPlayers;
numberToGuess = new Random().nextInt(MAX_GUESSING_NUMBER) + 1;
initPlayers();
}
public void initPlayers() {
players = new ArrayList();
for (int i = 0; i < numberOfPlayers; i++) {
players.add(new GuessingGamePlayer(i+1));
}
}
public void startGame() {
int currentRound = 0;
GuessingGamePlayer correctGuesser = null;
System.out.println("The number to guess is: " + numberToGuess);
while((correctGuesser == null) && (currentRound <= roundsToPlay)) {
++currentRound;
System.out.println("\nRound " + currentRound);
for (GuessingGamePlayer player : players) {
int playerGuess = player.getGuess();
System.out.println(" " + player + " guessed " + playerGuess);
if (playerGuess == numberToGuess) {
correctGuesser = player;
}
}
}
System.out.println();
if (correctGuesser == null) {
System.out.println("Nobody guessed the right number!");
} else {
System.out.println(correctGuesser + " guessed the number in round " + currentRound);
The comments are more trouble than they're worth. I understand it's a tutorial, but if they're going to be in there, they should do more--right now they don't add value. Since it's a learning exercise, use those comments to teach them something, including terminology.
// Create a new GuessingGame instance to represent the current game.
// Begin playing by calling the startGame() method.But I'd leave them out altogether, and have the corresponding text/lecture do the describing; you will achieve more by writing or talking about them outside of the code.
Secondly, I'd consider keeping the players in an array or a list. If not now, then in "part two". This simplifies the code conceptually, because you can directly represent "for each player, check their guess" in code. If not in "part one", then I'd at least move the guess-getting into another method--you only need to return a boolean, the players hold whether or not it's a right guess.
(IMO the player shouldn't maintain that state, rather the game should.)
Next, I'd refactor more; the
startGame does more than starts the game. Either refactor, or rename. Right now, startGame starts, plays, and ends the game. By refactoring, the code becomes more story-like, at the cost of more methods. But good methods should be tightly focused and easy to reason about.On a more theoretical level, the end conditions as implemented makes a certain assumption about the nature of the game. Asking if anyone can spot a potential "gotcha" with the current implementation might be a good "extra credit" problem.
In real life, what would happen if two players both guessed correctly? In the current implementation, the players are always checked in numerical order. In real life, a typical game would be either who guessed the fastest (which I supposed the player order could be said to represent), or multiple players could win, or...?
To put that into "real life" terms, let's say the guesses are access control votes, or search result weightings, etc. In those cases, a tie does matter. So instead of having a single winner, there would be a collection of "winners". How to decide if there should be a single winner, or a group, depends on the nature of the game.
Lastly, I'd make some of the things more configurable, although perhaps with reasonable defaults. This also mirrors real life a bit more accurately, and I tend towards adding a bit of complexity early, since it can be ignored.
Some of my suggestions are more appropriate for a "second round" implementation, while some make sense for what you have now. Pick and choose, or ignore them all :) I've appended everything in a single blob.
```
public class GuessingGameTester {
public static void main(String[] args){
GuessingGame game = new GuessingGame();
game.startGame();
}
}
public class GuessingGamePlayer {
private int playerNumber;
public GuessingGamePlayer(int playerNumber) {
this.playerNumber = playerNumber;
}
int getGuess(){
return new Random().nextInt(GuessingGame.MAX_GUESSING_NUMBER) + 1;
}
@Override
public String toString() {
return "Player " + playerNumber;
}
}
public class GuessingGame {
private int numberToGuess;
private int roundsToPlay;
private int numberOfPlayers;
private List players;
public static int MAX_GUESSING_NUMBER = 20;
public GuessingGame() {
init(100, 3);
}
public GuessingGame(int roundsToPlay, int numberOfPlayers) {
init(roundsToPlay, numberOfPlayers);
}
public void init(int numberOfRounds, int numberOfPlayers) {
this.roundsToPlay = numberOfRounds;
this.numberOfPlayers = numberOfPlayers;
numberToGuess = new Random().nextInt(MAX_GUESSING_NUMBER) + 1;
initPlayers();
}
public void initPlayers() {
players = new ArrayList();
for (int i = 0; i < numberOfPlayers; i++) {
players.add(new GuessingGamePlayer(i+1));
}
}
public void startGame() {
int currentRound = 0;
GuessingGamePlayer correctGuesser = null;
System.out.println("The number to guess is: " + numberToGuess);
while((correctGuesser == null) && (currentRound <= roundsToPlay)) {
++currentRound;
System.out.println("\nRound " + currentRound);
for (GuessingGamePlayer player : players) {
int playerGuess = player.getGuess();
System.out.println(" " + player + " guessed " + playerGuess);
if (playerGuess == numberToGuess) {
correctGuesser = player;
}
}
}
System.out.println();
if (correctGuesser == null) {
System.out.println("Nobody guessed the right number!");
} else {
System.out.println(correctGuesser + " guessed the number in round " + currentRound);
Code Snippets
// Create a new GuessingGame instance to represent the current game.
// Begin playing by calling the startGame() method.public class GuessingGameTester {
public static void main(String[] args){
GuessingGame game = new GuessingGame();
game.startGame();
}
}
public class GuessingGamePlayer {
private int playerNumber;
public GuessingGamePlayer(int playerNumber) {
this.playerNumber = playerNumber;
}
int getGuess(){
return new Random().nextInt(GuessingGame.MAX_GUESSING_NUMBER) + 1;
}
@Override
public String toString() {
return "Player " + playerNumber;
}
}
public class GuessingGame {
private int numberToGuess;
private int roundsToPlay;
private int numberOfPlayers;
private List<GuessingGamePlayer> players;
public static int MAX_GUESSING_NUMBER = 20;
public GuessingGame() {
init(100, 3);
}
public GuessingGame(int roundsToPlay, int numberOfPlayers) {
init(roundsToPlay, numberOfPlayers);
}
public void init(int numberOfRounds, int numberOfPlayers) {
this.roundsToPlay = numberOfRounds;
this.numberOfPlayers = numberOfPlayers;
numberToGuess = new Random().nextInt(MAX_GUESSING_NUMBER) + 1;
initPlayers();
}
public void initPlayers() {
players = new ArrayList<GuessingGamePlayer>();
for (int i = 0; i < numberOfPlayers; i++) {
players.add(new GuessingGamePlayer(i+1));
}
}
public void startGame() {
int currentRound = 0;
GuessingGamePlayer correctGuesser = null;
System.out.println("The number to guess is: " + numberToGuess);
while((correctGuesser == null) && (currentRound <= roundsToPlay)) {
++currentRound;
System.out.println("\nRound " + currentRound);
for (GuessingGamePlayer player : players) {
int playerGuess = player.getGuess();
System.out.println(" " + player + " guessed " + playerGuess);
if (playerGuess == numberToGuess) {
correctGuesser = player;
}
}
}
System.out.println();
if (correctGuesser == null) {
System.out.println("Nobody guessed the right number!");
} else {
System.out.println(correctGuesser + " guessed the number in round " + currentRound);
}
}
}Context
StackExchange Code Review Q#5853, answer score: 4
Revisions (0)
No revisions yet.