Created
November 23, 2011 21:10
-
-
Save NatashaTheRobot/1389923 to your computer and use it in GitHub Desktop.
This is the solution to Stanford CS106A Yahtzee Assignment 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* File: Yahtzee.java | |
* ------------------ | |
* This program will eventually play the Yahtzee game. | |
*/ | |
import acm.io.*; | |
import acm.program.*; | |
import acm.util.*; | |
import java.util.*; | |
public class Yahtzee extends GraphicsProgram implements YahtzeeConstants { | |
/* Private instance variables */ | |
private int nPlayers; //number of players | |
private String[] playerNames; //an array of Player names | |
private YahtzeeDisplay display; | |
private RandomGenerator rgen = new RandomGenerator(); //random number generator | |
private int[] dieResults = new int [N_DICE]; //stores the most recently rolled dice numbers | |
private int[][] categoryScores; //stores the score for each category for each player | |
private int category; //selected category | |
private int[][] selectedCategories; //stores the already selected categories | |
public static void main(String[] args) { | |
new Yahtzee().start(args); | |
} | |
public void run() { | |
IODialog dialog = getDialog(); | |
nPlayers = dialog.readInt("Enter number of players"); | |
while(true) { | |
if(nPlayers <= MAX_PLAYERS) break; | |
nPlayers = dialog.readInt("You can only enter up to " + MAX_PLAYERS +" number of players. Enter number of players"); | |
} | |
playerNames = new String[nPlayers]; | |
categoryScores = new int [nPlayers + 1][N_CATEGORIES+1]; | |
selectedCategories = new int[nPlayers+1][N_CATEGORIES+1]; | |
for (int i = 1; i <= nPlayers; i++) { | |
playerNames[i - 1] = dialog.readLine("Enter name for player " + i); | |
} | |
display = new YahtzeeDisplay(getGCanvas(), playerNames); | |
playGame(); | |
} | |
private void playGame() { | |
for(int i = 0; i < N_SCORING_CATEGORIES; i++) { | |
for(int j=1; j <= nPlayers; j++) { | |
initializeFirstRoll(j); | |
secondAndThirdRoll(j); | |
selectCategory(j); | |
} | |
} | |
calculateResults(); | |
calculateWinner(); | |
} | |
/* In the beginning of a players turn, | |
* the player clicks on "Roll Dice", | |
* the Dice results are displayed and | |
* stored in the diceResults array */ | |
private void initializeFirstRoll(int playerNumber) { | |
for(int i = 0; i < N_DICE; i++) { | |
int dieRoll = rgen.nextInt(1,6); | |
dieResults[i] = dieRoll; | |
} | |
display.printMessage(playerNames[playerNumber - 1] + "'s turn! Click the " + "\"Roll Dice\" " + "button to roll the dice."); | |
display.waitForPlayerToClickRoll(playerNumber); | |
display.displayDice(dieResults); | |
} | |
/* For the second and third roll, | |
* the player selects the dice he or she wants to re-roll, | |
* the selected dice are re-rolled, and the new | |
* dice values are displayed and stored in the diceResults array */ | |
private void secondAndThirdRoll(int playerNumber) { | |
for (int i = 0; i < 2; i++) { | |
display.printMessage("Select the dice you wish to re-roll and click " + "\"Roll Again\""); | |
display.waitForPlayerToSelectDice(); | |
for(int j = 0; j < N_DICE; j++) { | |
if(display.isDieSelected(j) == true) { | |
int dieRoll = rgen.nextInt(1,6); | |
dieResults[j] = dieRoll; | |
} | |
} | |
display.displayDice(dieResults); | |
} | |
} | |
/* Pre-condition: The player has rolled the dice three times. | |
* The player selects the category for the dice. | |
* The player cannot select a category that he/she already chose in a previous turn.*/ | |
private void selectCategory(int playerNumber) { | |
while(true) { | |
display.printMessage("Select a category for this roll"); | |
category = display.waitForPlayerToSelectCategory(); | |
if(selectedCategories[playerNumber][category] == 0) { | |
calculateCategoryScore(playerNumber); | |
break; | |
} | |
} | |
} | |
/* Pre-condition: The user selected a category he/she has not previously selected. | |
* Assigns 1 to the selectedCategories array to keep track of selected categories. | |
* Checks to see if the selected category matches the dice configuration, | |
* and calculates the score. If it does not match, assigns the score of 0. | |
* Post-condition: Shows the score category and total score in the scorecard. | |
*/ | |
private void calculateCategoryScore(int playerNumber) { | |
selectedCategories[playerNumber][category] = 1; | |
int totalScore; | |
if(checkCategory(dieResults, category) == true) { | |
setCategoryScore(playerNumber, category); | |
int score = categoryScores[playerNumber][category]; | |
display.updateScorecard(category, playerNumber, score); | |
calculateTotalScores(playerNumber); | |
totalScore = categoryScores[playerNumber][TOTAL]; | |
display.updateScorecard(TOTAL, playerNumber, totalScore); | |
} | |
else { | |
categoryScores[playerNumber][category] = 0; | |
display.updateScorecard(category, playerNumber, 0); | |
calculateTotalScores(playerNumber); | |
totalScore = categoryScores[playerNumber][TOTAL]; | |
display.updateScorecard(TOTAL, playerNumber, totalScore); | |
} | |
} | |
/*sets the score in the categoryScores matrix for each player | |
based on the scoring category they chose after rolling the dice*/ | |
private void setCategoryScore(int playerNumber, int category) { | |
int score = 0; | |
if(category >= ONES && category <= SIXES) { | |
for(int i = 0; i < N_DICE; i++) { | |
if(dieResults[i] == category) { | |
score += category; | |
} | |
} | |
} | |
else if(category == THREE_OF_A_KIND || category == FOUR_OF_A_KIND || category == CHANCE) { | |
for(int i = 0; i<N_DICE; i++) { | |
score += dieResults[i]; | |
} | |
} | |
else if(category == FULL_HOUSE) { | |
score = 25; | |
} | |
else if(category == SMALL_STRAIGHT) { | |
score = 30; | |
} | |
else if(category == LARGE_STRAIGHT) { | |
score = 40; | |
} | |
else if(category == YAHTZEE) { | |
score = 50; | |
} | |
categoryScores[playerNumber][category] = score; | |
} | |
/*sets the total scores for each player */ | |
private void calculateTotalScores(int playerNumber) { | |
int upperScore = 0; | |
int lowerScore = 0; | |
int totalScore = 0; | |
for(int i = ONES; i <= SIXES; i++) { | |
upperScore += categoryScores[playerNumber][i]; | |
} | |
for(int i = THREE_OF_A_KIND; i <= CHANCE; i++) { | |
lowerScore += categoryScores[playerNumber][i]; | |
} | |
totalScore = upperScore + lowerScore; | |
categoryScores[playerNumber][UPPER_SCORE] = upperScore; | |
categoryScores[playerNumber][LOWER_SCORE] = lowerScore; | |
categoryScores[playerNumber][TOTAL] = totalScore; | |
} | |
/* Pre-condition: All players have completed the game. | |
* Calculates and displays the Upper Score, Upper Bonus, and LowerScore */ | |
private void calculateResults() { | |
for(int i = 1; i <= nPlayers; i++) { | |
display.updateScorecard(UPPER_SCORE, i, categoryScores[i][UPPER_SCORE]); | |
display.updateScorecard(LOWER_SCORE, i, categoryScores[i][LOWER_SCORE]); | |
if(categoryScores[i][UPPER_SCORE] >= 63) { | |
categoryScores[i][UPPER_BONUS] = 35; | |
} | |
display.updateScorecard(UPPER_BONUS, i, categoryScores[i][UPPER_BONUS]); | |
categoryScores[i][TOTAL] = categoryScores[i][TOTAL] + categoryScores[i][UPPER_BONUS]; | |
display.updateScorecard(TOTAL, i, categoryScores[i][TOTAL]); | |
} | |
} | |
/* Pre-condition: The game has ended, and all the final scores have been added up. | |
* Calculates which player has the highest score and what the highest score is | |
* and prints that information in a message at the very end of the game.*/ | |
private void calculateWinner() { | |
int winningScore = 0; | |
int winningPlayerNumber = 0; | |
for(int i = 1; i<=nPlayers; i++) { | |
int x = categoryScores[i][TOTAL]; | |
if( x > winningScore) { | |
winningScore = x; | |
winningPlayerNumber = i - 1; | |
} | |
} | |
display.printMessage("Congratulations, " + playerNames[winningPlayerNumber] + ", you're the winner with a total score of " + winningScore + "!"); | |
} | |
/* Pre-condition: The player has finished rolling the dice and selects a category. | |
* This method returns true if the selected category matches | |
* to the actual category correctly, and false if it does not match. */ | |
private boolean checkCategory(int[] dice, int category) { | |
boolean categoryMatch = false; | |
if(category >= ONES && category <= SIXES || category == CHANCE) { | |
categoryMatch = true; | |
} | |
else { | |
//creates an array for each possible dice value (1-6) | |
ArrayList <Integer> ones = new ArrayList<Integer>(); | |
ArrayList <Integer> twos = new ArrayList<Integer>(); | |
ArrayList <Integer> threes = new ArrayList<Integer>(); | |
ArrayList <Integer> fours = new ArrayList<Integer>(); | |
ArrayList <Integer> fives = new ArrayList<Integer>(); | |
ArrayList <Integer> sixes = new ArrayList<Integer>(); | |
/*goes through each rolled die and puts 1 as a place-holder into the appropriate ArrayList | |
* e.g. if the first die value is 1, then 1 is added to the ones ArrayList or | |
* if the second die value is 5, then 1 is added to the fives ArrayList*/ | |
for(int i = 0; i < N_DICE; i++) { | |
if(dice[i] == 1) { | |
ones.add(1); | |
} | |
else if(dice[i] == 2) { | |
twos.add(1); | |
} | |
else if(dice[i] == 3) { | |
threes.add(1); | |
} | |
else if(dice[i] == 4) { | |
fours.add(1); | |
} | |
else if(dice[i] == 5) { | |
fives.add(1); | |
} | |
else if(dice[i] == 6) { | |
sixes.add(1); | |
} | |
} | |
if(category == THREE_OF_A_KIND) { | |
if(ones.size() >= 3 || twos.size() >= 3 || threes.size() >= 3 || fours.size() >= 3 || fives.size() >= 3 || sixes.size() >= 3) { | |
categoryMatch = true; | |
} | |
} | |
else if(category == FOUR_OF_A_KIND) { | |
if(ones.size() >= 4 || twos.size() >= 4 || threes.size() >= 4 || fours.size() >= 4 || fives.size() >= 4 || sixes.size() >= 4) { | |
categoryMatch = true; | |
} | |
} | |
else if(category == YAHTZEE) { | |
if(ones.size() == 5 || twos.size() == 5 || threes.size() == 5 || fours.size() == 5 || fives.size() == 5 || sixes.size() == 5) { | |
categoryMatch = true; | |
} | |
} | |
else if(category == FULL_HOUSE) { | |
if(ones.size() == 3 || twos.size() == 3 || threes.size() == 3 || fours.size() == 3 || fives.size() == 3 || sixes.size() == 3) { | |
if(ones.size() == 2 || twos.size() == 2 || threes.size() == 2 || fours.size() == 2 || fives.size() == 2 || sixes.size() == 2) { | |
categoryMatch = true; | |
} | |
} | |
} | |
else if(category == LARGE_STRAIGHT) { | |
if(ones.size() == 1 && twos.size() == 1 && threes.size() == 1 && fours.size() == 1 && fives.size() == 1){ | |
categoryMatch = true; | |
} | |
else if(twos.size() == 1 && threes.size() == 1 && fours.size() == 1 && fives.size() == 1 && sixes.size() == 1) { | |
categoryMatch = true; | |
} | |
} | |
else if(category == SMALL_STRAIGHT) { | |
if(ones.size() >= 1 && twos.size() >= 1 && threes.size() >= 1 && fours.size() >= 1) { | |
categoryMatch = true; | |
} | |
else if(twos.size() >= 1 && threes.size() >= 1 && fours.size() >= 1 && fives.size() >= 1) { | |
categoryMatch = true; | |
} | |
else if(threes.size() >= 1 && fours.size() >= 1 && fives.size() >= 1 && sixes.size() >= 1) { | |
categoryMatch = true; | |
} | |
} | |
} | |
return categoryMatch; | |
} | |
} |
srobert1953 - in yahtzee, for 3 of a kind the score you get is from all of the dice... As well as the value of 4 of a kind...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, with testing your code, I am getting wrong score. If you roll after 3 attempts three 3's for example, and you want to assign it to Three of a kind, your score is 11. It should be 9. Also, if you get four 6's and click on Four of a kind, your score is 25, should be 24.
Looking at the code, you should change the setCategoryScore method, as it counts all dices numbers for Three of a kind and four of a kind. You consider these two as Chance kategory, which counts all dices numbers. Instead, they should count only the dices which have the three/four numbers on it. (Example: if you roll 2, 1, 5, 5, 5 - You should count only the 3 5's for Three of a kind kategory with result of 15, not 18).