1

Ive は最近 Java の学習を開始しましたが、ほとんどの場合、順調に進んでいます。私が学んでいることを理解するのを助けるために、私はカードゲームエンジンを書くことに決めました。私は、適切な抽象化とカプセル化の方法であると信じているものを使用して、カードとデッキのクラスを構築しました。しかし、ディーラー クラスの作成中に問題が発生しました。ディーラー クラス内からカード クラス データにアクセスする方法がわかりません。デッキ クラスからは、カード クラスに必要なすべてのアクセス権がありますが、ディーラー クラスに到達すると、2 つのクラスの深さでカプセル化されたデータにアクセスする方法がわかりません。

ここに私がこれまでに持っているものがありますが、問題を解決するためのコードは高く評価されていますが、誰かが私が経験していることをよりよく理解するのに役立つドキュメントまたは本の方向に私を向けることができれば、大歓迎です.

ただ明確にします。ディーラー クラスのインスタンス変数値など、デッキ配列内の個々のカードに関するデータにアクセスできるようにしたいと考えています。println ステートメントから a card を参照すると、cards to string メソッドが呼び出されることがわかっています。しかし、探しているのはカードの実際のデータです。

最後のクラスは、私が書いたメソッドをテストするために使用していたものです。

   import java.util.*;
   public class Card {

        public Card() {
            suit = 0;
            value = 0;
            setName(value);                             
        }

        public Card(int cSuit, int cValue) {
            suit = cSuit;
            value = cValue;
            setName(cValue);
        }

        public String getNewCard() {
                suit = rgen.nextInt(4)+1;
            value = rgen.nextInt(13)+1;
            setName(value);

            return name +" of " +getSuitAsString();             
        }

        public int getValue() {
            return value;
        }

        public int getSuit() {
            return suit;
        }

        public String getName() {
            setName(value);
            return name;
        }

        public String getName(int val) {
            setName(val);
            return name;
        }

        public String getSuitAsString() {

            switch(suit) {
            case 1: return "Diamonds";
            case 2: return "Hearts";
            case 3: return "Spades";
                        case 4: return "Clubs";
                      default: return null;
            }
        }

        public String getSuitAsString(int cSuit) {
            switch (cSuit) {
                case 1: return "Diamonds";
            case 2: return "Hearts";
            case 3: return "Spades";
                    case 4: return "Clubs";
                default:return null;
            }
        }

        public String toString() {
            return name +" of "+ getSuitAsString();
        }

        private void setName(int value) {
            switch (value) {
            case 0 : name = "null";
            break;
            case 1 : name =  "Ace";
            break;
            case 2 : name =  "Two";
            break;
            case 3 : name =  "Three";
            break;
            case 4 : name =  "Four";
            break;
            case 5 : name =  "Five";
            break;
            case 6 : name =  "Six";
            break;
            case 7 : name =  "Seven";
            break;
            case 8 : name =  "Eight";
            break;
            case 9 : name =  "Nine";
            break;
            case 10 : name = "Ten";
            break;
            case 11: name =  "Jack";
            break;
            case 12 : name = "Queen";
            break;
            case 13 : name = "King";
            break;
            }


        }

    private int suit;
    private String name;
    private int value;


    private Random rgen = new Random();
    }
    import java.util.Random;


    public class Deck {

    //Constructor assembles an initial deck of 52 cards in order by suit.
    //Array element [0] is never used.
        public Deck(){
            int cards = 1;
            int cardsPerSuit = 13;
            int suits = 4;
            while(cards < DECK_ARRAY_SIZE){
                for(int i = 1; i <= suits ; i++){
                    for(int j = 1; j <= cardsPerSuit; j++){
                    deck[cards++] = new Card(i , j);


                }
            }
        }   
    }

    //  Constructor creates and empty deck of 53 indexes set to null.
    //  Array element [0] is never used.
        public Deck(int deckArraySize){
            for(int i = 1; i < deckArraySize ; i++){
                deck[i] = new Card();
                }
        }

        public Deck(int suitCount , int cardsPerSuit , int deckArraySize){
    //  Constructor for special deck configuration.     
    }



        public void shuffle(){
            int SHUFFLE_COUNT = 100000;
            int arrayPos1 = 0;
            int arrayPos2 = 0;
            int count = 0;

            while(count < SHUFFLE_COUNT){
                Card card1 = deck[rgen.nextInt(DECK_ARRAY_SIZE)];
                if(card1 == deck[0]) card1 = deck[1];//This prevents the NullPointerException error.broke the always use braces rule.
                Card card2 = deck[rgen.nextInt(DECK_ARRAY_SIZE)];
                if(card2 == deck[0]) card2 = deck[52];//This prevents the NullPointerException error.broke the always use braces rule.



                for(int i = 1; i < DECK_ARRAY_SIZE; i++){
                    for (int j = 1; j < DECK_ARRAY_SIZE; j++){
                        if (deck[i].equals(card1)){
                            arrayPos1 = i;
                            if (deck[j].equals(card2)){
                            arrayPos2 = j;

                            }
                        }
                    }   
                    Card temp = deck[arrayPos1];
                    deck[arrayPos1] = deck[arrayPos2];
                    deck[arrayPos2] = temp;
                    count++;    

                }       

        }           

    }


    //  Gets the top card of the deck.
        public Card getTopCard(){
            Card topCard = deck[1];
            return topCard;

        }
    //  Gets a card at specified index. 
        public Card getCardAt(int cardAtPos){
            Card cardAt = deck[cardAtPos];  
            return  cardAt; 

        }


    //This method makes an implicit call to the Card classes toString method when string manipulation is performed .    
    //This is done by the compiler automatically.
        public void getDeckInfo(){
            for(int i = 1; i < DECK_ARRAY_SIZE ; i++){
            System.out.print(i +" ");
            System.out.println(deck[i]);
            }
        }


        public String toString(){
    //      getDeckInfo();
            return "Nothing to see here, move along.";

        }

    private Random rgen = new Random();
    public static final int DECK_ARRAY_SIZE = 53;
    private Card[] deck = new Card[DECK_ARRAY_SIZE];

    }
    public class Dealer {

    public Dealer(){
        playDeck = new Deck();
        discardStack = new Deck(Deck.DECK_ARRAY_SIZE);
    }

    public int getDeckCardCount(){
// this count should go down anytime a card is dealt to a player 
        return deckCardCount;
    }

    public int getDiscardCount(){
// this count should go up anytime a card is removed from the deck or from play.        
        return discardCount;
    }

    public void dealCards(){

// should be self explanatory.      
    }

    public void shuffle(){
// need to make sure that shuffle compensates for cards removed 
// from deck and move cards to the front of the array before the shuffle.
// make sure that the empty indexes at the end of the array are not included in the shuffle.
// also need a shuffle method for shuffles at the end of the game. or just 
// throw out he deck and get a new deck.... 
// maybe pass the remaining cards in the deck to the shuffle method .

    }

    public String toString(){

        return "Nothing to see here , move along.";
}
public Deck playDeck;   
public Deck discardStack;
private int deckCardCount;
private int discardCount;
    }

