Prima încercare la un joc Java Blackjack

Tocmai am finalizat primul meu program multi-clasă, Blackjack, și funcționează! Permite utilizatorului să joace Blackjack împotriva unui singur dealer, fără alți jucători la masă. Mă întrebam, văzând că este primul meu program multi-clasă, dacă mă puteți ajuta să-l optimizez și / sau să-mi dați vreun sfat. Vreau să implementez asigurări și împărțiri, astfel încât orice sfat care să ajute la pregătirea codului pentru adăugarea în cele din urmă a acestor caracteristici ar fi cu adevărat util! În cele din urmă, principala mea metodă este destul de lungă – mă întrebam dacă acest lucru este tipic pentru programele Java și, dacă nu, cum pot rezolva problema.

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; } 

Puntea

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); } 

Dealer

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; } 

Principal

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(); } 

Comentarii

Răspuns

Structura clasei

  • O clasă Hand ar putea fi utilă. Poate calcula și stoca valoarea mâinii. Acest lucru ar evita, de asemenea, duplicarea pe care o aveți în prezent (calcHandValue și Hit).
  • conține o mulțime de cod pe care nu l-aș plasa acolo. Conține AI-ul dealerului (când lovește dealerul?), Verificarea condiției de câștig / pierdere, tipărirea și numărarea. Cu o clasă Hand, ați separa deja o parte din aceasta. De asemenea, aș elimina toate tipăririle (îngreunează refolosirea codului și conduc la o structură defectuoasă a codului) și aș separa logica AI de propria sa clasă (acest lucru ar face mai ușoară schimbarea regulilor, deoarece toate sunt într-o singură locul).
  • Clasa dvs. Blackjack face, de asemenea, mult prea mult. Tipărește, citește intrarea, gestionează intrarea, verifică starea de câștig / pierdere (din nou, o dublare, vezi punctul următor) etc. Jucătorul, precum și jocul, încalcă principiul responsabilității unice.
  • Ori de câte ori copiați / lipiți codul, încercați să vă gândiți la o alternativă mai bună. în acest caz, Dealer și clasa Blackjack conțin o mulțime de duplicări. În principal, deoarece ambele reprezintă un jucător de blackjack (dealerul și player). O clasă generică Player ar putea fi utilă, din care se extind Dealer și HumanPlayer .

Deci, pentru a rezuma: aș adăuga cel puțin un Hand, Player și clasa HumanPlayer. Posibil, de asemenea, o interfață Input / Output și ConsoleInput / ConsoleOutput class (ceea ce ar facilita adăugarea unui GUI). Există mai multe clase pe care le-ați putea crea, dar acesta ar fi un început bun.

Diverse

  • Întreaga funcție shuffle poate fi înlocuită cu Collections.shuffle(deck);.
  • De ce Dealer clasa are hand și aHand? Acest lucru pare inutil și confuz.
  • aveți unele probleme legate de stil (poziția parantezei crețate, indentare, spații etc.). Pare în mare parte consecvent intern (aceasta este partea importantă), dar nu se potrivește cu ceea ce sunt obișnuiți majoritatea programatorilor Java. Majoritatea IDE-urilor care acceptă Java (de exemplu, Netbeans sau Eclipse) formează codul implicit într-un mod în care recunosc majoritatea programatorilor Java .
  • numele variabilelor și ale metodelor ar trebui să înceapă cu litere mici, deci nu sunt confundate cu clasele.
  • if (cond) return true else return false poate fi scris ca return cond.

