Merge pull request #30 from journich/main

Java version of Bullseye
This commit is contained in:
Jeff Atwood
2021-02-18 11:23:40 -08:00
committed by GitHub
6 changed files with 496 additions and 0 deletions

View File

@@ -0,0 +1,248 @@
import java.util.ArrayList;
import java.util.Scanner;
public class Bullseye {
public static final int FIRST_IDENT = 10;
public static final int SECOND_IDENT = 30;
public static final int THIRD_INDENT = 30;
public static final double[] SHOT_ONE = new double[] { .65, .55, .5, .5};
public static final double[] SHOT_TWO = new double[] { .99, .77, .43,.01};
public static final double[] SHOT_THREE = new double[] { .95, .75, .45, .05 };
private enum GAME_STATE {
STARTING,
START_GAME,
PLAYING,
GAME_OVER
}
private GAME_STATE gameState;
private ArrayList<Player> players;
private Shot[] shots;
// Used for keyboard input
private Scanner kbScanner;
private int numberOfPlayers;
private int round;
public Bullseye() {
gameState = GAME_STATE.STARTING;
players = new ArrayList<>();
// Save the random chances of points based on shot type
shots = new Shot[3];
shots[0] = new Shot(SHOT_ONE);
shots[1] = new Shot(SHOT_TWO);
shots[2] = new Shot(SHOT_THREE);
// Initialise kb scanner
kbScanner = new Scanner(System.in);
}
/**
* Main game loop
*
*/
public void play() {
do {
switch (gameState) {
// Show an introduction the first time the game is played.
case STARTING:
intro();
gameState = GAME_STATE.START_GAME;
break;
// Start the game, set the number of players, names and round
case START_GAME:
this.numberOfPlayers = chooseNumberOfPlayers();
for(int i=0; i<this.numberOfPlayers; i++) {
String name = displayTextAndGetInput("NAME OF PLAYER #" + (i+1) + "? ");
Player player = new Player(name);
this.players.add(player);
}
this.round = 1;
gameState = GAME_STATE.PLAYING;
break;
// Playing round by round until we have a winner
case PLAYING:
System.out.println();
System.out.println("ROUND " + this.round);
System.out.println("=======");
// Each player takes their turn
for(int i=0; i<players.size(); i++) {
Player player = players.get(i);
int playerThrow = getPlayersThrow(player);
int points = calculatePlayerPoints(playerThrow);
player.addScore(points);
System.out.println("TOTAL SCORE = " + player.getScore());
}
boolean foundWinner = false;
// Check if any player won
for(int i=0; i<players.size(); i++) {
Player thePlayer = players.get(i);
int score = thePlayer.getScore();
if(score >=200) {
if(!foundWinner) {
System.out.println("WE HAVE A WINNER!!");
System.out.println();
foundWinner = true;
}
System.out.println(thePlayer.getName() + " SCORED "
+ thePlayer.getScore() + " POINTS");
}
}
if(foundWinner) {
System.out.println("THANKS FOR THE GAME.");
gameState = GAME_STATE.GAME_OVER;
} else {
// No winner found, continue on with the next round
this.round++;
}
break;
}
} while(gameState != GAME_STATE.GAME_OVER);
}
/**
* Display info about the game
*
*/
private void intro() {
System.out.println("BULLSEYE");
System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
System.out.println();
System.out.println("IN THIS GAME, UP TO 20 PLAYERS THROW DARTS AT A TARGET");
System.out.println("WITH 10, 20, 30, AND 40 POINT ZONES. THE OBJECTIVE IS");
System.out.println("TO GET 200 POINTS.");
System.out.println();
System.out.println(paddedString("THROW", "DESCRIPTION", "PROBABLE SCORE"));
System.out.println(paddedString("1", "FAST OVERARM","BULLSEYE OR COMPLETE MISS"));
System.out.println(paddedString("2", "CONTROLLED OVERARM", "10, 20 OR 30 POINTS"));
System.out.println(paddedString("3", "UNDERARM", "ANYTHING"));
}
/**
* Calculate the players score
* Score is based on the type of shot plus a random factor
*
* @param playerThrow 1,2, or 3 indicating the type of shot
* @return player score
*/
private int calculatePlayerPoints(int playerThrow) {
// -1 is because of 0 base Java array
double p1 = this.shots[playerThrow-1].getShot(0);
double p2 = this.shots[playerThrow-1].getShot(1);
double p3 = this.shots[playerThrow-1].getShot(2);
double p4 = this.shots[playerThrow-1].getShot(3);
double random = Math.random();
int points;
if(random >= p1) {
System.out.println("BULLSEYE!! 40 POINTS!");
points = 40;
// If the throw was 1 (bullseye or missed, then make it missed
// N.B. This is a fix for the basic code which for shot type 1
// allowed a bullseye but did not make the score zero if a bullseye
// was not made (which it should have done).
} else if (playerThrow == 1) {
System.out.println("MISSED THE TARGET! TOO BAD.");
points = 0;
} else if(random >= p2) {
System.out.println("30-POINT ZONE!");
points = 30;
} else if(random >= p3) {
System.out.println("20-POINT ZONE");
points = 20;
} else if(random >= p4) {
System.out.println("WHEW! 10 POINTS.");
points = 10;
} else {
System.out.println("MISSED THE TARGET! TOO BAD.");
points = 0;
}
return points;
}
/**
* Get players shot 1,2, or 3 - ask again if invalid input
*
* @param player
* @return 1,2, or 3 indicating the players shot
*/
private int getPlayersThrow(Player player) {
boolean inputCorrect = false;
String theThrow;
do {
theThrow = displayTextAndGetInput(player.getName() + "'S THROW ");
if(theThrow.equals("1") || theThrow.equals("2") || theThrow.equals("3")) {
inputCorrect = true;
} else {
System.out.println("INPUT 1, 2, OR 3!");
}
} while(!inputCorrect);
return Integer.valueOf(theThrow);
}
/**
* Get players guess from kb
*
* @return players guess as an int
*/
private int chooseNumberOfPlayers() {
return Integer.valueOf((displayTextAndGetInput("HOW MANY PLAYERS? ")));
}
/*
* Print a message on the screen, then accept input from Keyboard.
*
* @param text message to be displayed on screen.
* @return what was typed by the player.
*/
private String displayTextAndGetInput(String text) {
System.out.print(text);
return kbScanner.next();
}
/**
* Format three strings to a given number of spaces
* Replacing the original basic code which used tabs
*
* @param first String to print in pos 1
* @param second String to print in pos 2
* @param third String to print in pos 3
* @return formatted string
*/
private String paddedString(String first, String second, String third) {
String output = String.format("%1$" + FIRST_IDENT + "s", first);
output += String.format("%1$" + SECOND_IDENT + "s", second);
output += String.format("%1$" + THIRD_INDENT + "s", third);
return output;
}
}

