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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

1704閲覧

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

cloford_

総合スコア2

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/10/19 02:19

編集2020/10/19 02:35

前提・実現したいこと

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

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

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

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

該当のソースコード

C#

1 2using System; 3 4/* 5初期カードは52枚。引く際にカードの重複は無いようにする 6プレイヤーとディーラーの2人対戦。プレイヤーは実行者、ディーラーは自動的に実行 7実行開始時、プレイヤーとディーラーはそれぞれ、カードを2枚引く。引いたカードは画面に表示する。ただし、ディーラーの2枚目のカードは分からないようにする 8その後、先にプレイヤーがカードを引く。プレイヤーが21を超えていたらバースト、その時点でゲーム終了 9プレイヤーは、カードを引くたびに、次のカードを引くか選択できる 10プレイヤーが引き終えたら、その後ディーラーは、自分の手札が17以上になるまで引き続ける 11プレイヤーとディーラーが引き終えたら勝負。より21に近い方の勝ち 12JとQとKは10として扱う 13Aはとりあえず「1」としてだけ扱う。「11」にはしない 14*/ 15namespace ConsoleApp2 16{ 17 class Deck//山札を管理するクラス 18 { 19 static void Main(string[] args)//52枚のカードを作る関数 20 { 21 Card[] cards = new Card[1]; 22 int[] num = new int[5] { 1, 2, 3, 4, 5 }; 23 string[] mark = new string[4] { "daiya","spades","clubs","hearts"}; 24 cards[0].mark ="daiya"; 25 //cards[0].num = 1; 26 Console.WriteLine(cards[0].mark); 27 28 } 29 } 30 31 class Me //自分の手札を管理するクラス 32 { 33 34 } 35 36 class Dealer//ディーラーの手札を管理するクラス 37 { 38 39 } 40 41 public class Card//カードの変数を作るためのクラス 42 { 43 public int num; 44 public string mark; 45 } 46} 47

試したこと

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

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

Visual Studioを使っています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/10/19 02:23

>上に書いてしまった 質問は編集できますので、うつせば良いと思います。
cloford_

2020/10/19 02:31

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

2020/10/19 02:33

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

2020/10/19 02:36

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

回答2

0

ベストアンサー

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

C#

1Card cards = new Card();

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

C#

1int[] num = new int[5];

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

C#

1Card[] cards = new Card[1];

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

C#

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

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

投稿2020/10/19 02:33

編集2020/10/19 02:57
yuuyu

総合スコア1139

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2020/10/19 02:41

cards[0]は初期化時nullなので Card cards.mark = "daiya"; というよりは null.mark = "daiya"; なのではないでしょうか。 エラーもNullReferenceExceptionとnullへの参照によるエラーです。
yuuyu

2020/10/19 02:45

> YAmaGNZ さん それは実行後の結果の話ではないでしょうか? 本来質問主さんが書かれたコードをそのまま読んだ場合、new宣言を行っていないので Card cards; cards.mark = "daiya"; という記述と同じ形になりますが、一行で書いてしまったため Card cards.mark = "daiya"; という記述になっています。
YAmaGNZ

2020/10/19 02:56 編集

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

2020/10/19 02:54

> Card cards.mark = "daiya"; これだと(文法的におかしいのもあって)話の意味がわからない. 記述を圧縮(?)する特段の理由も無いでしょうし, > Card cards; > cards.mark = "daiya"; とそのまま書けば話の意味が通じると思うので,そのようにすればどうでしょうか.
yuuyu

2020/10/19 03:00

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

0

classは参照型となります。

C#

1Card[] cards = new Card[1];

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

C#

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

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

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

C#

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

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

C#

1if (Card.mark = "spade")

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

投稿2020/10/19 02:31

編集2020/10/19 02:48
YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/10/19 02:59

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

2020/10/19 12:38

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問