Comentarii

  • bine voi încerca câteva dintre aceste lucruri. Mulțumesc foarte mult . Nu ‘ prea înțeleg de ce aș adăuga o interfață de intrare / ieșire și ce aș face să facă. >
  • De asemenea, în ce clasă mi-ați recomanda să rulez jocul?
  • @Jared Input ar strânge doar acțiunea (care ar putea fi o enumere; lovit, împărțit etc.), iar ieșirea ar ieși principalul motiv este că separă acele lucruri de restul codul dvs. este mai ușor de citit și mai ales mai reutilizabil. Puteți rula jocul într-o clasă BlackJackGame, care ar trebui să mențină bucla jocului (care ar apela alte clase pentru a acorda o mână, a obține intrare, a verifica starea finală și a aplica rezultatele, după care se ocupă de mâna următoare). Toate celelalte ar trebui să se întâmple în mod ideal în altă parte.
  • dacă nu este ‘ prea mare problemă, aveți vreun exemplu de cod sau vreun link către un exemplu de cod al unui joc sau ceva ce ați considera bine structurat?
  • Foarte frumos realizată, victorie bine meritată! +1

Răspuns

Există „multe lucruri de îmbunătățit în acest sens. Iată câteva sfaturi pentru a începe.

Comentarii excesive

Aceste comentarii adaugă ceva nou care nu este deja clar?

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 

Nu au. De fapt, nici majoritatea celorlalte comentarii din cod nu adaugă valoare. Cel mai bun cod nu are nevoie de comentarii. Căutați toate comentariile din codul dvs., dacă nu sunt necesare, apoi eliminați-le, dacă sunt necesare, apoi încercați să schimbați codul într-un mod pentru a nu avea nevoie de comentarii.

Făcând Card imuabil

Va avea sens pentru rank, suit și value pentru a schimba pe durata de viață a unei instanțe Card? Probabil că nu. Deci creați aceste câmpuri „2545677a99”>

. Există o metodăsetValue, de care nici nu aveți nevoie.

Examinați și celelalte clase. Faceți tot ceea ce final nu are nevoie să se schimbe sau nu are sens să se schimbe vreodată. Această practică vă poate ajuta să identificați unele erori de proiectare.

Consultați tipuri de interfețe

Declarați mai multe liste de genul acesta:

ArrayList<Card> hand; 

Folosiți tipul de interfață în schimb:

List<Card> hand; 

Luați în considerare enum s

Aceste variabile sunt candidați buni pentru 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"}; 

Astfel:

enum Suit { Clubs, Diamonds, Hearts, Spades } 

Dacă doriți să repetați posibilele costume, puteți face for (Suit suit : Suit.values()) { ... }

Numere magice

Există prea multe numere magice în cod. 17, 10, 11, 4, … Ar fi mai bine să le puneți în variabile public static final cu nume descriptive, pentru a clarifica scopul acestor valori, pentru a le avea împreună în partea de sus codului pentru un control mai ușor și flexibilitate cu care să te joci.

Formatare

Codul nu urmează formatarea comună generată de opțiunea de formatare automată a IDE-urilor obișnuite precum Eclipse și IntelliJ . Vă sugerez să reformatați întregul lucru, pentru a face codul să pară mai familiar și mai ușor de citit pentru majoritatea programatorilor Java. În Eclipse, comanda rapidă de la tastatură este Control-Shift-f

Comentarii

  • Dacă folosesc formatul automat, acesta este modul în care programele sunt de obicei formatate?
  • Da, ‘ este mod obișnuit
  • Am ‘ adăugat întreaga valoare ” ” al cardului nu este necesar, doar funcția getValue () este, care are nevoie doar de rang pentru a funcționa.

Răspuns

Returnează direct booleanul

Următoarele:

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

ar trebui să devină:

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

Același lucru este valabil și pentru public static boolean hasBlackJack(int handValue) și public static boolean isHitorStand(String hitter) și public static boolean checkBust(int handvalue) pentru acesta din urmă ar trebui să mutați tipărirea din funcție.

Utilizați roți deja existente

Puteți amesteca punte folosind -in:

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

Comentarii

  • va amesteca în acest fel amestecarea pachetului meu ArrayList sau îmi va da o nouă listă numită listă care este amestecată?
  • @Jared in place ..

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *