質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.20%

Java ブラックジャックの作成過程で発生したエラーの解決方法

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,529

kixx

score 14

前提・実現したいこと

Javaで下記の問題でブラックジャックを作成しています。どうしてもエラーの解決方法が分からず、詰まってしまいました。何度も質問を投稿してしまい申し訳ありませんが、ご教授いただけたら幸いでございます。

【問題】
トランプゲームのBlackJackを作成します。
今回作成するBlackJackは、以下の条件を満たしていればOKです。
・トランプのマークは意識しなくても良いです。1-13×4の52枚。
・チップの概念は不要です。
・1は1と11で計算可能ですが、1に固定してもOKです。
・全自動でOKです。Hitの判断を手動でさせる必要はありません。
・全てのメソッドにアクセス修飾子publicをつけてください。
・全てのフィールドにアクセス修飾子protectedをつけてください。

■ Humanという抽象クラスを作成し、以下を実装してください。
openというabstractな公開メソッドを用意してください。
setCardというArrayListを引数とした、abstractな公開メソッドを用意してください。
checkSumというabstractな公開メソッドを用意してください。
myCardsというArrayListの変数を用意してください。
■ Humanを継承したDealerクラスを実装してください。
cardsというArrayListの変数を用意し、初期処理でこのcardsに全てのトランプを持たせてください。また、処理の最後にcardsの要素をシャッフルしてください
dealという公開メソッドを用意し、cardsから2枚のカードを取得し、ArrayList型の戻り値にしてください。
hitという公開メソッドを用意し、cardsから1枚のカードを取得し、ArrayList型の戻り値にしてください。
■ Humanを継承したUserクラスを実装してください。
■ DealerとUser両方に抽象メソッドを実装してください。
setCardは、引数から受けたカード情報をmyCardsに追加するように実装してください。
checkSumは、myCardsを確認し、まだカードが必要ならtrue、必要無ければfalseを戻り値にするように実装してください。
openは、myCardsのカードの合計値を戻り値とするように実装してください。
■ BlackJackクラスにてDealerとUserクラスを使ってゲームが実行できるように処理を実装してください。
カードのやり取りは自動で構いません、カードの変化と最終結果を表示してください。

発生している問題・エラーメッセージ

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at blackjack.Dealer.hit(Dealer.java:31)
    at blackjack.BlackJack.main(BlackJack.java:22)

該当のソースコード

package blackjack;
import java.util.ArrayList;

public class BlackJack {
    public static void main(String[] args) {
        Dealer dealer = new Dealer() ;
        User user = new User();

        user.open();


        System.out.println("カードを配ります");

        ArrayList<Integer>deal = new ArrayList<Integer>();
        dealer.deal();
        System.out.println(dealer.deal());

        ArrayList<Integer>hit = new ArrayList<Integer>();
        dealer.hit();

        while(user.checkSum() == true) {
            dealer.hit();
        }

        while(dealer.checkSum() == true) {
            dealer.hit();
        }

        if(user.open() == 21) {
            System.out.println("ブラックジャック!あなたの勝ち");
        }else if(user.open() <= 21 && dealer.open() > user.open()){
            System.out.println("あなたの勝ち");
        }else if(user.open() > 21){
            System.out.println("バースト!あなたの負け");
        }else if(user.open() < dealer.open()){
            System.out.println("あなたの負け");
        }else if(user.open() == dealer.open()){
            System.out.println("引き分け");
        }
    }
}
package blackjack;
import java.util.ArrayList;

public abstract class Human {
    //手札の合計値を計算して戻す
    abstract public int open();

    //引いたカードを手元に追加する
    abstract public void setCards();

    //手札の合計値によってまだ引くべきかを決定する
    abstract public boolean checkSum();

    //UserとDealerの持つ手札の情報
    ArrayList<Integer> myCards = new ArrayList<Integer>();

}
package blackjack;
import java.util.ArrayList;
import java.util.Collections;

public class Dealer extends Human {
    public Dealer() { allCards(); }
    //全てのトランプを持たせてシャッフルする
    ArrayList <Integer> cards = new ArrayList<Integer>();
    public void allCards() {
        for(int n=1;n<=3;n++) {
            for(int i=1;i<=13;i++) {
                cards.add(i);
            }
        }
        Collections.shuffle(cards);
    }

    protected ArrayList<Integer> deal(){  //ディーラーがカードを配る
        ArrayList<Integer> deal = new ArrayList<Integer>();
        //山札cardsから2枚取って配列dealの0,1を入れる
        deal.add(cards.get(0));
        deal.add(cards.get(1));
        cards.remove(0);
        cards.remove(1);
        return deal;
    }

    protected ArrayList<Integer> hit(){
        ArrayList<Integer> hit = new ArrayList<Integer>();
        //山札から1枚取って配列hitの0に入れる
        hit.add(cards.get(0));
        cards.remove(0);
        return hit;
    }

