第 6 章 数当てゲームで遊んでみよう
サンプルプログラムのダウンロード (chap6_csharp.msi, 222 KB)
※ また、サンプルプログラムは、あらかじめ Visual C# 2005 Express Edition と同じパソコンにインストールしておいてください。
設定方法は こちら
この章でやること
・ 数当てゲームを完成させます。
・ 乱数の使い方を体験します。
学校の帰り道、翔太君 と美咲さん が今日のテストのことを話しています。どうやらテストがあったのは翔太君のクラスだけだったようです。
| 翔太 | :なんとかテストが終わったよ。100 点とまではいかなかったけど、夕べ暗記した効果はあったみたい。 |
| 美咲 | :じゃあ、あの単語帳プログラムが役に立ったのね。私のクラスでテストがあるときにも使おうかな。 |
| 翔太 | :全部じゃないけどね。覚える範囲が多すぎて、テキストファイルを作るのが間に合いそうになかったから、とりあえず問題に出そうなところを適当に選んだんだ。それでも、3 割くらいは予想が当たってたと思う。 |
| 美咲 | :それじゃ、勉強したっていうより予想してたみたいなものじゃない。あきれた。 |
| 翔太 | :まあまあ。でも、作った問題に関してはばっちり暗記できたから、あのプログラムは悪くないと思うよ。残りのプログラムの中にまだ便利なものがあるといいなぁ。 |
| 美咲 | :それじゃ、帰ったら続きをやりましょうか。・・・もちろん、宿題のあとでね。 |
| 翔太 | :しかたない、宿題と一緒にがんばるか。 |
二人は翔太君の家に着くと、早速宿題に取り掛かりました。宿題が一段落したころ、翔太君の携帯電話が鳴りました。
| 翔太 | :あれ? 健一さんだ。 ・・・もしもし。 |
| 健一 | :もしもし、今日もプログラムの勉強をするのかい? |
| 翔太 | :うん、そのつもりだよ。宿題がもうすぐ終わりそうだから、また続きをやろうと思ってるところなんだ。 |
| 健一 | :そうか。実は、急に出張が入ってしまって、今日はそっちにいけそうにないんだよ。 |
| 翔太 | :そうなんだ。でも、大丈夫。昨日の 第 5 章が何とかなったから、今日もがんばってみるよ。 |
| 健一 | :これから飛行機に乗るから、しばらくは電話に出られないけど、ホテルについたらまた電話するよ。 |
| 翔太 | :うん、ありがとう。それじゃ。 |
| 美咲 | :健一さん来られないのね。 |
| 翔太 | :うん、でもとりあえずやってみようよ。健一さんにもあとで電話で質問しながらやれば、何とかなるよ、きっと。 |
| 美咲 | :それじゃ始めましょうか。 |
二人は、早速入門マニュアルを開いて、第 6 章に取り掛かりました。
| 美咲 | :今回は、数当てゲームだそうよ。 |
| 翔太 | :ゲーム? へぇー、どんなプログラムなんだろう。サンプルを開いてみよう。 |
プログラムメニューから Visual C# 2005 Express Edition を立ち上げて、サンプルファイルフォルダの中の Part6_C#\Part6_Base フォルダにある Part6.sln を開きます。そして、[ソリューション エクスプローラ] から、[Form1.cs] を開きます。

| 翔太 | :入力欄っていうところに数字の 50 って入ってるね。横に上下ボタンがついているところをみると、数値アップダウン コントロールを使ってるみたいだ。[START] ボタンでゲームが始まって、そのあとはどうするんだろう。 |
| 美咲 | :ゲームの遊び方が書いてあったわ。入力欄に 1 から 100 の間の数字を指定して [解答] ボタンを押すんだそうよ。それで、[START] ボタンを押したときにプログラムが用意した正解の数字が何なのかを当てるゲームですって。数字が当たっていれば、メッセージを表示してゲームが終了するらしいわ。 |
| 翔太 | :メッセージは下の黒いところに表示されるのかな。右側の解答履歴は何? |
| 美咲 | :10 回まで答えを入力できるんだけど、今までどの数字を答えたのかが表示されるみたい。つまり不正解だった数字を確認しながら推理できるようになってるわけね。 |
| 翔太 | :なるほど。とりあえず、デバッグ ボタンを押してみようか。 |
デバッグ ボタンをクリックして、プログラムを実行します。[START] ボタンをクリックしても、特に何も起こりません。

| 翔太 | :[START] ボタンを押しても何も起きないね。入力欄だけは動くみたいだ。 |
| 美咲 | :まずは変数の準備から始めるみたいだわ。 |
| 翔太 | :また変数か。やっぱりプログラミングでは重要なんだね。それじゃどういう変数が必要か見ていこうか。
|
二人はデバッグ 画面を閉じて、先に進めることにしました。
<ゲーム内で使う変数を用意しよう>
| 美咲 | :まず、コードを書き込むための画面に切り替えるところからね。 |
| 翔太 | :・・・え? |
| 美咲 | :え、って? |
| 翔太 | :いや、今までだとイベントを登録したりすることでコード エディタを開いてたじゃない。それがいきなりコード エディタの画面に行っちゃうの? というより、どうやって直接開くの? |
| 美咲 | :今回はイベントとかを抜きにして、変数から入るみたいだからじゃないかしら。コード エディタの開き方は、[表示] メニューの [コード] を選択するといいらしいわ。 |
| 翔太 | :どれどれ・・・ |