public class CardTest  {

public static void main(String[] args){


    Card singleCard = new Card();
    Deck deck = new Deck();
    Deck playDeck = new Deck();
    Deck discardStack = new Deck(53); 
    Dealer dealer = new Dealer();

System.out.println("value: "+singleCard.getValue());
System.out.println("Name: "+singleCard.getName());
System.out.println("Suit: "+singleCard.getSuitAsString());
System.out.println("Card to string: "+singleCard.toString());
System.out.println("New card: " +singleCard.getNewCard());
System.out.println("New card: " +singleCard.getNewCard());
System.out.println("New card: " +singleCard.getNewCard());
System.out.println("Pass a 4 to the getSuitAsString() method:    "+singleCard.getSuitAsString(4));
System.out.println("Pass a 12 to the getName() method: "+singleCard.getName(12));
deck.getDeckInfo();
System.out.println("Top card is: "+deck.getTopCard());

System.out.println("Shuffling...");
int count =0;
while(count < 500){
dealer.playDeck.shuffle();
discardStack.shuffle();
count++;
}

deck.getDeckInfo();
System.out.println("Top card is: "+deck.getTopCard());
System.out.println("Card at position ??: "+deck.getCardAt(5));
playDeck.getDeckInfo();
discardStack.getDeckInfo();
playDeck.shuffle();
playDeck.getDeckInfo();
discardStack.shuffle();
discardStack.getDeckInfo();
dealer.playDeck.getDeckInfo();
dealer.playDeck.shuffle();
System.out.println("Shuffling...");
dealer.playDeck.getDeckInfo();
System.out.println(dealer.playDeck.getCardAt(5));
System.out.println(dealer.discardStack.getCardAt(5));   


}

}

