Første forsøg på et Java Blackjack-spil

Jeg har lige afsluttet mit første multi-klasseprogram, Blackjack, og det fungerer! Det giver brugeren mulighed for at spille Blackjack mod en enkelt forhandler uden andre spillere ved bordet. Jeg spekulerede på, da det var mit første multiklasseprogram, om du kunne hjælpe mig med at optimere det og / eller give mig nogle råd. Jeg vil implementere forsikring og opdeling, så ethvert råd til at hjælpe med at forberede koden til i sidste ende at tilføje disse funktioner ville være virkelig nyttigt! Endelig er min hovedmetode ret lang – jeg spekulerede på, om dette er typisk for Java-programmer, og hvis ikke, hvordan jeg kan ordne det.

Kort

package Blackjack; class Card { /* * Creates a playing card. */ private int rank;//represents the rank of a card private int suit;//represents the suit of a card private int value;//represents the value of a card private static String[] ranks = {"Joker","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"}; private static String[] suits = {"Clubs","Diamonds","Hearts","Spades"}; /* * Created with an integer that represents a spot in the String array ranks and the String array suits. This represents * the rank and suit of an individual card. */ Card(int suit, int values) { this.rank=values; this.suit=suit; } /* * Returns the string version of a card. */ public String toString() { return ranks[rank]+" of "+suits[suit]; } /* * Returns the rank of a card. */ public int getRank() { return rank; } /* * Returns the suit of a card. */ public int getSuit() { return suit; } /* * Returns the value of a card. If a jack, queen, or king the value is ten. Aces are 11 for now. */ public int getValue() { if(rank>10) { value=10; } else if(rank==1) { value=11; } else { value=rank; } return value; } /* * Sets the value of a card. */ public void setValue(int set) { value = set; } 

Dæk

package Blackjack; import java.util.ArrayList; import java.util.Random; /* * Creates and shuffles a deck of 52 playing cards. */ class Deck { private ArrayList<Card> deck;//represents a deck of cards Deck() { deck = new ArrayList<Card>(); for(int i=0; i<4; i++) { for(int j=1; j<=13; j++) { deck.add(new Card(i,j)); } } } /* * Shuffles the deck by changing the indexes of 200 random pairs of cards in the deck. */ public void shuffle() { Random random = new Random(); Card temp; for(int i=0; i<200; i++) { int index1 = random.nextInt(deck.size()-1); int index2 = random.nextInt(deck.size()-1); temp = deck.get(index2); deck.set(index2, deck.get(index1)); deck.set(index1, temp); } } /* * Draws a card from the deck. */ public Card drawCard() { return deck.remove(0); } 

Forhandler

package Blackjack; import java.util.ArrayList; import java.util.Arrays; /* * Creates a dealer that the user plays against. */ class Dealer { ArrayList<Card> hand;//represents the dealer"s hand private int handvalue=0;//value of the dealer"s hand (starts at 0) private Card[] aHand;//used to convert the dealer"s hand to an array private int AceCounter;//counts the aces in the dealer"s hand Dealer(Deck deck) { hand = new ArrayList<>(); aHand = new Card[]{}; int AceCounter=0; for(int i=0; i<2; i++) { hand.add(deck.drawCard()); } aHand = hand.toArray(aHand); for(int i=0; i<aHand.length; i++) { handvalue += aHand[i].getValue(); if(aHand[i].getValue()==11) { AceCounter++; } while(AceCounter>0 && handvalue>21) { handvalue-=10; AceCounter--; } } } /* * Prints the dealer"s first card (the card face up at the beginning of a blackjack game). */ public void showFirstCard() { Card[] firstCard = new Card[]{}; firstCard = hand.toArray(firstCard); System.out.println("["+firstCard[0]+"]"); } /* * Gives the dealer another card and updates the value of his hand. Takes into account the value of aces. */ public void Hit(Deck deck) { hand.add(deck.drawCard()); aHand = hand.toArray(aHand); handvalue = 0; for(int i=0; i<aHand.length; i++) { handvalue += aHand[i].getValue(); if(aHand[i].getValue()==11) { AceCounter++; } while(AceCounter>0 && handvalue>21) { handvalue-=10; AceCounter--; } } } /* * Determines if the dealer wants to hit according to classic Blackjack rules. */ public boolean wantsToHit() { if(handvalue<17) { return true; } return false; } /* * Returns true if the dealer has blackjack. */ public boolean hasBlackJack() { if(hand.size()==2 && handvalue==21) { System.out.println("The dealer has blackjack!"); return true; } return false; } /* * Prints the dealer"s hand. */ public void showHand() { System.out.println(hand); } /* * Returns the value of the dealer"s hand. */ public int getHandValue() { return handvalue; } /* * Determines if a dealer has busted. */ public boolean busted(int handvalue) { if(handvalue>21) { System.out.println("The dealer busted!"); return true; } return false; } /* * Takes the turn for the dealer and returns the value of his hand. */ public int takeTurn(Deck deck) { while(wantsToHit()) { System.out.println("The dealer hits"); Hit(deck); if(busted(handvalue)) { break; } } if(handvalue<=21) { System.out.print("The dealer stands."); } return handvalue; } 

Hoved

package Blackjack; import java.util.*; public class Blackjack { private static int cash;//cash the user bets with private static int bet;//how much the user wants to bet private static int AceCounter;//how many aces are in the user"s hand private static ArrayList<Card> hand;//represents the user"s hand private static int handvalue;//the value of the user"s hand private static String name;//name of the user public static void main(String[] args){ System.out.println("Hi! What is your name?"); Scanner scan = new Scanner(System.in); name = scan.nextLine(); System.out.println("Hello, "+name+", lets play some BlackJack!"); System.out.println("How much cash do you want to start with?"); Scanner money = new Scanner(System.in); cash = money.nextInt(); System.out.println("You start with cash: "+cash); while(cash>0){ Deck deck = new Deck();//initialize deck, dealer, hands, and set the bet. deck.shuffle(); AceCounter=0; Dealer dealer = new Dealer(deck); List<Card> hand = new ArrayList<>(); hand.add(deck.drawCard()); hand.add(deck.drawCard()); System.out.println("How much would you like to bet?"); bet=Bet(cash); System.out.println("Cash:"+(cash-bet)); System.out.println("Money on the table:"+bet); System.out.println("Here is your hand: "); System.out.println(hand); int handvalue = calcHandValue(hand); System.out.println("The dealer is showing: "); dealer.showFirstCard(); if(hasBlackJack(handvalue) && dealer.hasBlackJack())//check if both the user and dealer have blackjack. { Push(); } else if(hasBlackJack(handvalue))//check if the user has blackjack. { System.out.println("You have BlackJack!"); System.out.println("You win 2x your money back!"); cash=cash+bet; Win(); } else if(dealer.hasBlackJack())//check if the dealer has blackjack. { System.out.println("Here is the dealer"s hand:"); dealer.showHand(); Lose(); } else { if(2*bet<cash)//check if the user can double down. { System.out.println("Would you like to double down?");//allows the user to double down. Scanner doubledown = new Scanner(System.in); String doubled = doubledown.nextLine(); while(!isyesorno(doubled)) { System.out.println("Please enter yes or no."); doubled = doubledown.nextLine(); } if(doubled.equals("yes")) { System.out.println("You have opted to double down!"); bet=2*bet; System.out.println("Cash:"+(cash-bet)); System.out.println("Money on the table:"+bet); } } System.out.println("Would you like to hit or stand?");//ask if the user will hit or stand Scanner hitorstand = new Scanner(System.in); String hitter = hitorstand.nextLine(); while(!isHitorStand(hitter)) { System.out.println("Please enter "hit" or "stand"."); hitter = hitorstand.nextLine(); } while(hitter.equals("hit"))//hits the user as many times as he or she pleases. { Hit(deck, hand); System.out.println("Your hand is now:"); System.out.println(hand); handvalue = calcHandValue(hand); if(checkBust(handvalue))//checks if the user busted { Lose(); break; } if(handvalue<=21 && hand.size()==5)//checks for a five card trick. { fivecardtrick(); break; } System.out.println("Would you like to hit or stand?"); hitter = hitorstand.nextLine(); } if(hitter.equals("stand"))//lets the user stand. { int dealerhand = dealer.takeTurn(deck);//takes the turn for the dealer. System.out.println(""); System.out.println("Here is the dealer"s hand:"); dealer.showHand(); if(dealerhand>21)//if the dealer busted, user wins. { Win(); } else { int you = 21-handvalue;//check who is closer to 21 and determine winner int deal = 21-dealerhand; if(you==deal) { Push(); } if(you<deal) { Win(); } if(deal<you) { Lose(); } } } } System.out.println("Would you like to play again?");//ask if the user wants to keep going Scanner yesorno = new Scanner(System.in); String answer = yesorno.nextLine(); while(!isyesorno(answer)) { System.out.println("Please answer yes or no."); answer = yesorno.nextLine(); } if(answer.equals("no")) { break; } } System.out.println("Your cash is: "+cash);//if user doesn"t want to play or runs out of cash, either congratulates them on their winnings or lets them know if(cash==0) { System.out.println("You ran out of cash!"); } else { System.out.println("Enjoy your winnings, "+name+"!"); } } /* * Checks if the user has blackjack. */ public static boolean hasBlackJack(int handValue) { if(handValue==21) { return true; } return false; } /* * Calculates the value of a player"s hand. */ public static int calcHandValue(List<Card> hand) { Card[] aHand = new Card[]{}; aHand = hand.toArray(aHand); int handvalue=0; for(int i=0; i<aHand.length; i++) { handvalue += aHand[i].getValue(); if(aHand[i].getValue()==11) { AceCounter++; } while(AceCounter>0 && handvalue>21) { handvalue-=10; AceCounter--; } } return handvalue; } /* * Asks the user how much he or she would like to bet. */ public static int Bet(int cash) { Scanner sc=new Scanner(System.in); int bet=sc.nextInt(); while(bet>cash) { System.out.println("You cannot bet more cash than you have!"); System.out.println("How much would you like to bet?"); bet=sc.nextInt(); } return bet; } /* * Called if the user wins. */ public static void Win() { System.out.println("Congratulations, you win!"); cash=cash+bet; System.out.println("Cash: "+cash); } /* * Called if the user loses. */ public static void Lose() { System.out.println("Sorry, you lose!"); cash=cash-bet; System.out.println("Cash: "+cash); } /* * Called if the user pushes */ public static void Push() { System.out.println("It"s a push!"); System.out.println("You get your money back."); System.out.println("Cash: "+cash); } /* * Adds a card to user"s hand and calculates the value of that hand. Aces are taken into account. */ public static void Hit(Deck deck, List<Card> hand) { hand.add(deck.drawCard()); Card[] aHand = new Card[]{}; aHand = hand.toArray(aHand); handvalue = 0; for(int i=0; i<aHand.length; i++) { handvalue += aHand[i].getValue(); if(aHand[i].getValue()==11) { AceCounter++; } while(AceCounter>0 && handvalue>21) { handvalue-=10; AceCounter--; } } } /* * Determines if a user has input hit or stand. */ public static boolean isHitorStand(String hitter) { if(hitter.equals("hit") || hitter.equals("stand")) { return true; } return false; } /* * Determines if a user has busted. */ public static boolean checkBust(int handvalue) { if(handvalue>21) { System.out.println("You have busted!"); return true; } return false; } /* * Determines if a user has input yes or no. */ public static boolean isyesorno(String answer) { if(answer.equals("yes") || answer.equals("no")) { return true; } return false; } /* * Called if the user has a five card trick. */ public static void fivecardtrick() { System.out.println("You have achieved a five card trick!"); Win(); } 

Kommentarer

Svar

Klassestruktur

  • En Hand -klasse kan være nyttig. Det kan beregne og gemme håndværdien. Dette ville også undgå den duplikering, du i øjeblikket har (calcHandValue og Hit).
  • Din Dealer -klassen indeholder en masse kode, som jeg ikke ville placere der. Den indeholder forhandlerens AI (hvornår rammer forhandleren?), Vinder / taber tilstandskontrol, udskrivning og optælling. Med en Hand klasse ville du allerede adskille noget af det. Jeg ville også fjerne alle udskrifterne (de gør det vanskeligt at genbruge kode og føre til dårlig kodestruktur) og adskille AI-logikken til sin egen klasse (dette ville gøre det lettere at ændre reglerne, fordi de alle er i én sted).
  • Din Blackjack klasse gør også alt for meget. Den udskriver, den læser input, den håndterer input, den kontrollerer vindende / tabende tilstand (igen, en duplikering, se næste punkt) osv. Det er både spilleren og spillet, der overtræder princippet om et enkelt ansvar.
  • Når du kopierer / indsætter kode, så prøv at tænke på et bedre alternativ. i dette tilfælde indeholder din Dealer og din Blackjack en masse dobbeltarbejde. Hovedsageligt fordi de begge repræsenterer en blackjack-spiller (dealeren og spiller). En generisk Player -klasse kan være nyttig, hvorfra Dealer og HumanPlayer udvides .

Så for at opsummere: Jeg vil mindst tilføje en Hand, Player og HumanPlayer klasse. Muligvis også en Input / Output interface og ConsoleInput / ConsoleOutput klasse (hvilket gør det let at tilføje en GUI). Der er flere klasser, du kan oprette, men det ville være en god start.

Diverse

  • hele din shuffle -funktion kan erstattes af Collections.shuffle(deck);.
  • Hvorfor gør din Dealer klasse har hand og aHand? Dette virker unødvendigt og forvirrende.
  • du har nogle stilproblemer (placering af krøllet parentes, indrykning, mellemrum osv.). Det virker for det meste internt konsistent (det er den vigtige del), men stemmer ikke rigtig overens med, hvad de fleste Java-programmører er vant til. De fleste IDEer, der understøtter Java (f.eks. Netbeans eller Eclipse), formaterer koden pr. Standard på en måde, som de fleste Java-programmører genkender .
  • navne på variabler og metoder skal starte med små bogstaver, så de ikke forveksles med klasser.
  • if (cond) return true else return false kan skrives som return cond.

Kommentarer

  • okay, jeg vil prøve nogle af disse ting. Mange tak . Jeg forstår ikke ‘ hvorfor jeg tilføjer et input / output interface og hvad jeg får det til at gøre. Har du noget imod at forklare lidt mere om dette punkt?
  • også, hvilken klasse vil du anbefale, at jeg kører spillet i?
  • @Jared Input ville bare samle handlingen (som kunne være en enum; hit, split osv.), og output ville output alt. Hovedårsagen er, at den adskiller disse ting fra resten es din kode mere læsbar og især mere genanvendelig. Du kan køre dit spil i en BlackJackGame -klasse, som skal opretholde spilsløjfen (som kalder andre klasser for at håndtere en hånd, få input, kontrollere sluttilstand og anvende resultater, hvorefter det handler om næste hånd). Resten skal ideelt set ske andre steder.
  • hvis det ikke er ‘ ikke for meget besvær, har du nogen eksempelkode eller nogen links til eksempelkode i et spil eller noget, du ville betragte som velstruktureret?
  • Meget pænt udført, velfortjent sejr! +1

Svar

Der er en hel del at forbedre på dette. Her er et par tip for at komme i gang.

Overdreven kommentarer

Tilføjer disse kommentarer noget nyt, der ikke allerede er klart?

private int rank;//represents the rank of a card private int suit;//represents the suit of a card private int value;//represents the value of a card 

De don t. Faktisk tilføjer de fleste andre kommentarer i koden heller ikke værdi. Den bedste kode behøver ikke kommentarer. Se igennem alle kommentarerne i din kode, hvis de ikke er nødvendige, skal du fjerne dem, hvis de er nødvendige, så prøv at ændre koden på en måde, så den ikke har brug for kommentarer.

Gør Card uforanderlig

Vil det give mening for rank, suit og value for at ændre i levetiden for en Card forekomst? Sandsynligvis ikke. Så lav disse felter final. Der er en setValue -metode, som du heller ikke har brug for.

Gennemgå også de andre klasser. Gør alt final, der ikke behøver at ændre sig, eller ikke giver mening at ændre sig nogensinde. Denne praksis kan hjælpe dig med at få øje på nogle designfejl.

Henvis til typer efter grænseflader

Du erklærer flere lister som denne:

ArrayList<Card> hand; 

Brug interface-typen i stedet:

List<Card> hand; 

Overvej enum s

Disse variabler er gode kandidater til enum s:

private static String[] ranks = {"Joker","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"}; private static String[] suits = {"Clubs","Diamonds","Hearts","Spades"}; 

Sådan:

enum Suit { Clubs, Diamonds, Hearts, Spades } 

Hvis du vil gentage de mulige dragter, kan du gøre for (Suit suit : Suit.values()) { ... }

Magiske tal

Der er for mange magiske tal i koden. 17, 10, 11, 4, … Det ville være bedre at sætte disse i public static final variabler med beskrivende navne for at afklare formålet med disse værdier, have dem sammen tæt på toppen af koden for lettere kontrol og fleksibilitet at lege med.

Formatering

Koden følger ikke den almindelige formatering, der er genereret af den automatiske formateringsmulighed for almindelige IDEer som Eclipse og IntelliJ Jeg foreslår at reformatere det hele for at få koden til at se mere velkendt og lettere at læse ud for de fleste Java-kodere. I Eclipse er tastaturgenvejen Control-Shift-f

Kommentarer

  • Hvis jeg bruger automatisk format, er det sådan, som programmer normalt formateres?
  • Ja, at ‘ er fælles måde
  • I ‘ d tilføj hele ” værdi ” attribut for Card er ikke nødvendigt, kun getValue () -funktionen er, som kun har brug for rang for at fungere.

Svar

Returner den boolske direkte

Følgende:

public static boolean isyesorno(String answer) { if(answer.equals("yes") || answer.equals("no")) { return true; } return false; } 

skal blive:

public static boolean isyesorno(String answer) { return answer.equals("yes") || answer.equals("no")) } 

Det samme gælder for public static boolean hasBlackJack(int handValue) og public static boolean isHitorStand(String hitter) og public static boolean checkBust(int handvalue) for sidstnævnte skal du flytte udskrivning ud af funktionen.

Brug allerede eksisterende hjul

Du kan blande dækket ved at bruge det indbyggede -in:

List<Cards> list = Arrays.asList(deck); Collections.shuffle(list); 

Kommentarer

  • vil blande denne måde blande min ArrayList-bunke eller give mig en ny liste kaldet liste, der blandes?
  • @Jared på plads ..

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *