Go to Previous Page Go to Contents Go to Java Page Go to Next Page
The Second Step of Java
 
 

Mastermind で肩ならし

Mastermind はどのようなゲーム

 
 

数字を当てよう

 
  最初のサンプルは Mastermind にしてみました。最初に Mastermind を知らない方も多いと思うので、ルールの説明をしてみましょう。

Mastermind は出題者が出した 4 桁の数字を当てるゲームです。ただし、正解には同じ数字を繰り返し使わないようにします。この数字を当てるのがゲームの目的なのですが、ただ当てるのでは難しすぎるので、答えた数字と正解に関して 2 つのヒントが与えられます。

Blow 答えた数字が正解に含まれている個数
Hit 答えた数字が正解に含まれており、場所も同じである個数

たとえば、正解が 2568 だったとしたとき、問題を解く人が答えた数字が 1265 だったとします。両方を比べると、2, 5, 6 がどちらにも含まれているので Blow は 3 になります。また、6 は両方とも 10 の桁にあるので Hit は 1 となります。もう少し例を出しておきましょう。答えた数字が 1548 の場合は、5 と 8 が正解に含まれており、また場所も同じなので、Blow が 2、Hit も 2 となります。

決められた回数内で、Blow と Hit を頼りに正解を当てれば、問題を解く人の勝ち。回数内で終わらなければ、問題を出す人の勝ちになります。

ゲームは次のように進んでいきます。

正解 4896
回数 回答 Blow Hit
1
1365
1
0
2
2465
2
0
3
2765
1
0
4
2856
2
2
5
8256
2
1
6
9856
3
2
7
8569
3
0
8
5896
3
3
9
4896
4
4 正解 !


この例では 9 回目に正解にたどりつきました。

数字以外にも色を選ぶなどの遊び方がありますが、ルール自体はまったく同じです。

まずは肩ならしということで、この Mastermind を作ってみましょう。

 

 
  ゲームは誰がやるのか  
 

すぐにでもプログラムを書きたいと思うでしょうけども、ちょっとまってください。まず、人間同士が Master Mind をするときのことを考えてみましょう。

Master Mind を行うときには正解となる数字を考えなくてはいけません。問題を出す人がこれを考えるのが普通でしょう。問題を出す人の他に、当たり前のようですが問題を解く人がいなくてはゲームが成立しません。

問題を解く人には答えた数字と正解を照らし合わせて、Blow と Hit を解く人に教えるという重要な役目もあります。

ここで Master Mind での登場人物をまとめておきましょう。

  • 問題を出す人 : 正解となる 4 桁の数字をつくる。また、回答者からの入力を受けとり、Blow と Hit を求める。
  • 問題を解く人 (回答者) : 正解を Blow と Hit を頼りに当てる

ソフトウェアで Master Mind を作るとすると、ユーザは問題を解く人となると思います。ユーザから見ると、ソフトウェアで行っていることは次の 3 つのことに見えます。

  • 正解の作成
  • 回答の入力
  • Blow と Hit を算出する (正解かどうかの判定)

正解かどうかの判定処理もあるのですが、Hit を算出するときに明らかになってしまうので、Blow と Hit を算出するほうに重点をおいてみました。

これを絵で表してみたのが図 1-1 です。この図は Unified Modeling Lagnuage (UML) [1] というオブジェクト指向のアプリケーションを設計するときに使用する記法で定義されたものの一つで、ユースケース図といいます。楕円でかかれたものがユースケース、人型で表されたものがアクタといいます。ユースケースの詳しい解説をしだすとそれだけで一冊の本 [2] になってしまうので、ここでは簡単にしか説明しません。しかし、これからユースケースは何度も出てくるので、何度も接しているうちにだんだんと概念が分かってくると思います。はじめですから、この章ではこんなものかぐらいでいいと思います。また、UML を記述する専用のソフトもあります。

ユースケースは何らかの処理を表していると思ってください。楕円の下に書いてあることがその処理を表しています。図 1-1 では「正解の作成」、「回答の入力」と「Blow, Hit の算出」が処理にあたります。

アクタはユースケースに対して何らかの関係を持ちます。通常、アクタはコンピュータを操作するユーザになりますが、アプリケーション間処理を示すときなどはアクタがアプリケーションやシステムになることもあります。

アクタとユースケースに何らかの関係がある場合、アクタとユースケースは線で結ばれます。図 1-1 ではアクタが問題に答えることになります。「Hit, Blow の算出」ユースケースはこの答えと正解から Blow と Hit を算出します。

同様にユースケース間に関係があるときも、線で結ばれます。入力を行ったら、回答から「Blow, Hit の算出」を行う必要があります。この場合、「回答の入力」ユースケースが「Blow, Hit を算出」ユースケースを使用するということになります。

このユースケース図には先ほどの登場人物がすべて入っていることはお分かりかと思います。回答者はそのままアクタになり、問題作成者は「正解の作成」、「回答の入力」と「Blow, Hit の算出」ユースケースになります。

Use Case of Mastermind
図 1-1 Mastermind のユースケース図
 
  Mastermind をやってみよう  
 

登場人物もそろったので、Mastermind をやってみましょう。ゲームの流れは次のようになるのではないでしょうか。

  1. 問題作成者が正解を作る
  2. 回答者が回答する
  3. 回答と正解を比較して Blow, Hit を算出する
  4. Blow, Hit を回答者に示す
  5. Hit が数字の桁数と同じなら正解
  6. 再び、2 に戻る

回答者が決められた回数内で正解にたどり着けば、勝ち。回数内にたどり着けなければ負けとなります。 

ところで、それぞれの動作は誰が行っているのでしょうか。日本語は主語が略されることが多いのですが、ソフトウェアにとっては誰が何をしたかはっきりしないと記述することができません。また、動作を行う対象、誰に対して行うかということも明確にしておく必要があります。1 から 5 までの動作は主語がはっきりしていますが、6 の動作はどうでしょうか。このままではよく分からないですね。もう少し具体的に書いてみましょう。

  1. 問題作成者が正解を作る
  2. 問題作成者は回答者からの回答を待つ
  3. 回答者は問題作成者に回答を行う
  4. 問題作成者は回答と正解を比較して Blow, Hit を算出する
  5. 問題作成者は Blow, Hit を回答者に示す
  6. 問題作成者は Hit 数と桁数を比較して、回答が正解かどうかを調べる
  7. 問題作成者は回答が正解であれば、回答者に示す
  8. 問題作成者は回答が正解であれば、ゲームを終わらせる
  9. 問題作成者は回答が不正解であれば、再び回答者からの回答を待つ

ちゃんと主語と動作の対象まで書くと、日本語としてはちょっと変ですね。このような箇条書きでは動作の流れを厳密にあらわすことは難しいということがお分かりかと思います。

それでは動作をどのようにあらわしましょう。先ほどのユースケース図を定義している UML には、動作を表すための図も規定されています。それがシーケンス図とコラボレーション図です。この 2 つの違いは、シーケンス図が時間的な流れを中心に記述するのに対し、コラボレーション図は登場人物間のやり取りを中心に記述している点です。

ここではシーケンス図を用いて Mastermind の流れを表してみましょう (図 1-2)。

Sequence of Mastermind
図 1-2 Mastermind のシーケンス図

図の一番上にかかれている四角が登場人物をあらわしています。ここでは問題作成者と回答者の 2人です。この四角から下に向かう点線上に登場人物が行う動作を記述していきます。動作を行っているときは線上に細い四角を書きます。点線は時間軸を表しており、下に行くほど時間が経過することをあらわしています。登場人物間でやり取りを行うときには矢印で線と線を結びます。オブジェクト指向ではこのようなやり取りをメッセージセンディングといい、矢印はメッセージを投げることを意味します。自分自身に向かっている矢印線は自分に対してメッセージを投げていることを示しています。

図 1-2 の説明をしていきましょう。まず、問題作成者が正解を作成します。動作を表す四角が何も無い部分は登場人物はなにもしないことを表しているので、回答待ちの状態にあることを示しています。

回答者は問題作成者に回答を示します。問題作成者は 3. と 5. でそれぞれ Blow, Hit の算出、正解かどうかのチェックを行います。そして、それぞれの結果を回答者に示します。

ところで、シーケンス図では表せないものがあります。それはループと分岐です。

たとえば、箇条書きで示した動作では一番最後に「再び回答者からの回答を待つ」とありますが、これは 2 から 9 の動作をループすることを示しています。しかし、これをシーケンス図に表すことはできないので、ループの中の部分だけをシーケンス図に表しました。

また、同様に箇条書きの動作の 7 と 8 は「もし XXXX であれば、YYYY を行う、ことなれば ZZZZ を行う」という分岐に相当します。Java でいえば if 文に相当します。ところが、これもシーケンス図で書くことはできません。

このため、アプリケーションのすべての動作を 1 つのシーケンス図で書くことはしないで、いろいろな場面で、条件付けを行ってシーケンス図を記述することになります。たとえば、図 1-2 では問題を作成して初めての回答に関しての処理の部分に関してシーケンス図を記述しています。回答が正解だとゲームを終了させる部分が入ってくるのですが、ここでは記述していません。ということは、このシーケンス図では回答が正解ではないことを条件としています。

アプリケーションの規模が大きくなればなるほど、さまざまな場面や条件があるので、それにつれて記述するシーケンス図も膨大になっていきます。シーケンス図を描くのは結構厄介なのですが、実際にソースコードを記述するときや、デバッグをするときにシーケンス図があるとないとでは作業効率がとても異なります。始めは面倒かもしれませんが、後々のためになるので、手書きでも何でもいいですから、ぜひ描いてみてください。

この節のまとめを次に示しました。

  • 登場人物をすべて洗いだそう
  • 登場人物の役割を明確にしよう
  • 動作を表すときには主語と述語がきちんと分かるようにしよう
  • 登場人物間のやり取りを中心にして、動作を表してみよう

まとめの前半 2 つを行うためにユースケース図、後半を行うためにシーケンス図を利用しました。

注)
[1] 参考文献として
  • UML ユーザガイド Grady Booch 著、ピアソン・エデュケーション、ISBN4-89471-155-9
  • UML レファレンス http://www.ogis-uml-university.com/reference/index.htm
  • かんたん UML オージス総研 著 千藤雅弘 監修、翔泳社、ISBN4-88135-759-X
などがあります
[2] ユースケースの適用:実践ガイド Gary Schunider/Jason Winters 著、ピアソン・エデュケーション、ISBN4-89471-186-9

(Aug. 2000)

 
 
Go to Previous Page Go to Contents Go to Java Page Go to Next Page