| 翔太 | :開いた! |
| 美咲 | :それで、リスト 6-1-1 のコードを「InitializeComponent();」の下にある「}」のさらに次の行に追加するの。 |
リスト 6-1-1
// 正解の数値を格納する変数
private int Answer;
// 残り解答回数を格納する変数
private int Count;
|
| 翔太 | :最初に変数を宣言してるんだね。 |
| 美咲 | :Answer が正解の数値で、Count が解答の数、どちらも int 型の変数ということになるわね。 |
| 翔太 | :なるほど。でも、こんなところで変数の宣言をするってことは、よほど重要な変数なんだろうね。 |
| 美咲 | :そうね。この変数をどう使うか、早速次に進んで見てみましょう。 |
<ゲームの開始処理を記述しよう>
| 美咲 | :それじゃ、ゲームが開始するための処理をプログラミングしていきましょうか。 |
| 翔太 | :開始するための処理、ってことは [START] ボタンの関係かな。 |
| 美咲 | :どうしてわかったの? |
| 翔太 | :だって、[START] ボタンを押さないと、ゲームが始まりそうにないじゃない。 |
| 美咲 | :あ、そうか。それじゃ、[START] ボタンのプロパティ ウィンドウを開いて、[イベント] アイコン をクリックしてイベントの一覧を表示して。 |
| 翔太 | :デザイナ 画面に一旦戻って、ボタンのプロパティ ウィンドウを開いて、っと。 |

| 美咲 | :[Click] の右にあるコンボ ボックスに「btnStart_Click」と入力して [Enter] キーを押すと、リスト 6-2-1 のコードが追加されるはずよ。 |
リスト 6-2-1 は、あとで読み返すときにわかりやすいようにコメント文を追加した形で紹介しています。実際に上記の手順でコードを追加した場合、コメントは追加されていませんので、必要に応じて自分で書き加えてください。以後のリストについても同様です。
リスト 6-2-1
// [START] ボタンを押したときの処理
private void btnStart_Click(object sender, System.EventArgs e)
{
}
|

