Javaブラックジャックゲームの最初の試み

最初のマルチクラスプログラムであるブラックジャックを完了したところ、動作しました。これにより、ユーザーはテーブルに他のプレーヤーがいなくても、単一のディーラーに対してブラックジャックをプレイできます。それが私の最初のマルチクラスプログラムであると見て、私がそれを最適化するのを手伝ってくれたり、アドバイスをくれたりしてくれないかと思っていました。保険と分割を実装したいので、最終的にこれらの機能を追加するためのコードを準備するのに役立つアドバイスは本当に役に立ちます!最後に、私の主な方法はかなり長いです—これがJavaプログラムの典型的なものかどうか、そうでない場合はどうすれば修正できるのか疑問に思いました。

カード

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

デッキ

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

ディーラー

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

メイン

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

コメント

回答

クラス構造

  • Handクラスが役立つ場合があります。手の値を計算して保存できます。これにより、現在の重複(calcHandValueHit)も回避できます。
  • Dealerクラスには、そこに配置しないコードがたくさん含まれています。ディーラーAI(ディーラーはいつヒットしますか?)、勝ち負けの状態チェック、印刷、カウントが含まれています。 Handクラスを使用すると、すでにその一部を分離していることになります。また、すべての印刷物を削除し(コードの再利用が困難になり、コード構造が悪くなります)、AIロジックを独自のクラスに分離します(これにより、すべてが1つになっているため、ルールの変更が容易になります)
  • Blackjackクラスもやりすぎです。印刷、入力の読み取り、入力の処理、勝ち負けの状態のチェックを行います(ここでも、重複、次のポイントを参照)など。単一の責任の原則に違反するのはプレーヤーであると同時にゲームでもあります。
  • コードをコピーして貼り付けるときは常に、より良い代替案を考えてください。この場合、DealerクラスとBlackjackクラスには多くの重複が含まれています。主な理由は、どちらもブラックジャックプレーヤー(ディーラーとプレーヤー)。一般的なPlayerクラスが役立つ場合があり、そこからDealerHumanPlayerが拡張されます。 。

要約すると、少なくとも

PlayerおよびHumanPlayerクラス。おそらく、Input / OutputインターフェイスとConsoleInput / ConsoleOutputクラス(GUIの追加が簡単になります)。作成できるクラスは他にもありますが、これは良いスタートです。

その他

  • shuffle関数全体をCollections.shuffle(deck);に置き換えることができます。
  • なぜDealerクラスにはhandaHandがありますか?これは不必要で紛らわしいようです。
  • スタイルの問題がいくつかあります(中括弧の位置、インデント、スペースなど)。ほとんど内部的に一貫しているように見えますが(これは重要な部分です)、ほとんどのJavaプログラマーが慣れているものと実際には一致しません。JavaをサポートするほとんどのIDE(NetbeansやEclipseなど)は、ほとんどのJavaプログラマーが認識する方法でデフォルトごとにコードをフォーマットします。 。
  • 変数名とメソッド名は小文字で始める必要があるため、クラスと混同しないでください。
  • if (cond) return true else return false

コメント

  • わかりました。これらのいくつかを試してみます。ありがとうございます。 。’入力/出力インターフェイスを追加する理由とその機能をよく理解していません。その点についてもう少し説明してもよろしいですか?
  • また、どのクラスでゲームを実行することをお勧めしますか?
  • @Jared Inputはアクション(列挙、ヒット、分割など)を収集するだけで、出力は出力されます主な理由は、それらを他のものから分離することです。コードをより読みやすく、特に再利用しやすくします。 BlackJackGameクラスでゲームを実行できます。このクラスは、ゲームループを維持する必要があります(他のクラスを呼び出して、ハンドを処理し、入力を取得し、終了条件を確認して、結果を適用します。その後、次のハンドを扱います)。残りはすべて、理想的には他の場所で発生するはずです。
  • ‘それほど問題がない場合は、ゲームのサンプルコードやサンプルコードへのリンク、または適切に構成されていると思われるものはありますか?
  • 非常にうまくできており、当然の勝利です。 +1

回答

これを改善するためのヒントはたくさんあります。ここにいくつかのヒントがあります。開始するには。

過度のコメント

これらのコメントは、まだ明確になっていない新しい何かを追加しますか?

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 

そうではありません。実際、コード内の他のコメントのほとんどは、付加価値もありません。最良のコードにはコメントは必要ありません。コード内のすべてのコメントが不要な場合はそれを確認し、必要な場合は削除してから、コメントが不要な方法でコードを変更してみてください。

Cardを不変にする

rank、とvalueは、Cardインスタンスの存続期間中に変更しますか?おそらくそうではありません。したがって、これらのフィールドをfinalsetValueメソッドがあります。どちらも必要ありません。

他のクラスも確認してください。変更する必要がない、または変更しても意味がないすべてのfinalを作成します。この方法は、いくつかの設計上のバグを見つけるのに役立ちます。

インターフェースで型を参照

次のようにいくつかのリストを宣言します:

ArrayList<Card> hand; 

代わりにインターフェイスタイプを使用します:

List<Card> hand; 

enum s

を検討してください

これらの変数は、enumの適切な候補です。

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

このように:

enum Suit { Clubs, Diamonds, Hearts, Spades } 

可能な訴訟を繰り返したい場合は、for (Suit suit : Suit.values()) { ... }

マジックナンバー

コードにマジックナンバーが多すぎます。 17、10、11、4、…これらの値の目的を明確にするために、これらを説明的な名前のpublic static final変数に入れて、上部近くにまとめた方がよいでしょう。

フォーマット

コードは、EclipseやIntelliJなどの一般的なIDEの自動フォーマットオプションによって生成される一般的なフォーマットに準拠していません。 。大多数のJavaコーダーがコードをより見やすく、読みやすくするために、全体を再フォーマットすることをお勧めします。Eclipseでは、キーボードのショートカットはControl-Shift-f

コメント

です。

  • 自動フォーマットを使用する場合、これはプログラムの通常のフォーマット方法ですか?
  • はい、’です。一般的な方法
  • ‘ d全体を追加します” value “属性は必要ありません。getValue()関数のみが必要です。これは、ランクが機能するためにのみ必要です。

回答

ブール値を直接返す

次のようになります:

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

次のようになります:

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

同じことがpublic static boolean hasBlackJack(int handValue)public static boolean isHitorStand(String hitter)public static boolean checkBust(int handvalue)後者の場合は、関数から印刷を移動する必要があります。

既存のホイールを使用する

内蔵のホイールを使用してデッキをシャッフルできます-in:

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

コメント

  • この方法でシャッフルすると、ArrayListデッキがシャッフルされるか、シャッフルされたリストと呼ばれる新しいリスト?
  • @Jared in place ..

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です