View File

@@ -0,0 +1,8 @@
public class BullseyeGame {
public static void main(String[] args) {
Bullseye bullseye = new Bullseye();
bullseye.play();
}
}

View File

@@ -0,0 +1,26 @@
/**
* A Player in the game - consists of name and score
*
*/
public class Player {
private String name;
private int score;
Player(String name) {
this.name = name;
this.score = 0;
}
public void addScore(int score) {
this.score += score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
}

View File

@@ -0,0 +1,21 @@
/**
* This class records the percentage chance of a given type of shot
* scoring specific points
* see Bullseye class points calculation method where its used
*/
public class Shot {
double[] chances;
// Array of doubles are passed for a specific type of shot
Shot(double[] shots) {
chances = new double[shots.length];
for(int i=0; i<shots.length; i++) {
chances[i] = shots[i];
}
}
public double getShot(int index) {
return chances[index];
}
}

View File

@@ -0,0 +1,186 @@
import java.util.ArrayList;
import java.util.Scanner;
public class Hurkle {
public static final int GRID_SIZE = 10;
public static final int MAX_GUESSES = 5;
private enum GAME_STATE {
STARTING,
START_GAME,
GUESSING,
PLAY_AGAIN,
GAME_OVER
}
private GAME_STATE gameState;
// Used for keyboard input
private Scanner kbScanner;
private int guesses;
// hurkle position
private int hurkleXPos;
private int hurkleYPos;
// player guess
private int playerGuessXPos;
private int playerGuessYPos;
public Hurkle() {
gameState = GAME_STATE.STARTING;
// Initialise kb scanner
kbScanner = new Scanner(System.in);
}
/**
* Main game loop
*/
public void play() {
do {
switch (gameState) {
// Show an introduction the first time the game is played.
case STARTING:
intro();
gameState = GAME_STATE.START_GAME;
break;
// Start the game, set the number of players, names and round
case START_GAME:
this.hurkleXPos = randomNumber();
this.hurkleYPos = randomNumber();
System.out.println("HURKLE AT : " + this.hurkleXPos + "," + this.hurkleYPos);
this.guesses = 1;
gameState = GAME_STATE.GUESSING;
break;
// Guess an x,y position of the hurkle
case GUESSING:
String guess = displayTextAndGetInput("GUESS #" + this.guesses + "? ");
this.playerGuessXPos = getDelimitedValue(guess, 0);
this.playerGuessYPos = getDelimitedValue(guess, 1);
if (foundHurkle()) {
this.gameState = GAME_STATE.PLAY_AGAIN;
} else {
showDirectionOfHurkle();
this.guesses++;
if(this.guesses > MAX_GUESSES) {
System.out.println("SORRY, THAT'S "
+ MAX_GUESSES + " GUESSES.");
System.out.println("THE HURKLE IS AT "
+ this.hurkleXPos + "," + this.hurkleYPos);
System.out.println();
this.gameState = GAME_STATE.PLAY_AGAIN;
}
}
break;
case PLAY_AGAIN:
System.out.println("LET'S PLAY AGAIN, HURKLE IS HIDING.");
System.out.println();
this.gameState = GAME_STATE.START_GAME;
break;
}
// Effectively an endless loop because the game never quits as per
// the original basic code.
} while (gameState != GAME_STATE.GAME_OVER);
}
private void showDirectionOfHurkle() {
System.out.print("GO ");
if(this.playerGuessYPos == this.hurkleYPos) {
// don't print North or South because the player has chosen the
// same y grid pos as the hurkle
} else if (this.playerGuessYPos < this.hurkleYPos) {
System.out.print("NORTH");
} else if(this.playerGuessYPos > this.hurkleYPos) {
System.out.print("SOUTH");
}
if(this.playerGuessXPos == this.hurkleXPos) {
// don't print East or West because the player has chosen the
// same x grid pos as the hurkle
} else if(this.playerGuessXPos < this.hurkleXPos) {
System.out.print("EAST");
} else if(this.playerGuessXPos > this.hurkleXPos) {
System.out.print("WEST");
}
System.out.println();
return;
}
private boolean foundHurkle() {
if ((this.playerGuessXPos - this.hurkleXPos)
- (this.playerGuessYPos - this.hurkleYPos) == 0) {
System.out.println("YOU FOUND HIM IN " + this.guesses + " GUESSES.");
return true;
}
return false;
}
/**
* Display info about the game
*/
private void intro() {
System.out.println("HURKLE");
System.out.println("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
System.out.println();
System.out.println("A HURKLE IS HIDING ON A " + GRID_SIZE + " BY "
+ GRID_SIZE + " GRID. HOMEBASE");
System.out.println("ON THE GRID IS POINT 0,0 IN THE SOUTHWEST CORNER,");
System.out.println("AND ANY POINT ON THE GRID IS DESIGNATED BY A");
System.out.println("PAIR OF WHOLE NUMBERS SEPERATED BY A COMMA. THE FIRST");
System.out.println("NUMBER IS THE HORIZONTAL POSITION AND THE SECOND NUMBER");
System.out.println("IS THE VERTICAL POSITION. YOU MUST TRY TO");
System.out.println("GUESS THE HURKLE'S GRIDPOINT. YOU GET "
+ MAX_GUESSES + " TRIES.");
System.out.println("AFTER EACH TRY, I WILL TELL YOU THE APPROXIMATE");
System.out.println("DIRECTION TO GO TO LOOK FOR THE HURKLE.");
}
/**
* Generate random number
* Used to create one part of an x,y grid position
*
* @return random number
*/
private int randomNumber() {
return (int) (Math.random()
* (GRID_SIZE) + 1);
}
/*
* Print a message on the screen, then accept input from Keyboard.
*
* @param text message to be displayed on screen.
* @return what was typed by the player.
*/
private String displayTextAndGetInput(String text) {
System.out.print(text);
return kbScanner.next();
}
/**
* Accepts a string delimited by comma's and returns the pos'th delimited
* value (starting at count 0).
*
* @param text - text with values separated by comma's
* @param pos - which position to return a value for
* @return the int representation of the value
*/
private int getDelimitedValue(String text, int pos) {
String[] tokens = text.split(",");
return Integer.parseInt(tokens[pos]);
}
}

View File

@@ -0,0 +1,7 @@
public class HurkleGame {
public static void main(String[] args) {
Hurkle hurkle = new Hurkle();
hurkle.play();
}
}