| 翔太 | :この「private void btnStart_Click〜」の次の行にある「{」と「}」の間にコードを書いていくんだね。 |
| 美咲 | :そうよ。次のリスト 6-2-2 を入力してみて。 |
リスト 6-2-2
// Random を使って乱数を生成して正解の数値として設定する
Random r = new Random();
Answer = r.Next(1, 101);
|
| 翔太 | :新しい単語が出てきたね。Random ってなんだろう。新しい変数なのかな。 |
| 美咲 | :でも、変数だったら new なんて変よね。入門マニュアルによると・・・、これは、クラスの設定らしいわ。それに、変数っていうのもあながち間違いじゃなかったみたい。 |
| 翔太 | :クラス? あの、コントロールみたいにあらかじめ特定の機能を用意してある奴? |
| 美咲 | :そう。Random っていうクラスをこのプログラムで使えるように宣言しているらしいわ。Random クラスは、呼び出されるたびに毎回違う数値を作り出す機能があるんだって。 |
| 翔太 | :毎回違う数値・・・? |
| 美咲 | :それで、このクラスをそのまま使うわけにはいかないので、r という名前の変数を用意して、Random クラス型として宣言してるそうよ。それで、その変数を通して Random クラスの機能を使ってるみたい。 |
| 翔太 | :new とかなんとかっていうのはそのために必要なことなんだ。 |
| 美咲 | :そう書いてあるわ。それで、その次の行でやってるのは、Random クラスの Next メソッドでその数値を取り出してるようよ。 |
| 翔太 | :なるほど、それを Answer 変数に代入してるんだ。1 と 101 っていうのは何? |
| 美咲 | :1 から 100 までの間の範囲で、Random クラスに数値を作らせるための範囲設定だそうよ。 |
| 翔太 | :100 までなのに 101 ? |
| 美咲 | :Random クラスは、最大値に設定された数値よりも小さい数値を作るから、1 から 100 までの範囲にしたい場合は、最大値を 101 にする決まりだって書いてあるわ。 |
| 翔太 | :なんだかややこしい決まりだなぁ。 |
| 美咲 | :本当ね。このあたりのことはちょっとわかりづらいから、あとで健一さんに確認しましょう。 |
| 翔太 | :そうだね。 |
| 美咲 | :次は、ゲームの初期化、っていう作業になるらしいわ。 |
| 翔太 | :初期化は第 4 章にも出てきたぞ。たしか、いろいろな値をゼロにしたりして、もっとも安全な状態でプログラムを始められるようにすることじゃなかったっけ。 |
| 美咲 | :たしかそんな感じだったわね。とりあえず、リスト 6-2-2 のあとに次のリスト 6-2-3 のコードを追加して。 |
リスト 6-2-3
// [解答] ボタンを有効化
btnAnswer.Enabled = true;
// [START] ボタンを無効化
btnStart.Enabled = false;
// [解答履歴] リスト ボックスをクリア
lstRireki.Items.Clear();
// [入力欄] 数値 アップ ダウン コントロールの値を 50 に設定
nudAnswer.Value = 50;
// 残り解答回数を 10 に設定
Count = 10;
// 残り解答回数のメッセージを作成してラベルに設定する
lblMessage.Text = "残り" + Count.ToString() + "回";
|
| 翔太 | :追加したよ。でも、あまり複雑なことはやってないね。 |
| 美咲 | :それじゃ説明してみてくれる? |
| 翔太 | :まず、btnAnswer だから [解答] ボタンのことだよね。このボタンを True だから有効にしている。それから btnStart だから [START] ボタンを False で無効にしてるね。lstRireki っていうのは、解答履歴のところに書いてあった名前だからここのことだろうな。それの Items が Clear ? ・・・これは初めてみるけど、テキスト ボックスじゃないのかな。 |
| 美咲 | :それはリスト ボックスって言うらしいわ。項目を一覧表示してくれるコントロールだそうよ。Items というのは一覧に表示される項目を指すプロパティみたい。 |
| 翔太 | :・・・、じゃあ、Clear っていうのは一覧の中身を削除してるんじゃない? だって前の解答一覧が表示されても困っちゃうし。 |
| 美咲 | :どうやら正解みたいよ。ということは、逆にこの Items プロパティに項目を追加するコードがいずれ出てくるってことでしょうね。 |
| 翔太 | :なるほど、それは解答作業のときの処理だね。ここの残りの行は、入力欄の値を 50 に、残り解答回数を 10 に設定して、さらに残り何回かっていうメッセージを表示させてるのか。Count.ToString の ToString は、数値を文字列に変換するメソッドだったよね、確か。 |
| 美咲 | :全部正解。すごいわ、翔太君。だんだんわかるようになってきたみたいね。 |
| 翔太 | :このあたりは今までやったことばかりだからね。まだ何とかなるけど、さっきみたいに新しいのが出てきたらだめだな。 |
| 美咲 | :新しい言葉が出てきたらわからないのはみんな一緒よ。あわてる必要はないんだから、ゆっくり見ていきましょうよ。 |
| 翔太 | :うん、わかってるよ。それじゃ、次に行ってみようか。 |
<解答の入力と当たり判定処理を追加しよう>
| 美咲 | :今度は、解答入力と、それが当たっているかどうかの判定処理に進みましょう。 |
| 翔太 | :解答の入力だね。それじゃコードを確認する前に、どういう処理をするか予想してみようか。 |
| 美咲 | :それじゃ、私も考えてみるわね。まず、[解答] ボタンがあるんだから、そのボタンを押したら解答したことになるのが理想よね。 |
| 翔太 | :そうだね。そうすると、まず Click イベントを処理するコードを追加しないといけないみたいだな。それで、イベントが発生すると、入力欄に入力された値と、Answer 変数の値が一致しているかどうかを判定するんだ。 |
| 美咲 | :判定のときは、条件分岐を使うといいのよね。 |
| 翔太 | :単語帳のときもそれでやってたしね。ここまでは合ってるのかな。 |
| 美咲 | :えっと、まず、Click イベントを処理するコードを追加する、ってなってるわ。 |
[解答] ボタンのプロパティ ウィンドウを表示します。そして、[イベント] アイコン でイベントの一覧を表示し、 [Click] の右にあるコンボ ボックスに「btnAnswer_Click」と入力して [Enter] キーを押します。すると、リスト 6-3-1 のコードが追加されます。
リスト 6-3-1
// [解答] ボタンを押したときの処理
private void btnAnswer_Click(object sender, System.EventArgs e)
{
}
|
| 美咲 | :リスト 6-3-1 のコードが追加されたら、「private void btnAnswer_Click〜」の次の行にある「{」と「}」の間の行にリスト 6-3-2 のコードを追加してみて。 |
リスト 6-3-2
// メッセージ文字列を格納する変数を用意する
string Message;
// 正解(Answer)と、[入力欄] に指定した解答が等しいか判断
if (Answer == nudAnswer.Value)
{
}
else
{
}
|
| 翔太 | :これって、条件分岐じゃないか。ここまでは正解だったんだね。 |
| 美咲 | :ここからが当たり判定の重要なところよ。 |
| 翔太 | :この部分の最初で Message 変数を string 型で宣言してるね。これが正解かどうかのメッセージを入れておくところになるんだろうな。 |
| 美咲 | :えーっと、さらに「if (Answer == nudAnswer.Value)」の次の行にある「{」と「}」の間の行にリスト 6-3-3 のコードを入力するように、って。 |
リスト 6-3-3
// 等しかったときの処理
// Message に「正解!」と代入
Message = "正解!";
// [解答] ボタンを無効化
btnAnswer.Enabled = false;
// [START] ボタンを有効化
btnStart.Enabled = true;
|
| 翔太 | :これは正解の場合の処理だね。if で始まる条件式のところでは、Random クラスを使って作った Answer 変数の値と、数値アップダウン コントロールの nudAnswer の値が同じになる条件式が書いてあるから、その条件式が満たされる、つまり正解が入力されたら、このリスト 6-3-3 が処理されるんだね。 |
| 美咲 | :ボタンの処理が、[START] ボタンを押したときと逆になってるわ。 |
| 翔太 | :[解答] ボタンが無効になって、[START] ボタンが有効になってるね。・・・ということは、最初に [START] ボタンを押す前に戻ってるんだから、ゲームはここで終了ってことなんだ。 |
| 美咲 | :あ、そうか。 |
| 翔太 | :ということは、不正解の場合はどうするんだろう? |
| 美咲 | :不正解の場合は、「else」の次の行にある「{」と「}」の間の行にリスト 6-3-4 を追加するとわかるみたいよ。 |
リスト 6-3-4
// 等しくなかったときの処理
// 残り解答回数を 1 減らす
Count = Count - 1;
// 残り解答回数が 0 か判断
if (Count == 0)
{
}
|
| 翔太 | :なんだ、なんだ? ちょっとわからなくなってきたぞ。 |
| 美咲 | :まず、Count というのは、残り解答回数を表わす変数だったわよね。 |
| 翔太 | :それが自分自身から 1 を引いたものを代入・・・? あ、そういえば、自分で自分に 1 を加える式って前に出てきたよね。 |
| 美咲 | :第 4 章のラーメンタイマー! あの時は、確か、設定された時間に達するまで Timer コンポーネントのイベントを数えてたんじゃなかったかしら。 |
| 翔太 | :そうだ、思い出した。自分で自分に足し算するなんておかしいと思って健一さんに質問したんだよ。てことは、ここでも同じことが行われてるってことかな。 |
| 美咲 | :今回は逆に数を 1 ずつ減らしていってるみたいね。それで、残り回数が 0 になったら、っていうのが if で設定されてるようよ。 |
| 翔太 | :ここに入るコードは? |
| 美咲 | :次のリスト 6-3-5 よ。 |
リスト 6-3-5
// 残り解答回数が 0 だったときの処理
// Message に「残念!」と代入
Message = "残念!";
// [解答] ボタンを無効化
btnAnswer.Enabled = false;
// [START] ボタンを有効化
btnStart.Enabled = true;
|
| 翔太 | :さっきの「正解!」って書いてあるところが「残念!」に変わっただけだね。・・・って、これだけ? |
| 美咲 | :ここはこれだけよ? どうして? |
| 翔太 | :だって、これじゃ、10 回終わるまで「残念!」って出ないってことになるじゃないか。それまでは正解したときにしかメッセージが出ないんじゃ面白みがないよね。 |
| 美咲 | :それをやるのはこれからよ。そんなに焦らないで。 |
リスト 6-3-5 を入力したあと、その下の「}」の行の次に続いてリスト 6-3-6 を書き加えてください。
リスト 6-3-6
// 残り解答回数が 0 ではなかったとき、
// 正解の数値と解答を比較する
else if (Answer > nudAnswer.Value)
{
// 正解が解答より大きかったら、解答残り回数と
// 正解がより大きいことを伝える文字列を作成し
// Message に代入する
Message = "残り" + Count.ToString() + "回"
+ Environment.NewLine + "もっと大きいよ";
}
else
{
// 正解が解答より小さかったら、解答残り回数と
// 正解がより小さいことを伝える文字列を作成し
// Message に代入する
Message = "残り" + Count.ToString() + "回"
+ Environment.NewLine + "もっと小さいよ";
}
|
この結果、この条件分岐は次のリスト 6-3-7 のようになります。
リスト 6-3-7
// 残り解答回数が 0 か判断
if (Count == 0)
{
// 残り解答回数が 0 だったときの処理
// Message に「残念!」と代入
Message = "残念!";
// [解答] ボタンを無効化
btnAnswer.Enabled = false;
// [START] ボタンを有効化
btnStart.Enabled = true;
}
// 残り解答回数が 0 ではなかったとき、
// 正解の数値と解答を比較する
else if (Answer > nudAnswer.Value)
{
// 正解が解答より大きかったら、解答残り回数と
// 正解がより大きいことを伝える文字列を作成し
// Message に代入する
Message = "残り" + Count.ToString() + "回"
+ Environment.NewLine + "もっと大きいよ";
}
else
{
// 正解が解答より小さかったら、解答残り回数と
// 正解がより小さいことを伝える文字列を作成し
// Message に代入する
Message = "残り" + Count.ToString() + "回"
+ Environment.NewLine + "もっと小さいよ";
}
|
| 翔太 | :なんだ、まだここの条件分岐は終わってなかったのか。 |
| 美咲 | :そういうこと。まず最初に、「else if」でまた条件式が出てるわね。 |
| 翔太 | :ちょっと整理しようか。この「else if」はリスト 6-3-4 に出てくる「if (Count == 0)」と繋がってるんだよね。だから、Count 変数、つまり残り解答回数が 0 じゃなかったら、この「else if」の条件式を確認しに来るんだ。 |
| 美咲 | :そうね。そして、ここには「Answer 変数」、つまり「正解の数値」が、「nudAnswer の値」、つまり、「入力した数値」よりも大きい、という式が書いてある。ということは、「この条件式が満たされる」場合を考えればいいんだから、「入力した数値よりも正解が大きい」場合は、「この次の行が処理される」ということでいいのかしら。 |
| 翔太 | :Message 変数に「もっと大きいよ」というメッセージが代入されているからそれで合ってると思うよ。でも、ここでまた新しい単語が出てきてるな。前半の「"残り" + Count.ToString() + "回"」が、残り回数を表示しようとしてるのはわかるんだけど、Environment.NewLine ってなんだろう? |
| 美咲 | :Environment っていうのもクラスの名前らしいわ。NewLine っていうのはそのプロパティ。Environment.NewLine とすることで、文字列を改行するための改行コードを結合させることができるみたい。 |
| 翔太 | :改行コード? ・・・ということは、これがないと残り回数表示とメッセージが続けて表示されちゃうってことなのかな。でも改行コードってどういうことだろう? |
| 美咲 | :うーん、改行するための何かが入ってるってことなのよね、きっと。 |
| 翔太 | :・・・あれ? そういえば、Random クラスは宣言みたいなことをしてたけど、Environment クラスは必要ないの? |
| 美咲 | :言われてみれば、そうね・・・ でも、この入門マニュアルにはそこまで書いてないわ。 |
| 翔太 | :うーん、やっぱり健一さんに聞いてみるしかないかな。さっきのプロパティで改行を設定しているところについてもあとで聞くことにしよう。でも健一さんに質問する前に、さっきの改行についてのコードがなければどうなるかも試してみたいな。 |
| 美咲 | :そうね。もう少しでこのプログラムも終わりそうだから、とりあえず最後までやってからにしない? |
| 翔太 | :わかったよ。えーと、正解が入力した値より大きい場合には、「もっと大きいよ」というメッセージが表示されるところまでいったんだよね。その次に出てくる else は、この条件式が満たされない場合に処理されるんだから、この場合は・・・ |
| 美咲 | :正解が入力した値よりも小さい場合、じゃない? |
| 翔太 | :そうだね。それで、その次の処理を見ると・・・ |
| 美咲 | :基本的には条件式を満たす場合と同じね。ただ、表示されるメッセージが「もっと小さいよ」に変わってるわ。 |
| 翔太 | :なるほど。で、それが終わると条件分岐が終了するんだ。これでもう終わりかな。 |
| 美咲 | :まだよ。もう一つ次の「}」も終わって、完全に条件分岐が終了したところで、リスト 6-3-8 のコードを追加するみたい。 |
| 翔太 | :リスト 6-3-8 ? |
リスト 6-3-8
// メッセージをラベルに設定する
lblMessage.Text = Message;
// [解答履歴] に解答を追加する
lstRireki.Items.Add(nudAnswer.Value.ToString());
|
| 美咲 | :まず、メッセージを表示するテキスト ボックスの Text プロパティに、Message 変数の値を代入してるわね。それから、解答履歴を表示するリスト ボックスに、nudAnswer で入力された値を追加しているみたい。 |
| 翔太 | :あれ、この行は・・・、そうか、条件分岐などとは関係がないんだ。だから、この [解答] ボタンがクリックされたときに必ず処理されるんだね。 |
| 美咲 | :そのようね。さあ、ここまでできたら、デバッグ ボタンをクリックして動かしてみましょうよ。 |
デバッグ ボタンを押して、実際の動作を確かめてみてください。



