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

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

ただいまの
回答率

88.20%

ブラックジャック(自分で作った型を使った山札の作成)

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 525

cloford_

score 1

前提・実現したいこと

プログラムの練習をするためブラックジャックをC#で作成しようとしています。
まず53枚のトランプが入った山札を作る目的でCardという型を作り、それを使おうとしたのですがどうも動きません。

最終的(まず)は自分で作ったCard型の配列にトランプを作って順番に全部を入れたいと思っています。
書き方が間違っていると思うのですが、調べても分からなかったのでご指導お願いします…

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

System.NullReferenceException: 'Object reference not set to an instance of an object.'
cards が null でした。

該当のソースコード

using System;

/*
初期カードは52枚。引く際にカードの重複は無いようにする
プレイヤーとディーラーの2人対戦。プレイヤーは実行者、ディーラーは自動的に実行
実行開始時、プレイヤーとディーラーはそれぞれ、カードを2枚引く。引いたカードは画面に表示する。ただし、ディーラーの2枚目のカードは分からないようにする
その後、先にプレイヤーがカードを引く。プレイヤーが21を超えていたらバースト、その時点でゲーム終了
プレイヤーは、カードを引くたびに、次のカードを引くか選択できる
プレイヤーが引き終えたら、その後ディーラーは、自分の手札が17以上になるまで引き続ける
プレイヤーとディーラーが引き終えたら勝負。より21に近い方の勝ち
JとQとKは10として扱う
Aはとりあえず「1」としてだけ扱う。「11」にはしない
*/
namespace ConsoleApp2
{
    class Deck//山札を管理するクラス
    {
        static void Main(string[] args)//52枚のカードを作る関数
        {
            Card[] cards = new Card[1];
            int[] num = new int[5] { 1, 2, 3, 4, 5 };
            string[] mark = new string[4] { "daiya","spades","clubs","hearts"};
            cards[0].mark ="daiya";
            //cards[0].num = 1;
            Console.WriteLine(cards[0].mark);

        }
    }

    class Me //自分の手札を管理するクラス
    {

    }

    class Dealer//ディーラーの手札を管理するクラス
    {

    }

    public class Card//カードの変数を作るためのクラス
    {
        public int num;
        public string mark;
    }
}

試したこと

自分で配列を作ってみましたがこのコードだとCard[0].markに"dia"が入ってると思うのですがnullが返ってきました。
書き方の問題かなと思って検索したが見つからなかった(探し方の問題?)

補足情報(FW/ツールのバージョンなど)

Visual Studioを使っています

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • m.ts10806

    2020/10/19 11:23

    >上に書いてしまった

    質問は編集できますので、うつせば良いと思います。

    キャンセル

  • cloford_

    2020/10/19 11:31

    編集しました!ご指摘ありがとうございます。

    キャンセル

  • Daregada

    2020/10/19 11:33

    回答を得られて動くようになったと思うので、"dia"なのか"daiya"なのか、自分で統一しましょう。
    さらに、文字列ではなく列挙型(Enum)でマークを示せないか調べるといいのでは。

    キャンセル

  • cloford_

    2020/10/19 11:36

    daiyaに統一しました!
    列挙型についても調べてみます。ありがとうございました。

    キャンセル

回答 2

checkベストアンサー

0

オブジェクトを使用する時、例えばCardクラスを使用する場合は初期化(正確にはインスタンス化ですが。。)が必要です。

Card cards = new Card();

また、配列を使用する場合は、それもまた初期化が必要です。

int[] num = new int[5];

ところで、下記コードはクラス、配列の初期化でしょうか。

Card[] cards = new Card[1];


[1]と記載されているので、配列の初期化になります。
つまり、cards[0]は、まだクラスの初期化を行っていません。
そのため、cards[0].mark ="daiya";は、

Card cards;
cards.mark = "daiya"; //cardsを初期化していないため、実質 null.markになっている


をしているようなコードになってしまっているため、エラーが出ていると思われます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/10/19 11:52 編集

    ですから、質問者さんのコードは
    Card[] cards = new Card[1];
    cards[0].mark ="daiya";
    このようになっていて、cards[0]は初期状態のnullです。
    この問題はnew Card[1]とインスタンスを作成しているつもりでも参照型のために実際のCardクラスのインスタンスが作成されていないのが原因で、
    Card cards;
    cards.mark = "daiya";
    とインスタンスを作成していないのがひと目で分かるものと比較するのは少し違うのではないかと思います。

    キャンセル

  • 2020/10/19 11:54

    > Card cards.mark = "daiya";

    これだと(文法的におかしいのもあって)話の意味がわからない.
    記述を圧縮(?)する特段の理由も無いでしょうし,

    > Card cards;
    > cards.mark = "daiya";

    とそのまま書けば話の意味が通じると思うので,そのようにすればどうでしょうか.

    キャンセル

  • 2020/10/19 12:00

    > 記述を圧縮(?)する特段の理由も無い
    これに関しては回答時点で分割して記述する方法が思いつかなかった(というか考えもしなかった)のでこういう表記を記述しました。
    分かりにくいと言われたらそれは間違いないので、この点は修正します。

    キャンセル

0

classは参照型となります。

Card[] cards = new Card[1];


なので、上記のように定義したclassの配列の中身はそのclassの参照が入ることになります。
配列を作成した時点では、その参照はnullと設定されています。

cards[0] = new Card();
cards[0].mark ="daiya";


と値を代入する前にcards[0]に実際のクラスの参照を入れてやらないといけません。

追記
コメントにてマークについて触れていたので・・・

    public enum CardMark
    {
        Non=0,
        spade = 1,
        club = 2,
        diamond = 3,
        heart = 4
    }
    public class Card//カードの変数を作るためのクラス
    {
        public int num;
        public CardMark mark;
    }


といった感じで文字列で持つのではなく列挙型を使ったほうがよろしいかと思います。
文字列で持つと

if (Card.mark = "spade")


といった感じで書いてスペルミスなどでバグを埋め込む原因となったりします。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/10/19 11:59

    (ものすごくどうでもいい話ですが… "CardMark" → "Suit" とかにしたい)

    キャンセル

  • 2020/10/19 21:38

    直しました。確かにスートですもんね。

    キャンセル

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

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

関連した質問

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