4

3 に答える 3

1

モデルは悪くありません。問題は Deck の 2 番目と 3 番目のコンストラクターにあります。

なぜ「特別な構築」が必要なのかを自問してみてください。もし必要なら..最初のデッキ コンストラクターによって作成された適切な 52 枚のカード デッキから始めて、そこから作業を開始できないのはなぜですか..つまり、使用していないカードを削除します。いらない。

最後に、オブジェクト指向の哲学では、インスタンスが構築後に無効な状態になってはならないことが規定されています。コンストラクター Card() を持つことは、最終的にどのカードになりたいかを知る必要があるため、単純に十分ではありません.. ハートの 6 Card.new(6, "hearts") は有効な ctor です

于 2013-01-31T04:32:42.733 に答える
0

いくつかの一般的な意見:

  • ある時点で、インデックス0から始まる配列について学習/処理を開始する必要があります。実行していること(「//配列要素[0]は使用されない」)のように、遅かれ早かれそれを実行することもできます。後で1つずつエラーが発生する可能性があります...

  • 本当に必要なコンストラクターのみを定義してください。空のコンストラクターは、適切なユースケースがある場合にのみ役立ちます。通常、構築後、オブジェクトインスタンスは有効な状態になります。これは、デフォルトを呼び出す場合には当てはまりません。newu Card()

  • 文字列定数を処理する方法はたくさんあります。あなたがそれをしている方法は最も簡単なものですが、最もエラーが発生しやすい方法でもあります。たとえば、"Diamonds"文字列のどこかでタイプミスをした場合、それを見つけるのに時間がかかることがあります。今のところ、定数、つまりいくつかのpublic static final DIAMOND = "Diamond"定義を使用することをお勧めします。そのように、ダイヤモンドの文字列が必要なときはいつでも、変数を使用するだけDIAMONDです。これには正しいものが含まれており、変更することはできません。(後で、列挙型について読み始めることもできます。)

あなたの質問に

誤解が起こっていると思います...

「printlnステートメントからカードを参照すると、カードから文字列へのメソッドが呼び出されることを知っています。しかし、探しているのはカードの実際のデータです。」

本当じゃない。カード変数が文字列のみを期待する場所にある場合(たとえば、+演算子を使用して2つの文字列を連結する場合)、メソッドにアクセスしtoString()ます。

Card card = // some card variable

// This will use card.toString()
system.out.println("Printing a card string " + dealer.playDeck.getCardAt(5));

// However, you can just print something like this:
system.out.println("Printing a card suit " + dealer.playDeck.getCardAt(5).getSuitAsString());

補遺
他の回答へのコメントでのあなたの質問について。

for(int i = 0; i < deck.getCards().length; i++){
    deck.getCards()[i] // this is the i-th card, do something with it
}
于 2013-01-31T07:22:11.520 に答える
0

私は何かを理解していないように感じますが、このメソッドをDeckクラスに入れるのと同じくらい簡単ではありません。

public Card[] getCards() {
    return deck;
}

Dealerこれで、電話をかけて、好きなことをすることができますaDeck.getCards()

たとえば、このコードをDealerクラスに入れると、正常にコンパイルされます。

public Dealer() {
    Deck deck = new Deck();
    for (Card card : deck.getCards()) {
        int suit = card.getSuit();
        int value = card.getValue();
    }
}
于 2013-01-31T04:29:06.440 に答える