| 翔太 | :どうやらちゃんとできたみたいだ。 |
| 美咲 | :数字の大小もちゃんと判別してるようね。 |
| 翔太 | :それじゃ、リスト 6-3-6 に出てきたコードをちょっと変えてやってみようか。 |
| 美咲 | :あの改行のところ? |
| 翔太 | :そう、リスト 6-3-6 から、「+ Environment.NewLine」の部分を削除して、リスト 6-3-9 のようにしてデバッグ ボタンを押してみよう。 |
デバッグ 画面を一度終了してから、コード エディタで、リスト 6-3-6 を入力した部分を次のリスト 6-3-9 ように書き直してみてください。直し終わったら、デバッグ ボタンを押して、ゲームを開始してみます。
リスト 6-3-9
// 残り解答回数が 0 ではなかったとき、
// 正解の数値と解答を比較する
else if (Answer > nudAnswer.Value)
{
// 正解が解答より大きかったら、解答残り回数と
// 正解がより大きいことを伝える文字列を作成し
// Message に代入する
Message = "残り" + Count.ToString() + "回" + "もっと大きいよ";
}
else
{
// 正解が解答より小さかったら、解答残り回数と
// 正解がより小さいことを伝える文字列を作成し
// Message に代入する
Message = "残り" + Count.ToString() + "回" + "もっと小さいよ";
}
|