    public void setCards() {
        ArrayList<Integer> set = new ArrayList<Integer>();;
        myCards.add(cards.get(0));
        myCards.add(cards.get(1));
        myCards = set;
    }

    public boolean checkSum() {
        if (open() <= 15) {
            return true;
        }else{
            return false;
        }
    }

    public int open() {
        int total_cards = 0;
            for(int i=1;i<=myCards.size();i++) {
                if(10 <= myCards.get(i)) {
                    myCards.set(i, 10);
                }
                total_cards += myCards.get(i);
            }
    return total_cards;
    }
}
package blackjack;

public class User extends Human {
    public void setCards() {

    }

    public int open() {
        int total_cards = 0;
        for(int i=1;i<=myCards.size();i++) {
            if(10 <= myCards.get(i)) {
                myCards.set(i, 10);
            }
            total_cards += myCards.get(i);
        }
        return total_cards;
    }

    public boolean checkSum() {
        if (open() <= 15) {
            return true;
        }else{
            return false;
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • jimbe

    2020/01/09 03:37

    コード枠の ``` の後の文字列は, ファイル名ではなく言語名(java)をお書きください.
    ファイル名は枠の外に書くか, 中にコメントとしてお書きください.

    キャンセル

回答 3

checkベストアンサー

0

IndexOutOfBoundsException
というのは、配列の範囲外へのアクセスなので、
ArrayListが要素0の状態でArrayList.get(0)を行っているのが直接的な原因になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/08 23:45

    いつもご回答いただきありがとうございます。
    最初に山札cardsから2枚取る・hitで山札cardsから1枚取る を
    行なっていますが、この山札cardsの中身が空ということなのでしょうか?

    キャンセル

  • 2020/01/09 08:33

    はい、山札の中身が空になっているのが原因だと思います。
    protected ArrayList<Integer> hit(){
     system.out.writeline("残り:" + cards.size());
    というのを加えると、動きがわかるかもしれません。

    キャンセル

0

恐らく何かの課題と思いますが失礼な丸投げ頻出する中頑張ってて和みました。

エラー自体については他の方の回答の通りですが、その背景+αとして以下のバグが見受けられます。

・BlackJack.javaのdealとhitがおかしい
返り値について勉強してみて下さい。配られたカードが返り値になるんだろうと思いますので、それをsetCardsでUserに渡してやる必要があります。
今のままではUserがカードを受け取らないので永遠にcheckSumがtruefalseにならずDealerがカードを配り尽くしてエラーが発生します。
・カードの枚数が39枚になっている
for(int n=1;n<=3;n++) の終了条件を見直して下さい。

他にも何かあるかもですがとりあえずこんなところで。

【修正部について】
こういうミスするからboolを返すメンバの命名のcheckって嫌いなんですよね…
trueだとどうなのか分かる名前の方が良いですね…

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/08 23:53

    お忙しい中ご丁寧に本当にありがとうございます。
    ・カードの枚数について全く気付いてませんでした。ありがとうございます。
    ・配られたカードをUserに渡す方法を考えているのですが。。。

    User.javaにて

    Dealer dealer = new Dealer();

    public ArrayList<Integer> setCards() {
    dealer.allCards();
    ArrayList<Integer> deal = new ArrayList<Integer>();
    dealer.deal();
    myCards.add(deal.get(0));
    myCards.add(deal.get(1));
    return myCards;
    }

    と、行なってみたのですがどうも上手くいきません、渡し方が違うのでしょうか?どうしても分かりません。勉強不足でしょうか。。

    キャンセル

  • 2020/01/09 00:37

    変数のスコープ、返り値、引数が分からない、メソッドと変数の区別が付かない、と言ったところでしょうか(かなりきついですね...

    はっきり言ってしまいますがそのsetCardsでは滅茶苦茶です。
    setCardsの目的を見直して下さい。単純にカードを受け取ってmyCardsに追加すると言われていたはずです。
    「Dealerがカードを配る」という話はありません。
    ここについてはメソッドに外からデータを受け渡すための方法である引数について理解することが解決に繋がります。
    cards.gets(0)の0とかがそうですね。


    あと
    ArrayList<Integer> deal = new ArrayList<Integer>();
    これはdealという名前の空のArrayListを作っているだけで
    dealer.deal()のdealとは名前が同じになっているだけでなんにも関係がありません。変数の方のdealはずっと空です。

    dealer.deal()の結果が欲しいのであれば、以下のように返り値を受け取る必要があります。

    ArrayList<Integer> deal = dealer.deal();
    別に変数名はメソッド名と一致させる必要はありませんし、むしろメソッド名に関係なく分かりやすい名前を付けるのが普通です。

    まずは引数と返り値を調べて見て下さい。

    キャンセル

  • 2020/01/09 04:22 編集

    > 配られたカードをUserに渡す方法を考えているのですが
    もなにも,
    > setCardというArrayListを引数とした、abstractな公開メソッドを用意してください。
    が, メソッド名から合っていませんね.

    キャンセル

0

Geekjobの課題はだしてはいけません

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.20%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る