Basically I have to write a program that plays the card game, 21.
This is the assignment. I've done most of it but my code has a few issues.
"
PART 1:
You are going to create a simple card game of 21. In this game, the single player has to try to come as close to a score of 21 without going over and beat the computer's score.
1. Set up a class called PlayingCard. Add a method that returns a string representing its rank and suit. For example, the card with rank 1 and suit 'S' is "Ace of Spades".
2. Set up a class called DeckOfPlayingCards which contains the following information:
INSTANCE VARIABLES
an array of 52 PlayingCard objects
index of the "top" card in the deck
METHODS
constructor - initializes each PlayingCard object to a unique card in a standard deck
shuffle - randomly permute the order of the cards in the array (see below for a hint) and sets the top card to the first card in the array
deal - returns the top card in the deck and sets the top card index to the next card
3. Set up a class TwentyOne with a main method that creates the deck of cards and then allows the user to play the game of 21.
SHUFFLING
In order to shuffle the cards, use similar to the following algorithm:
for i = 0 to 50
pick a random integer j between i and 51
swap card i with card j
end for
GENERAL GAME RULES
Each card has a point value based on its rank (the suit is ignored in this game). The cards with ranks 2 through 10 have point values of 2 through 10 respectively. The "face" cards (Jack, Queen, King) have a point value of 10 each. The Ace is considered as 11 points, unless that puts the player over a total of 21 points, in which case it reverts to 1 point instead. For example, the following cards are dealt to the player and the total scores are shown to their right:
CARD CARD SCORE TOTAL SCORE
5 of Diamonds 5 5
Ace of Hearts 11 16
7 of Clubs 7 13
3 of Clubs 3 16
Ace of Spades 1 17
4 of Hearts 4 21
In each game, the deck of cards is shuffled, and the user starts with the first two cards of the deck. The user may pick the next card of the deck by inputting "HIT" or the user may stop at this point by inputting "STAY". The user can pick as many cards as he or she wants in order to try to come up with a score as close to 21 without going over. If the user goes over 21 points, the user automatically loses and the computer wins. Otherwise, if the user stops with a total score less than or equal to 21, then the computer plays. The computer starts with the next two cards of the deck. The computer automatically "hits" until its score is at least 17. If the computer goes over 21 (but the user did not), then the user wins automatically. Otherwise, the winner is the player with the higher score. A tie (same total score) is won by the computer.
INPUT PROCESSING
Input will come from the keyboard in this game. The user should input "HIT" or "STAY" (lowercase ok) as the game proceeds. Any other input should flag an error "Unrecognized input", etc. and you should ask for the input again. At the end of the game, you should ask the user if he/she wants to play again. The input here will be "Y" or "N" (lowercase ok). All other input will lead to an error and you should ask the user to input again. See OUTPUT PROCESSING for an example of correct input.
OUTPUT PROCESSING
Here is a sample of the output of the program (user input in purple italics):
LET'S PLAY 21!
SHUFFLING CARDS...
YOUR TURN
5 of Diamonds 5
Ace of Hearts 16
HIT or STAY? HIT
7 of Clubs 13
HIT or STAY? hit
3 of Clubs 16
HIT or STAY? HIT
Ace of Spades 17
HIT or STAY? hit
4 of Hearts 21
HIT or STAY? STAY
COMPUTER'S TURN
King of Clubs 10
9 of Diamonds 19
YOUR SCORE: 21
COMPUTER'S SCORE: 19
YOU WIN!
PLAY AGAIN? (Y/N) Y
LET'S PLAY 21!
SHUFFLING CARDS...
YOUR TURN
8 of Hearts 8
Queen of Spades 18
HIT or STAY? stay
COMPUTER'S TURN
Jack of Hearts 10
3 of Clubs 13
7 of Spades 20
YOUR SCORE: 18
COMPUTER'S SCORE: 20
YOU LOSE!
PLAY AGAIN? (Y/N) Y
LET'S PLAY 21!
SHUFFLING CARDS...
YOUR TURN
Queen of Hearts 10
5 of Diamonds 15
HIT or STAY? HIT
7 of Hearts 22
YOU LOSE!
PLAY AGAIN? (Y/N) Y
LET'S PLAY 21!
SHUFFLING CARDS...
YOUR TURN
4 of Spades 4
10 of Clubs 14
HIT or STAY? HIT
6 of Hearts 20
HIT or STAY? STAY
COMPUTER'S TURN
5 of Hearts 5
Jack of Spades 15
Ace of Diamonds 16
4 of Clubs 20
YOUR SCORE: 20
COMPUTER'S SCORE: 20
YOU LOSE!
PLAY AGAIN? (Y/N) Y
LET'S PLAY 21!
SHUFFLING CARDS...
YOUR TURN
8 of Hearts 8
9 of Diamonds 17
HIT or STAY? STAY
COMPUTER'S TURN
King of Clubs 10
6 of Spades 16
Jack of Diamonds 26
YOU WIN!
PLAY AGAIN? (Y/N) N"
--- Update ---
Here is my code. It's divided into the classes that were stipulated in the assignment.
public class PlayingCard { // instance variables private static int rank; // rank of card private static char suit;// card's suit // default constructor // setter method for Rank public static void setRank(int i) { rank = i; } // getter method for Rank public static int getRank() { return rank; } // setter method for Suit public static void setSuit(char i ) { suit = i; } // getter method for suit public static char getSuit() { return suit; } // cardInfo method. It accepts parameters, 2 string arrays, rank, and suit to return string that indicates the card's name and suit public static String cardInfo(String [] rankstr, String[] suitstr, int rank, char suit) { // The logic behind this declaration is the following. This code will use the char input and discern int's nature in if statements and then assign corresponding index values so that I can use that index to access the right string in the array of characters int suitindex =0; // The suits are ordered from least to greatest value. S,H,D,C. That is the order if(suit=='S') suitindex =1; if(suit=='H') suitindex = 2; if(suit=='D') suitindex =3; if(suit=='C') suitindex=4; // String variable r is used to store the string at index rank. String r =rankstr[rank]; // String variable s is used to store the string at the suitindex obtained previously. String s = suitstr[suitindex]; // String info is essentially a concatenation of r and s along with "of". String info = r+" of " + s; return info; } public static void main(String [] args) { Scanner input = new Scanner(System.in); // String array of names that correspond with ranks String r[] = {null,"Ace", "King", " Queen " , "Jack", "Ten", "Nine", "Eight ", " Seven", "Six"," Five", "Four", "Three", " Dueces"}; // String array of suits corresponding to ranks String s[] = { null, "Spades", " Hearts", "Diamonds ", "Clubs"}; // Prompt user for input System.out.println("Enter card rank and suit"); int rank = input.nextInt(); String str = input.next(); // Method "charAt" is used to find the character at index zero because scanners don't work for characters. char suit = str.charAt(0); PlayingCard nm = new PlayingCard(); String m =nm.cardInfo(r, s, rank, suit); // PlayingCard object System.out.println(m); // Value returned by the invocation of the cardInfo method is stored in s1; // s1 is now being printed } }
import java.util.Arrays; public class DeckOfPlayingCards { private static PlayingCard cards[] = new PlayingCard[52]; private static int indexOftop =51; String rankstr[] = {"Ace", "King", " Queen " , "Jack", "Ten", "Nine", "Eight ", " Seven", "Six"," Five", "Four", "Three", " Dueces"}; String suitstr[] = { "Spades", " Hearts", "Diamonds ", "Clubs"}; public void setCards() { this.cards = cards; } public PlayingCard[] getCards() { return cards; } public void setIndexOftop() { this.indexOftop= indexOftop; } public int getIndexOftop() { return indexOftop; } public DeckOfPlayingCards() { for(int i =0; i<cards.length; i++) { int rank =cards[i].getRank(); char suit = cards[i].getSuit(); cards[i]=new PlayingCard(); cards[i].cardInfo(rankstr, suitstr, rank, suit); }} public void shuffle(){ int j; for(int i = 0 ; i<51; i++) { j = (int)Math.random()*51; PlayingCard temp = cards[i]; cards[i]=cards[j]; cards[j]=temp; temp = cards[0]; cards[0]=cards[indexOftop]; } } public PlayingCard deal() { for(int i=0; i<51; i++){ indexOftop=52; indexOftop -=i; } return cards[indexOftop]; } }
import java.util.Scanner; public class TwentyOne { public static void main(String [] args) { Scanner input = new Scanner(System.in); DeckOfPlayingCards deck = new DeckOfPlayingCards(); // String array of ranks String rankstr[] = { "Ace", "2", " 3 " , "4", "5", "6", "7 ", " 8", "9"," 10", "Jack", "Queen", " King"}; // String array of suits corresponding to ranks String suitstr[] = { "Spades", " Hearts", "Diamonds ", "Clubs"}; gamePlay(rankstr,suitstr,deck); System.out.println("DO YOU WANT TO PLAY AGAIN? Y OR N"); String answer = input.next(); while(answer.equals("Y")) { gamePlay(suitstr, suitstr, deck); if(answer.equals("N")) { System.out.println("THANK YOU FOR PLAYING"); break; }} } public static void gamePlay(String rankstr[],String suitstr[],DeckOfPlayingCards deck) { Scanner input = new Scanner(System.in); // Initialization of rank and index number of suit array. int rank = (int)Math.random(); int suitIndex = (int)Math.random(); // Represents the score of the user int total; // A secondary variable for user's score. Its use will become more apparent as you progress through the program int tot =0; // Represents computer's score int totcomputer =0; // suitIndex is used to get a string from the array and then charAt() is used to find the first character String str= suitstr[suitIndex]; char suit = str.charAt(0); // Game System.out.println("LET'S PLAY 21!"); System.out.println(); System.out.println(); System.out.println("SHUFFLING CARDS..."); System.out.println(); deck.shuffle(); System.out.println(); System.out.println("YOUR TURN"); // I'm adding 1 to rank b/c the first element in the array of ranks is the ranked number 1 and so on and so forth for the other elements total = rank+1; // Print first card System.out.println(deck.deal().cardInfo(rankstr, suitstr, rank, suit) +" " +"\t\t\t" + total); deck.shuffle(); rank = (int)((Math.random()*rankstr.length-1)); suitIndex = (int)((Math.random()*suitstr.length-1)); str= suitstr[suitIndex]; suit = str.charAt(0); total = rank+1; // Print second card System.out.println(deck.deal().cardInfo(rankstr, suitstr, rank, suit) +" " +"\t\t\t" + total); deck.shuffle(); System.out.println("HIT OR STAY"); String response = input.next(); // When user decides to hit, more cards will be played while(response.equals("HIT")||response.equals("hit")) { rank = (int)((Math.random()*rankstr.length-1)); suitIndex = (int)((Math.random()*suitstr.length-1)); str= suitstr[suitIndex]; suit = str.charAt(0); tot+=rank+1; if(rank==0) rank=10; if(tot>21&&rank==11) rank =0; System.out.println(deck.deal().cardInfo(rankstr, suitstr, rank, suit) + " " +"\t\t\t" + tot); deck.shuffle(); if(tot==21){ System.out.println("YOU WIN"); break;} if(tot>21){ System.out.println("YOU LOSE. THE COMPUTER WINS"); break; } System.out.println("HIT OR STAY"); response = input.next(); // When user is done if(response.equals("STAY")||response.equals("stay")) { System.out.println("COMPUTER'S TURN"); do { rank = (int)((Math.random()*rankstr.length-1)); suitIndex = (int)((Math.random()*suitstr.length-1)); str= suitstr[suitIndex]; suit = str.charAt(0); totcomputer+=rank+1; if(rank==1) rank=11; if(totcomputer>21&&rank==11) rank =1; deck.shuffle(); System.out.println(deck.deal().cardInfo(rankstr, suitstr, rank, suit) +" " +"\t\t\t" + totcomputer); if(totcomputer==21) { System.out.println("THE COMPUTER WINS"); break;} if(totcomputer>21&&tot<=21){ System.out.println(); System.out.println(); System.out.println("YOU WIN"); break; } } while(totcomputer<=17); System.out.println(); System.out.println(); System.out.println(); System.out.println("YOUR SCORE" + " " + tot + " "+ "COMPUTER'S SCORE" + " " + totcomputer); if(tot<21&&totcomputer<21&&tot>totcomputer){ System.out.println(); System.out.println("YOU WIN");} if(tot<21&&totcomputer<21&&tot<totcomputer){ System.out.println(); System.out.println("YOU LOSE. THE COMPUTER WINS");} if(tot==totcomputer&&tot<=21&&tot>=21) { System.out.println(); System.out.println("THE COMPUTER IS THE WINNER"); } if(tot==totcomputer&&tot<21&&totcomputer<21) { System.out.println(); System.out.println("THE COMPUTER IS THE WINNER"); } }} }}
--- Update ---
I keep getting indexoutofbounds exceptions and sometimes for my cardInfo method, 2 suits are printed instead of a rank and a suit. Can I please get some help? I'd really appreciate it. Thanks in advance!
--- Update ---
I keep getting indexoutofbounds exceptions and sometimes for my cardInfo method, 2 suits are printed instead of a rank and a suit. Can I please get some help? I'd really appreciate it. Thanks in advance!