| 美咲 | :へえー。改行されないとこういう風に表示されるのね。 |
| 翔太 | :見栄えを良くするためには、ああいうコードも必要だってことだね。 |
| 美咲 | :なるほど。プログラムの中身だけじゃなくて、見え方も考えないといけないのね。 |
| 翔太 | :とりあえず、これで第 6 章は終了かな。 |
| 美咲 | :そうみたい。 |
| 翔太 | :それじゃ、健一さんに電話して、クラスについて聞いてみようよ。 |
| 美咲 | :そうしましょう。 |
翔太君達が健一さんに電話している間に、もし今回のプログラムがうまく動かなかった人がいたら、デバッグを終了してコード エディタを開いて、イベントの名前や変数の名前などが間違っていないかよく確認してみてください。リスト 6-3-8 までのコードが正しく入力されていれば、次のリスト 6-3-10 のようになっているはずです。なお、ここまでやってきた作業には、すべて意味があります。ただ単にこのコードをそのままコピーして貼り付けても、正常に動作しない場合がありますので、わからなくなったら、最初からやり直してみてください。
リスト 6-3-10
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Part6
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// 正解の数値を格納する変数
private int Answer;
// 残り解答回数を格納する変数
private int Count;
private void btnStart_Click(object sender, System.EventArgs e)
{
Random r = new Random();
Answer = r.Next(1, 101);
btnAnswer.Enabled = true;
btnStart.Enabled = false;
lstRireki.Items.Clear();
nudAnswer.Value = 50;
Count = 10;
lblMessage.Text = "残り" + Count.ToString() + "回";
}
private void btnAnswer_Click(object sender, System.EventArgs e)
{
String Message;
if (Answer == nudAnswer.Value)
{
Message = "正解!";
btnAnswer.Enabled = false;
btnStart.Enabled = true;
}
else
{
Count = Count - 1;
if (Count == 0)
{
Message = "残念!";
btnAnswer.Enabled = false;
btnStart.Enabled = true;
}
else if (Answer > nudAnswer.Value)
{
Message = "残り" + Count.ToString() + "回"
+ Environment.NewLine + "もっと大きいよ";
}
else
{
Message = "残り" + Count.ToString() + "回"
+ Environment.NewLine + "もっと小さいよ";
}
}
lblMessage.Text = Message;
lstRireki.Items.Add(nudAnswer.Value.ToString());
}
}
}
|
さて、どうやら、健一さんと電話が繋がったようです。
| 健一 | :やあ、翔太君。また何かわからないことがあったのかな? |
| 翔太 | :健一さん、今電話で話しても大丈夫? |
| 健一 | :うん、ちょうどホテルについて、荷物を降ろしたところだから、大丈夫だよ。 |
| 翔太 | :第 6 章の数当てゲームを作ってみたんだけど、そこでクラスがまた出てきたんだ。 |
| 健一 | :そうか、クラスは使いこなせるとかなり便利だから、サンプルでも取り入れているんだろうな。それで、どの辺りがわからないんだい? |
| 翔太 | :Random クラスを使う際に、一番最初に宣言してるんだけど、クラスによって宣言したりしなかったりしてるみたいなのはどうして? |
| 健一 | :おいおい、いきなりすごい質問だな。 |
| 翔太 | :そうなの? |
| 健一 | :今の質問はクラスの使い方の根本にかかわる部分なんだ。Random クラスの宣言、といってるのは、new Random とか書いてあるところかい? |
| 翔太 | :そうそう。なんでそこで new なんて出てくるのかもよくわからなかったんだ。 |
| 健一 | :そうだな。ここでは、Random クラス型の r という変数を宣言してるよね。でも、宣言しただけでは、中身がないから使えないんだよ。変数を宣言するときには、最初に初期値を与えて初期化する、って言う話をしたのを覚えてる? |
| 翔太 | :覚えてるよ。変数を一番安全な状態から始めるために、何か値を設定しておくんだよね。 |
| 健一 | :クラス型の変数も中身を代入してからじゃないと使えないんだ。それで、クラスの場合は、“new クラス名“ と書くことで中身を新しく作って、それを代入するんだよ。 |
| 翔太 | :そういうことだったんだ。なるほど・・・ でも、そうしたらなぜ、new がいらないクラスがあるの? |
| 健一 | :クラスにもいくつか種類があるのはわかるよね。例えば、単語帳のときのように自分で作るクラスもあれば、あらかじめ用意されているクラスもある。それと同じように、クラスの中にも宣言が必要なものとそうでないものもある、という風に考えておいてくれればいい。 |
| 翔太 | :うん。 |
| 健一 | :ただ、クラスを使うときの基本的な使い方は、実は今回出てきた Random クラスを使うときの記述方法が一般的なんだ。細かい説明を始めると、またかなりややこしいことになるから省略するけど、とりあえず、今回のクラスの使い方は覚えておいて損はないよ。 |
| 翔太 | :うん、わかった。それじゃ、改めて本格的にプログラムのことを勉強するときにまた質問することにするよ。 |
| 健一 | :よし、そのときはとことん話してあげるよ。あとは何がわからなかったんだい? |
| 翔太 | :あとは、なんだっけ。 |
そばで聞いていた美咲さんがじれったくなって、口を挟みました。
| 美咲 | :改行の話! |
| 翔太 | :そうそう、今回、Environment.NewLine で改行コードを結合するっていうところが出てきたんだけど、文字列と改行コードを結合するってどういうことなの? |
| 健一 | :なるほど。えーっと、翔太君は改行コードが何かは知ってるの? |
| 翔太 | :改行するための何かなのかな、っていうくらいにしか・・・ |
| 健一 | :そうか。実は、テキストファイルで文字を改行させる場合、どこで行を変えるかっていう目印をパソコンに教えてあげないといけないんだよ。そうしないと、パソコンは行を変える場所がわからなくて、ずっと 1 行で文字を続けてしまうんだ。 |
| 翔太 | :へー。そうなんだ。意外に頭が悪いんだなぁ。 |
| 健一 | :うーん、頭が悪い、というのとはまたちょっと違うかな。パソコンは元々、命令を与えられて初めて動くものだから、改行しなさいという命令がなければ、逆に文字を続けて表示するという命令を守らざるを得ないんだよ。 |
| 翔太 | :あ、そういうことか。 |
| 健一 | :そう、でもこの改行文字というのは、普通のユーザーにはあまり意味がないから、パソコン上では見せる必要がない。Microsoft Word などのワープロソフトの場合は、改行位置を明確にするためにわざと表示している場合もあるみたいだけどね。 |
| 翔太 | :じゃ、この NewLine プロパティって言うのは・・・ |
| 健一 | :そう、目に見えない改行の文字を表わしているんだよ。実際のプログラム上で改行文字が見えないのは、それを見せる必要がないからなんだ。ホームページを書くときに使う HTML タグで改行を表わすのに <BR> というタグが用意されているんだけど、それと同じようなものだと考えてくれてもいい。 |
| 翔太 | :なるほど、そういうことだったんだ。それじゃ、あのコードでは、残りの解答回数の文字列と、改行文字と、判定結果のメッセージを結合して表示してるんだね。だから、Environment.NewLine を削除すると、改行文字が間に入らないから、解答回数とメッセージが続けて表示されたんだ。 |
| 健一 | :え? そんなことまでやったの? |
| 翔太 | :うん、入門マニュアルには書いてなかったけど、試しにやってみたんだ。そうしたらちゃんと改行されずに出てきたよ。 |
| 健一 | :そうか、そういうことまでやれるようになったんだね。たいしたもんだ。それじゃ、せっかくだから、Random の設定のところを変えてみるといいよ。 |
| 翔太 | :Random のところ? |
| 健一 | :そう、Random というのは、指定された範囲内で、適当に数値を取り出してくることができるんだ。こうして取り出された数値のことを乱数、と呼んでいる。 |
| 翔太 | :乱数? そういえば、スパイ映画とかで乱数表っていうのが出てきたのを聞いたことがあるよ。 |
| 健一 | :そうそう、その乱数だ。乱数とは、元々予測不可能な数字のことで、スパイはそれを使って暗号に役立ててるというのが、映画の設定。ニュースとかでも時々出てくるから実際にも使われてるらしいけど、パソコンの乱数は、もっと単純に、Random クラスによって生み出された予測できない数字として理解していればいい。 |
| 翔太 | :その設定を変えるってどういうこと? |
| 健一 | :コードではどういう風に設定されてた? |
| 翔太 | :えーっと、確か 1 から 100 までの間の数値、だったっけ。・・・あ、そうか、そこの範囲を変えてやればいいんだ。 |
| 健一 | :そのとおり。そうすると、数字を当てる範囲が変わるから、難易度を変えることもできる。そうそう、ただし、上限が 100 を超える場合には、数値アップダウン コントロールの最大値と初期値を変えるのを忘れないようにね。 |
| 翔太 | :数値アップダウン コントロールの最大値と初期値? |
そばで聞いていた美咲さんが答えました。
| 美咲 | :それならわ
かるわ。最大値は、デザイナ 画面を開いて、コントロールのプロパティ ウィンドウを開くのよ。それで、プロパティ一覧で、・・・えーっと、Maximum の値を 100 から変更すればいいのよ。初期値は、Random クラスで乱数を発生させたそのすぐあとに初期化してるところがあって、そこの数値を変更するのよね。 |
| 翔太 | :・・・ということなんだけど、それで合ってる? |
| 健一 | :正解! 二人とも優秀だね。ぜひあとで実際にどうなるか試してみてごらん。そういえば、今回のサンプルは数当てゲームなんだっけ? |
| 翔太 | :そうだよ。 |
| 健一 | :以前にも出てきた、変数に 1 を加えていくコードの逆で、1 を引いていくコードが出てきただろう? |
| 翔太 | :そうなんだ。でも、以前やったことがあるから、すぐにわかったよ。 |
| 健一 | :あれは、ラーメンタイマーのときだったっけ。あのときは、時間を蓄積するのに使ったんだよね。 |
| 翔太 | :そう、それで今回は回数の残りを数えるために使ってるんだよ。 |
| 健一 | :そうだね。実は、こうやって数を足したり引いたりしながら繰り返す作業というのは、以前も説明したようにプログラミングではとても重要な意味を持つんだ。・・・今が第 6 章で、入門マニュアルが全部で 8 章あるんだっけ。 |
| 翔太 | :そうだよ。 |
| 健一 | :ということは、確か、次の章あたりでこの繰り返し作業を使った新しいテクニックの話が出てくるはずだな、たしか。それじゃそのときにまた詳しいことは説明するとして、今は繰り返し作業が重要な意味を持つ、というのをよく覚えておいてほしい。 |
| 翔太 | :わかった。それじゃ、また第 7 章で困ったら電話するね。 |
| 健一 | :って、おいおい、もうすぐに第 7 章に取り掛かるつもりかい? |
| 翔太 | :うん、だって、面白くなってきたところだし。 |
| 健一 | :そんなにがんばりすぎちゃだめだって。もっとゆっくり楽しんで進めないと。 |
| 翔太 | :十分楽しんでるよ。 |
| 健一 | :うーん、だんだんサンプルのレベルが上がってきて、質問も細かくなってきてるから、そろそろまた僕がそばにいたほうがよさそうだな。今度の週末まで待ってもらってもいいかい? |
| 翔太 | :え? 健一さんがそばで教えてくれるの? |
| 健一 | :それまでには出張も終わってるはずだからね。それに、僕も予習をしてちゃんと質問に答えられるようにしておくよ。 |
翔太君は、美咲さんと相談することにしました。
| 翔太 | :美咲ちゃん、健一さんが残りの章は週末に一緒にやらないかって言ってくれてるんだけど、どうする? |
| 美咲 | :本当に? うーん、確かに先に進めたい気持ちはあるけど、健一さんに何度も電話して聞くのも申し訳ないわよね。 |
| 翔太 | :それもそうか。 |
| 美咲 | :その代わり、健一さんが来る前に宿題は完全に終わらせて、今までの章ももう一度おさらいしておきましょうよ。 |
| 翔太 | :宿題はともかく、今までのおさらいはいいアイデアだね。 |
| 翔太 | :健一さん、それじゃ週末に教えてもらえる? |
| 健一 | :よし、わかった。出張のお土産も持っていくから楽しみにしておいてくれ。 |
| 翔太 | :それじゃ、待ってるから。またね。 |
健一さんとの電話を切った翔太君が、美咲さんに報告しています。
| 翔太 | :健一さんが、出張のお土産を持ってきてくれるってさ。 |
| 美咲 | :それでまた楽しみが増えたわね。 |
| 翔太 | :それじゃ、早速今作ったばかりのサンプルを見ながらおさらいしていこうか。 |
| 美咲 | :またそんなに張り切っちゃって。あまり気合を入れすぎると、早くバテちゃうわよ。 |
| 翔太 | :大丈夫、大丈夫。 |
さあ、これで第 6 章はおしまいです。みなさん、いかがでしたか? 今回もまた新しい単語やプログラミングのテクニックが出てきましたが、いきなりすべてを覚える必要はありません。今まで何度も言ってきたように、こういうものがあると、こういうことができるんだ、ということを体で感じてもらえれば、それで今は十分です。
ところで、最後の健一さんと翔太君の会話の中で、乱数の設定を変える、という話が出ましたね。これは皆さんも実際に試すことができます。ぜひ時間があるようなら挑戦してみてください。ただし、コードを書き換える際には注意が必要です。変更するのは、Random クラスの設定範囲の数値と、数値アップダウン コントロールの初期値と、Maximum プロパティの数値、それから意外に忘れがちなのが、Value プロパティの数値です。Value プロパティは、サンプルプログラムを最初に起動したときに表示される値です。ゲームを開始すると、コードで設定された数値アップダウン コントロールの初期値に切り替わりますが、誤解を防ぐためには、コードで設定した値と同じ値にプロパティも変更しておきましょう。もちろん、内容に合わせてコメントを変えておくことも忘れずに。コメントとコードの内容が一致していないと、あとから見直すときに混乱してしまいます。
例えば、設定範囲の値を 1 から 50 にする場合は、次のリスト 6-3-11 の数値を、
リスト 6-3-11
リスト 6-3-12 のように変更します。
リスト 6-3-12
この場合、上限の数値が変更されているので、数値アップダウン コントロールの Maximum プロパティの数値も 50 に変更しておきます。

さらに、数値アップダウン コントロールの初期値を、例えば 25 から始める場合には、次のリスト 6-3-13 の数値を、
リスト 6-3-13
リスト 6-3-14 のように変更します。
リスト 6-3-14
また、数値アップダウン コントロールのプロパティ ウィンドウを開いて、Value プロパティの数値を 25 にしておきます。

さて、次は第 7 章ですが、第 7 章で作るサンプルプログラムは、文字列を使った暗号プログラムです。今までのことを思い出しながら、ぜひチャレンジしてみてください。
|