マインスイーパーを使った mvc モデル の有効性に...

27
1 マインスイーパーを使った MVC モデル の有効性について 日付:1月 15 所属:経営情報学部経営情報学科 学籍番号 氏名:5109224 平田 滉陽 5109172 寺杣 直也

Upload: others

Post on 19-Feb-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

1

マインスイーパーを使った MVC モデル

の有効性について

日付:1月 15日

所属:経営情報学部経営情報学科

学籍番号 氏名:5109224 平田 滉陽

:5109172 寺杣 直也

Page 2: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

2

-目次-

第1章 はじめに・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・p2

第2章 関連研究・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・p4

第1節 マインスイーパーとは・・・・・・・・・・・・・・・・・・・・・・・p4

第2節 C#とは・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・p5

第3節 オブジェクト指向とは・・・・・・・・・・・・・・・・・・・・・・・p6

第4節 コーディング規約とは・・・・・・・・・・・・・・・・・・・・・・・p7

第5節 MVCモデルとは・・・・・・・・・・・・・・・・・・・・・・・・・・p8

第3章 作成物の紹介・・・・・・・・・・・・・・・・・・・・・・・・・・・・p9

第1節 マインスイーパーの作成・・・・・・・・・・・・・・・・・・・・・・p9

第2節 Modelについて・・・・・・・・・・・・・・・・・・・・・・・・・・p11

第3節 Viewについて・・・・・・・・・・・・・・・・・・・・・・・・・・p14

第4節 Controlについて・・・・・・・・・・・・・・・・・・・・・・・・・p17

第4章 考察・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・p21

第1節 コマンド入力の構文分析技術・・・・・・・・・・・・・・・・・・・p22

第2節 本システムの GUI化・・・・・・・・・・・・・・・・・・・・・・・p25

第5章 まとめ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・p22

参考文献

謝辞

Page 3: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

3

第1章 はじめに

近年、情報化社会が進みパソコンや、多機能な携帯電話、ゲーム機などインターネット

に関わる情報端末が多く利用されている。パソコンであれば Webを閲覧して様々な情報を

得るが、最近の携帯電話はパソコンと同等程度の高機能な機種も存在する。ゲーム機のプ

レイステーション3、PSP、PSVITA、ニンテンドー3DS等はインターネットを通じて、全国

の誰とでもオンライン通信やインターネットを繋ぐ事が出来る。しかし、ゲーム機等の携

帯端末上で動作するオンラインゲーム等の仕組みについては理解をせずに使用している場

合がほとんどである。大まかな仕組みは、プログラムをプログラミング言語で記述して、

コンパイル後実行ファイルを起動する方法である。利用されるプログラミング言語は様々

な種類があり、設計方法もそれぞれのプログラミング言語によって異なる。そこで私達は

C#というプログラミング言語を用いて、初歩的なコンピューターゲームの作成を行う。こ

れによって、プログラミングにおける MVCモデル設計手法の基本構造とその有効性を理解

することを目指す。

今回作成するゲームプログラムはパソコンで動作するマインスイーパーである。作成理

由としては、比較的作成が簡単な事、MVCモデルを理解しやすいと考えたからである。次に

プログラミング言語に C#を選んだ理由を述べる。私達は普段の日常生活で自然に前述した

情報端末を触れているが、中身であるプログラムに触れたことが無かった。そのためプロ

グラムの知識や技術は私達には無く、初めから高度なプログラムを作ることは出来ない。

そこで、私達は VisualStudio.netいうソフトがプログラミング初心者向けであることを知

り、そのソフトで C#を使用することが初心者である私達にも理解しやすいと考え、この言

語で作成することを決定した。C#の詳細については第2章関連研究の第2節で解説する。

第3章では作成するゲームプログラムであるマインスイーパーの詳細、そこで用いた MVC

モデルの Model、View、Controlを述べ、第4章では実際に作成した際のコマンドやその他

のソースコードを解説し、考察と今後の課題を述べる。

Page 4: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

4

第2章 関連研究

本章では、マインスイーパーの作成にあたって、まず一般的なマインスイーパーを紹介

する。さらに、マインスイーパーを実現するための C#プログラミング言語、設計手法、そ

のほかのプログラミング規約等を説明する。

第1節マインスイーパーとは

マインスイーパー(Minesweeper)とは、1980年代にロバート・ドナー氏が開発した、地

雷原から地雷を撤去することを目的とした一人用コンピューターゲームである。[2]1990

年代には Windows版に移植し、その他にも Linuxの GNOMEや KDEといったそれぞれのコン

ピュータプラットフォームに書き直されている。マインスイーパーの実装は比較的難易度

が低く、C言語、C++、C#といった言語の他に Pascal言語を用いていることもある。マイン

スイーパーの実装で最も有名なのは Microsoft Windowsのもので(図1参照)、ゲーム画面

が正方形のマスで敷き詰められたフィールドで構成されており、3つのサイズで難易度の

調整をしているものである。マインスイーパーは年々進化しており、最初のマインスイー

パーは盤面がグレーとシンプルなものであったが、Windows Meでは、wimine.iniというフ

ァイルに sound = 3と書くことでビープ音を利用しゲームオーバーやクリアを再現した。

Windows2000では普通の音源が使われることになり、Windows Vistaでは盤面がグレーから

カラフルなものに変わり、3D化や地雷を踏むと周囲を誘爆するエフェクトがつくようにな

り、最近の OSである Windows8では初期のマインスイーパーと比べ劇的に進化している(図

2参照)。ゲームのルールはプレイヤーが正方形のマスに対し、クリックすることでフラッ

グを立てる、マスを開くといったアクションによってゲームを進め、指定された地雷のマ

ス以外の全てのマスを開けば勝ちとなる。基本操作は、左クリックでマスを開くとそこが

空白か、数字か、地雷かで表示される。空白であるならそのマスの周囲は何もないことを

示し、数字があれば、そのマスの周囲に数字分の地雷があることを表している。地雷であ

ればゲームオーバーとなる。右クリックではフラッグを立てることができる。フラッグは

地雷があると予想したマスに対し、旗を立てることでその地雷をマークしたことになる。

全ての地雷にフラッグを立てれば除去完了となり、ゲームクリアとなる。

図1 Windows 版のマインスイーパー

出所)http://gaagle.jp/gagazine/print.php?kiji_id=4778

Page 5: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

5

第2節 C#とは

C#とはプログラミング言語のひとつでオブジェクト指向と設計手法を実現するための言

語である。C言語をもとにマイクロソフトが開発した言語であり開発には、TurboPascalや

Delphi を開発したアンダース・ヘルスバーグも設計している。2002年にマイクロソフトが

発表し、マイクロソフトが提供する.NET Framework上で動く言語であり、オブジェクト指

向という考え方に基づいて作られている。2004年に C#2.0、2007年には C#3.0とバージョ

ンアップした。C#の主な特徴は、基本的な書式が C言語風になっており、C++Builderの独

自拡張構文と近い内容になっている。自動ボックス化、構造体、デリゲート、プロパティ、

カスタム属性、多次元配列、可変長引数などの機能を持つ他に、JAVAと同じ様に大規模ラ

イブラリや、CPU設計に依存しない実行形態、JITコンパイルによる実行の高速化等が実現

されている。言語仕様においては、言語や C++から多くの改良点があり、全てのメソッドと

メンバはクラスの一部として宣言しなければならない。C#には bool型が存在し、if文や

while文のような条件を取るステートメントには bool型の式を与え、bool型と整数の可換

を禁止する仕様になり、Cや C++での整数型の相互の変換によるミスを防げるようになった。

C#は他の言語である C++と比べるとメモリ管理の自動化によりコーディングが手軽になり、

JAVAと比較するとより現実的でどんな処理も容易にかけるというそれぞれの言語の短所を

補い、長所を集めた言語である。

図2 Windows8版

出所)http://ggsoku.com/2012/08/windows8-screenshots/

Page 6: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

6

第3節 オブジェクト指向とは

ソフトウェアの設計や開発における考え方のひとつがオブジェクト指向設計方論である。

それ以前に一般的にであった構造化設計手法は関数、構造体、ライブラリを利用するが、

オブジェクト指向では物理的な物をクラスとして扱うところが大きく異なる。オブジェク

ト指向では、現実世界でどのように動くかをモデリングし、役割分担を明確に定義し、そ

れに沿って作成していく考え方である。オブジェクト指向でのプログラミングのメリット

は、データとデータ操作一体化させたオブジェクトと呼ばれる単位を組み合わせてプログ

ラミングするため、部分的な再利用ができるということである。

次に、オブジェクト指向の中のクラスとインスタンスについて説明する。クラスとはオ

ブジェクト指向のプログラミングおけるオブジェクトの雛型を定義したものであり、一般

的には抽象的なものを定義する。図3で説明すれば、犬の定義を決めたものがクラスであ

る。クラスには2つ定義しなければならないことがあり、クラス自身の情報を表す「属性」

と、クラスの動作を表す「メソッド」がある。図3の場合、犬というものは名前と生年月

日があり、鳴く、エサを食べる、寝るといった動作をするものが犬であるというクラス定

義している。インスタンスとは抽象的で雛型であるクラスに対し、具体的な数値や名前を

持つ、実体のあるデータのことである。図3ではタロー、ポチ、マルといった名前や生年

月日が具体的に決まっており、共通するメソッドを持っている犬がインスタンスであると

言える。インスタンスは一つのクラスから複数作ることが可能で、それぞれ違った名前や

数値を持つことが出来る。定義したものの雛型であるクラスはプログラムの中で実際に扱

われず、具体的な実態を持つインスタンスが扱われる。

図3 クラスとインスタンス

クラス

-名前

-生年月日

+鳴く()

+餌を食べる()

+寝る()

属性

メソッド

タロー:犬 名前=タロー

生年月日=1990/12/25

ポチ:犬 名前=ポチ

生年月日=1993/10/13

マル:犬

名前=マル

生年月日=2010/6/23

インスタンス

Page 7: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

7

第4節 コーディング規約とは

コーディング規約とは、プログラムを作る際のルールである。[1]プログラムを分担し

て作る際に、それぞれが自由に作った場合、一つのプログラムとしての統一がとれない。

同じ仕様でもプログラムの書き方が違うことになり、プログラム変更する際の可読性が悪

くなり、結果として不具合が生じる。このミスを事前に防ぐためコーディング規約という

ルールを定め、ソースコードに統一性を持たせ読みやすさや保守性を高める。実際にマイ

ンスイーパーを作成するときに参考にした JAVAコーディング標準を、図4に示す。

① public クラスはそのクラス名をファイル名にして、メソッド名や変数名から、意味や役

割が分かるようにする。また、パブリックなクラス名は大文字小文字の区別も含め、コ

ンパイラの規則によりファイル名と同じでなければならない。

② クラスの定義開始の“{”は改行しない。コードがどこまでそのクラスのものかを分か

りやすくするためである。

③ メソッドの定義の開始の“{”も、クラスの時と同様に見やすくするため改行しない。

④ if や while文等のキーワードと“(”の間はスペースを1つ空ける。ただし、public void

pushの後に続く(object item)の様なメソッド名の後の“(”はスペースを入れずに、<=

といった演算子の両側にスペースを入れる。

⑤ コード毎の“{”と“}”は必ず段落を合わせる。字下げは1TAB = 4SPACE。

⑥ コードの条件式のミスを防ぐため Ifや elseの文での“{”、“}”の位置を注意する必要

がある。

① public class stack { ←②

public void push(object item) { ←③

if(itemCapacity <= itemCount){←④

// …

}←⑤

else{ ←⑥

// …

}

}

}

図4 コーディング規約の例 名前や書き方について

Page 8: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

8

次に、変数の宣言と初期化について説明する。図5のローカル変数 iと jをこのままの

状態で宣言した場合、初期化されていないためコンパイル時に警告メッセージが表示され

る。変数に最初の値をあらかじめ代入しておくことを初期化と言い、警告を防ぐため変数

の宣言時には必ず初期化しなければならない。この場合、ローカル変数 i、jは値型の integer

で宣言されているため、図6の様に数値を入れて初期化すると良い。

第5節 MVCモデルとは

MVC モデルとはプログラムを作る際に、それぞれ Model、View、Controlとなるべく相互

の影響を受けないように役割を分担させて設計手法のことで、頭文字から名前を取ってい

る。図7を使って Model、View、Controlのそれぞれの役割を説明する。

良い例 void f (int start){ int i = 0 , j = 0;

図6初期化した変数の宣言

悪い例

void f (int start){ int i, j;

図5 変数の初期値無しの宣言

ユーザー

操作

プログラム

Control

Model

View 表示

出力依頼

処理依頼

処理結果

図7 MVC モデルの構造

Page 9: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

9

Modelは Controlから受け付けた操作を Model内にあるデータベースを元に処理を行い、

その結果を View に渡すといったアプリケーションの要の部分を担当している。図7ではユ

ーザーがプログラムを操作した時に、ユーザーが行ってほしい処理を、Controlを通じて処

理をするという役割を担っている。Viewは名前の通り、プログラム内部の処理を出力する

部分を担当している。ユーザーは Viewで出力された画面を見て操作を行うが、プログラム

内部では Viewが画面の表示で受付の役割を担い、Controlが処理を Modelに依頼するため

View自身は処理を行うことはしない。Controlはプログラムを制御する部分を担当してい

る。図7ではユーザーから受けた操作を Modelに処理するように依頼する役割と、ユーザ

ーから受けた操作を Viewに出力依頼をするといった、Viewと Modelをコントロールする役

割を担っている。

MVC モデルのメリットは Model、View、Controlが連動して動いているが、それぞれが独

立した役割を持っているので仕様変更が容易であることである。例えば、出力を担う View

をユーザーがもっと見やすくなるように変更しても、出力を担当しているのは Viewのみな

ので Modelや Controlに影響を受けにくいので変更部分のみに注力することが出来る。こ

れは View以外にも言えることであり、Controlなら他の処理を追加したり、Modelのデー

タベースを最適化して構造を変えたりしてもそれぞれの独立性が高いため、影響を受けに

くい設計手法であるといえる。

Page 10: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

10

第3章 作成物の紹介

第1節 マインスイーパーの作成

MVC モデルを用いて作成したマインスイーパーの紹介をする。本プログラムは一般的なマ

インスイーパーのクリックだけでゲームを進める操作に対し、あらかじめ決められている

コマンドを入力することによってゲームを進行する。本プログラムは C#言語で作成し、コ

ンソール画面で起動する。設計時に MVCモデルという設計手法を用いて、Model、View、

Control とプログラムを役割ごとに分担し、仕様変更がし易すい様に作成した。基本的なゲ

ームの流れは push、flag、checkの三つのコマンドとゲーム内のマスの x軸、y軸の値を指

定することでゲームを進めていき、コマンドに対する盤面上のマスの処理で地雷がどの位

置にあるかを予想し全ての地雷に旗を立てることでゲームクリアとなり、pushコマンドに

よって地雷のマスを開くとゲームオーバーとなる。本プログラム内のコードの説明は Model

が第2節、View は第3節、Controlは第4節で説明する。

Page 11: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

11

図8は本プログラムのマインスイーパーのフローチャートである。各コマンドは switch

文で case毎に分け、多分岐させることでユーザーからのコマンド入力に対応している。push

というコマンドは指定したマスを開き、flagは指定したマスに地雷があると予想した時に

使用するコマンドでマスを開かずに旗を立てるという処理を行う。checkのコマンドは flag

のコマンドと同様に地雷があると予想した時に使う。flagコマンドとの違いは、flagは周

囲のマスから予測してそのマスに地雷があると確定した際に使うコマンドである。checkは

マスに地雷があると予想して、旗を立てる代わりにクエスチョンマークを立てて目印の役

割を果たすコマンドである。ゲームを進めるためのコマンドはあらかじめ Controlクラス

で設定されているため、それ以外のコマンドは「対応していない操作です」と表示される。

ゲームのループは全ての地雷に旗を立てるか、地雷を踏むとループを抜ける。

対応していない操作です。と表示

データの読み込みと初期化

ゲームクリア

ゲームオーバー

マスに旗を立てる

地雷踏んだ?

マスを開く

コマンド入力

マスに?を描画する

全ての地雷に旗を立てた?

コマンド:push

コマンド:check

コマンド:flag

No

No

Yes

Yes

その他のコマンド

図8 マインスイーパーのフローチャート

Page 12: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

12

第2節 Modelについて

Model は本プログラムの地雷の配置や数の設定、旗の数の設定の他に Controlクラスによ

って受けたコマンドに対してどう処理を行うかという設定を決め、その処理の結果を View

に渡す役割を担っている。Modelクラスの特徴は Model自身に描画をするための処理やユー

ザーからコマンドを入力してもらうための処理は無く Viewクラスと Controlクラスが正常

に稼働するための設定を作り、受けた処理を結果として反映する点が特徴である。また、

ユーザーから受けた pushコマンドや checkコマンドの処理は第3節の Cells Statusとい

うクラスを用いて処理を行っている。

マインスイーパーの盤面は縦 10マス横 10マスとなっており、行番号2の Cellsによっ

て設定している。randomは図 10 の SetMinesメソッドで使う関数であり、この関数を使う

ことで乱数を使うことが出来る。行番号7と8の for文中の変数 y、xは盤面上の縦と横の

マスでこのコードによって盤面上を0クリアし初期化を行う。地雷の数は MineNumberで設

定し、数値を変更することで地雷の数の増減を決めることが出来る。マインスイーパーは、

地雷に対して全ての旗を立てればゲームクリアとなるので、ModFlagは地雷に対して立てた

旗のみに対応するため、地雷の残りの数が旗を立てなければならない本数となる(図9参

照)。

1:public Model() {

2: Cells = new int[ 10, 10 ];

3: random = new Random();

4: Initialize();

5:}

6:public void Initialize() {

7: for ( int y = 0 ; y < Cells.GetLength( 1 ) ; y++ ) {

8: for ( int x = 0 ; x < Cells.GetLength( 0 ) ; x++ ) {

9: Cells[ x, y ] = 0;

10: }

11:}

12:MineNumber = 15;

13: ModFlag = -1;

14:}

図9 盤面のコンストラクタと地雷と旗の数のコード

Page 13: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

13

次に地雷設置のコードについて説明する。地雷は図9で設定された地雷の数に達するま

で while 文で盤面上にランダムに配置される。ランダムに地雷を配置するため、重複しな

いように if 文を使い、既に地雷が置かれているセルはスルーするようにした。マインスイ

ーパーは地雷がどのマスにあるか推測する必要があるため IncrementCellsで地雷が設置し

た際に周囲のマスに地雷がある場合は数値を描画するようになっている。

IncrementCellsは地雷を設置した際に地雷の場所を推測するための数値を表示させるた

めの処理を行っている。行番号2の for文の中の変数 mine_xと行番号3の mine_yに数値

を入れることで地雷の周囲のマスに数値を入れ、if文のコードで盤面上のマスの境界値の

1:public void SetMines() {

2: int count = 0;

3: while ( count < MineNumber ) {

4: int x = random.Next( 0, 9 );

5: int y = random.Next( 0, 9 );

6:if ( Cells[ x, y ] == ( int ) CellsStatus.MineCheck ) {

7: continue;

8: }

9:Cells[ x, y ] = ( int ) CellsStatus.MineCheck;

10: count++;

11: IncrementCells( x, y );

12: }

図 10 地雷設置のコード

1:public void IncrementCells( int mine_x, int mine_y ) {

2: for ( int y = mine_y - 1 ; y <= mine_y + 1 ; y++ ) {

3: for ( int x = mine_x - 1 ; x <= mine_x + 1 ; x++ ) {

4: if ( 0 <= x && x <= Cells.GetLength( 0 ) &&

5: 0 <= y && y <= Cells.GetLength( 1 ) ) {

6: if ( Cells[ x, y ] == ( int ) CellsStatus.MineCheck ) {

7: continue;

8: }

9: Cells[ x, y ]++;

10: }

12: }

13: }

14:}

図 11 地雷の周囲のマスに数値を表示するための

Page 14: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

14

チェックを行っている。また、地雷には数値を入れることは出来ないのでセルの中身が

CellsStatus.MineCheckだった場合は数値が描画されないようになっている(図 11参照)。

Controlクラスがユーザーから受けた入力に対して行番号1から15はコマンドの処理を

行っている。pushコマンドが入力されるとこのコードで指定されたマスに対しCellsStatus

クラスにあるCellsStatus.PushCheckを使って処理を行う。pushコマンドによって開かれた

マスは数値か地雷でしかないので、行番号5から行番号6までのif文で旗が立てられない

ようになっている。旗を立てる処理を行われるとModFlag--;で旗を減らす処理が行われる

(図12参照)。

1:public void Push(int x, int y) {

2: Cells[ x, y ] = Cells[ x, y ] | ( int ) CellsStatus.PushCheck;

3:}

4:public bool Check(int x, int y, CellsStatus status ) {

5: int flag = Cells[ x, y ] & ( int ) CellsStatus.FlagMask;

6: if (flag == (int) CellsStatus.PushCheck){

7: return false;

8: }

9: int tenpcell = Cells[ x, y ] & ( int ) CellsStatus.NumMask;

10: Cells[ x, y ] = tenpcell | (int) status;

11: if (flag ==(int)CellsStatus.FlagCheck){

12: ModFlag--;

13: }

14: return true;

15: }

図 12 各コマンドの処理

Page 15: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

15

第3節 Viewについて

View は本プログラムのコンソール画面上でユーザーから入力を受け、その受けたコマン

ドによって盤面上のマスや旗を描画する役割を担っている。Viewクラスの特徴は、あらか

じめ盤面上のマスや旗などの値をユーザーのコマンド入力を受けて、どういった処理を行

うかという設定を決めている CellsStatus クラスのコードを Viewクラス内部のコードで

使用している(図 13 参照)。

CellsStatus クラスはマインスイーパーの盤面上のマスや、コマンド入力によってマス

の状態を変化させる処理をするための設定を決めているクラスである。このクラスの特徴

は、マスクをすることでマスが各コマンドで特定の処理を論理積の計算で実行することで

ある。論理積の計算は2進数で行われており、コードでは整数に置き換えられている。例

えば、NonePushCheck = 0なら盤面上のマスは何も押されていない状態であり、整数0、

二進数では 000000で表現される。この NonePushCheck=0の状態のマスに pushコマンドが

入力されると二進数では 110000 となり PushCheck = 48の処理を行う。CellsStatus クラ

スの各コードは、FlagMaskは flagコマンドが入力されていない状態のマスク、NumMaskは

マスが開かれた時に数値を表示するためのマスク、flagCheck、QuestionCheck、PushCheck

はそれぞれ flag コマンド、checkコマンド、pushコマンドが入力された時の処理を行うコ

ードである。MineCheckは地雷がマスにある状態で MineFlagCheck、MinePushCheckは地雷

があるマスに旗が立っている状態と地雷があるマスが押された状態を示している。

enum CellsStatus {

1: FlagMask = 48, // 110000

2: NumMask = 15, // 001111

3: NonePushCheck = 0, // 000000

4: FlagCheck = 16, // 010000

5: QuestionCheck = 32, // 100000

6: PushCheck = 48, // 110000

7: MineCheck = 9, // 001001

8: MineFlagCheck = 24, // 011001

9: MinePushCheck = 57, // 111001

図 13 CellsStatus クラスのコード

Page 16: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

16

次に盤面上のセルが押されている状態、押されていない状態の処理を行うコードの説明

をする。コンソール画面上に Viewは盤面とユーザーの入力を受け付ける場所を描画する役

割を担っており、盤面やセルが入力されたコマンドの処理によって変わる描画に対応して

いる。描画の処理は pushコマンドによってセルが押されている状態と押されていない状態

とで別れている(図 14参照)。セルが押さていない状態の描画と押された状態の描画の処理

は、pushのコマンドが入力された場合とそれ以外のコマンドが入力された場合とで分かれ

ている。

図 14の行番号1の Console.SetCursorPositionでコンソール画面上に描画する盤面の位

置を決めている。for文の中にあるローカル変数 yと xは縦にマスを 10個、横にマスを 10

個描画し、マインスイーパーの盤面は図 15のようになる。

図 14 セルの状態を変更する処理のコード

1: Console.SetCursorPosition( 0,0 );

2: int[ , ] Cells = model.GetCells();

3: for ( int y = 0 ; y < 10 ; y++ ) {

4: for ( int x = 0 ; x < 10 ; x++ ) {

5: int flagValue = Cells[ x, y ] & ( int ) CellsStatus.FlagMask;

6: if ( flagValue == ( int ) CellsStatus.NonePushCheck ) {

7: Console.Write( "□" );

8: }

9: else if ( flagValue == ( int ) CellsStatus.FlagCheck ) {

10: Console.Write( "P" );

11: }

12: else if ( flagValue == ( int ) CellsStatus.QuestionCheck )

{

13: Console.Write( "?" );

14: }

15: else if ( flagValue == ( int ) CellsStatus.PushCheck )

{

16: int number = Cells[ x, y ] & ( int )

CellsStatus.NumMask;

17: if ( number == ( int ) CellsStatus.MineCheck )

{

18: Console.Write( "○" );

19: }

20: else if ( 0 <= number && number <= 8 ) {

21: Console.Write( Strings.StrConv( number.ToString(),

StrConv.Wide ) );

22: }

23: else {

24: Console.Write( "E" );

図 15 マインスイーパーの盤面

Page 17: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

17

行番号6から 14はセルが押されていない時の処理で、盤面上のマスがどの処理もされ

ていない場合は□を表示する処理を行い、flagコマンドを入力し、マスに対し旗を立てた

場合は P、マスに地雷があるかどうか確定せずに予想した際に使われる checkコマンドの処

理で?を表示する。盤面上がどのコマンドも実行されていない場合は、最初は□を表示す

る様になっている。図 16、図 17はそれぞれマスに旗を立てた状態と?を立てた状態を表し

ている。

Push コマンドが入力された場合、セルの押されている状態はセルの中身によって決まる。

セルが押された時、行番号 17でまず地雷かどうかをチェックする。もし地雷ならば図 19

の様に○を表示する。図 18の様に地雷でなければマスに数値を描画する。行番号 21のコ

ードにある StrConv.Wideはマスに描画する際に全角に変換する。数値以外のエラーが出るような

場合は Eと表示する。

図 18 pushコマンドで数値が表示されている状態

図 17 checkコマンドが入力された状態 図 16 flagコマンドが入力された状態

図 19 pushコマンドで地雷が表示されている状態

Page 18: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

18

第4節 Controlについて

Control は本プログラムの Viewクラス、Modelクラスを制御する役割とユーザーから入

力されるコマンドを構文解析することで特定のコマンド以外を受け付けないようにする役

割を担っている。Controlクラスの特徴は入力されたコマンドを Modelクラスで設定した仕

様に沿って処理し、Viewクラスに出力してもらうように依頼するといった、名前の通りコ

ントローラーの役割を担っているため、それぞれの thisポインタを使ってクラスを呼びだ

している。図 20で他のクラスを呼びだしているコードの説明を行い、図 21、図 22でゲー

ムループと構文解析のコードを示す。図 23ではそれぞれのコマンドに対する処理の実行に

ついて説明する。

Controlクラスには viewと model というクラス変数がある。行番号 10の Controlクラス

の this.view、this.modelは SetView()メソッドや SetModel()メソッドの中にも viewと

modelという変数があるため、ただ viewとコードを書くとどちらの変数か判別できないの

で、クラス変数の Viewであることを明確にするために thisをつけて記述している(図 20

参照)。

1: class Control {

2: private View view;

3: public void SetView( View view ) {

4: this.view = view;

5: }

6: private Model model;

7: public void SetModel( Model model ) {

8: this.model = model;

9: }

10: public Control( Model model, View view ) {

11: this.view = view;

12: this.model = model;

13: }

図 20 各クラスの呼びだしを行うコード

Page 19: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

19

次にゲームループについて説明する。GameLoopメソッドでは model.SetMines()によって

地雷が配置され、while文でゲームが終わるまでループされており、Regexでコマンドと参

照するための文字列を設定し、ユーザーから入力された文字を View.UserInput()で習得し、

bool syntaxOK = SyntaxAnalysis( utumoji )でユーザーが入力した文字の構文解析を行う。

構文が合っていれば処理を続行し違っていれば処理をスルーしループの先頭に戻るように

なっている(図 21参照)。

このゲームループの特徴は Regex を使った構文解析である。Regexとは正規表現の事で

「0-9」や「a-z」などのコードを組み合わせることによって文字列の参照や置換を行う

事が出来る。ゲームループ中はこの regexによって本プログラムのコマンドとユーザーの

文字の入力が一致するかどうか判断を行っている。

ゲームをクリアまたはゲームオーバーするとゲームループを抜ける(図 22参照)地雷を

踏んでゲームオーバー、もしくは旗を全て立てるとクリアし、図 23の様に表示される。パ

ソコン上のキーを押すとコンソール画面が閉じゲームが終了する。

1:public void GameLoop(){

2: model.SetMines();

3: while (true){

4: Regex rx = new Regex( @"^[0-9a-z]+" );

5: view.Paint();

6: String utumoji = view.UserInput();

7: bool syntaxOK = SyntaxAnalysis( utumoji );

8: if ( !syntaxOK ) {

9: utumoji = "";

10: }

図 21 ゲームループのコード

1: if ( model.CheckClear() ) {

2: Console.WriteLine( "おめでとうさん" );

3: break;

4: }

5: if ( model.GheckGameOver() ) {

6: Console.WriteLine( "残念" );

7: break;

8: }

図 22 ゲームループが抜けた時のコード

Page 20: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

20

本プログラムにはコマンドが正しく入力されているかどうかを確かめる構文解析のコ

ードがある。SyntaxAnalysisは Regexを使った文字列を参照して構文解析を行う。本プロ

グラムのコマンドは push、flag、checkと三つのコマンドがあり、各コマンドと各マスの

数値を入力し、ゲームを進めていくためそれ以外の文字やコマンドは入力しても「対応し

ていない操作です。」と表示される(図 25参照)。format文はそれぞれのコマンドと0か

ら9の任意の数字を二つの組み合わせのみ構文が一致するようになっている(図 24参照)。

図 24 構文解析のコード

1:private bool SyntaxAnalysis( string line ){

2: string[] format = new string[ 3 ];

3: format[ 0 ] = @"^push [0-9]+ [0-9]+$";

4: format[ 1 ] = @"^flag [0-9]+ [0-9]+$";

5: format[ 2 ] = @"^check [0-9]+ [0-9]+$";

6: for ( int i = 0 ; i < format.Length ; i++ ){

7: if ( Regex.IsMatch( line,format[i])){

8: return true;

9: }

10: }

11: return false;

12: }

図 23 左がゲームクリアの状態で右がゲームオーバーの状態

図 25 コマンドが指定されたコマンド以外の状態

Page 21: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

21

次に処理の実行のコードについて説明する。それぞれのコマンドは switch文で case毎

にコマンドを分け、ユーザーから入力されたコマンドに従って処理を行う(図 26参照)。

また、コマンドは Splitで分割されており、コマンドとマスを指定する数値の間にスペー

スを入れなければ正確にコマンドを処理せずにスルーされる(図 27参照)。

1:string[] select = utumoji.Split( new char[]{ ' ' } );

2:int x = -1;

3:int y = -1;

4:switch ( select[0] ) {

5: case "push":

6: x = int.Parse( select[ 1 ] );

7: y = int.Parse( select[ 2 ] );

8: model.Push(x,y);

9: break;

10: case "flag":

11: x = int.Parse( select[ 1 ] );

12: y = int.Parse( select[ 2 ] );

13: model.Flag(x,y,CellsStatus.FlagCheck);

14: break;

図 26 処理の実行のコード

15: case "check":

16: x = int.Parse( select[ 1 ] );

17: y = int.Parse( select[ 2 ] );

18:model.Check(x,y,CellsStatus.QuestionCheck);

19: break;

20: default:

21: Console.WriteLine( "対応していない操

作です。" );

22: break;

図 27 コマンドが対応していない状態

Page 22: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

22

第4章 考察

第1節 コマンド入力の構文分析技術

本プログラムを作成するにあたって、コマンドを参照するため正規表現を使用した。正

規表現とは、通常の文字と特殊文字(メタキャラクタ)を組合せて表記される文字列の検

索と参照に優れている方式である。正規表現でできることをマッチするという。正規表現

の特殊文字の組合せが多くあるため一つの結果に対していろいろな方式を作ることができ

る。本プログラムで使用した@"^push[0-9]+ [0-9]+$"はプッシュのコマンドを宣言し

記入した数字場所のマスを開く正規表現である。この正規表現を作成にあたって、まず初

めに1桁の数字とアルファベットが混合したコードが必要だったため、 [0-9a-z]とい

うコードを作成した。このコードを Regex rx = new Regex( @"^[0-9a-z]+" )という正規

表現で宣言することで数値1桁とa-zの小文字のアルファベットを表すことができるよ

うになる。

次に、設定したコマンド入力のみを受け付けるようにした。このコードを作成した際に

どのようにコマンドが正確に読み取ってもらえるかが課題であった。コマンドとマスを指

定する数値をすべて参照するには、すぐ前の文字を参照する特殊文字“^”で pushを参照

するようにし、後方一致を意味する特殊文字“$” ”でコマンドとマスを指定する数値を

参照するようにしたことでコマンドを正確に読み取ることができた。本プラグラムでは前

方一致を表す特殊文字“^”と後方一致を表す特殊文字“$”を使用したが他にも様々な正

規表現がある。図 28 にその正規表現を示す。

指定内の任意の表現では “[]”を使用する。“[]”はクラスや文字セットといい、二つ

以上の文字を読み取りたいときや複数の文字の中に読み込ませたい文字などを“[]”内に

宣言することで読み取ることができる。

① [a-z]は小文字のアルファベットすべてを表す。“abc opq”と”xyz hij”という 2 つ

の文字列に対して[a-z]とを指定した場合どちらも小文字のアルファベットなのでマッ

チすることになる。

② [0-9]は数値1桁を表す。“3”と“11”という2つの文字に対して“3”は1桁の

数字なのでマッチするが“11”は2桁の数字なのでマッチしない。

③ [A-Z]は A-Z の大文字のアルファベットをすべて表す。①で述べた小文字のアルファベ

ットが大文字のアルファベットになったものである。

図 28 指定内の任意の表現

Page 23: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

23

④ [^a-z]は漢字や数字などの半角小文字のアルファベット以外を表す。“課金”や

“KAKIN”は半角小文字のアルファベットは含まれないのでマッチする。“Kakin”は初

めの文字は大文字なのでマッチされるがほかの文字が半角小文字のアルファベットな

のでマッチされない。

⑤ [a-z&& [^bc]]は b と c を除く a から z までの小文字のアルファベットを表すものであ

る。“baseball”や“soccer”は bと cが含まれているのでマッチしない。“tennis”

は bと cを含まないのでこの正規表現にマッチしているといえる。

⑥ [abc]は a、b、cを参照する。a、b、cが含まれるものはこのコードにすべてマッチする。

⑦ [^abc]は a、b、c以外の文字を参照する。⑥とは逆のコードで a、b、cが含まれていな

いものはこのコードにすべてマッチする。

⑧ [a-zA-Z]は a から z までと A から Z まで参照する。①と③の両方を含んだもので 大文

字と小文字の半角アルファベットはマッチする。“Amazon”や“mild”などもこれにマ

ッチする。数字や漢字などはマッチしない。

⑨ [a-d[m-p]]は aから dまたは mから pまでを示す。a、b、c、dまたは m、n、o、pが含

まれていればこのコードにマッチする。それ以外の半角小文字のアルファベットを使用

しているとマッチされない。

⑩ [a-z&&[^m-p]]は mから pを除く aから zまでを示す。m、n、o、p以外の小文字の半角

アルファベットがマッチする。

図 29のように,回数指定の表現では“{}”を使用する。文字の後に“{}”を置くことで

は繰り返してほしい回数や、示してほしい数字の回数を決めることができる。

① {a}は直前の文字を a回繰り返す。a{4}なら[aaaa]となる。

② {a,}は直前の文字を a回以上繰り返す。 b{5,}なら[bbbbb]や[bbbbbb…]となる。

③ {a,b}は直前の文字を a 回以上 b 回以下を示す。c{3,5}なら3回以上5回以下なので

[ccc]、[cccc]、[ccccc]と表される。

④ {a,}?は?マークがつくことで最短を表現できる。

⑤ {a,b}?は?マークが付くことで最短を表現できる。

⑥ x?または x??は x、1回または0回を示す。“34?” なら0回または1回をさすので“3”

や“34”と表される。

⑦ x*または x*?は x、0回以上を示す。“12*”なら0回以上の表現なので“1”や

図 29 回数指定の表現

Page 24: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

24

“122222222…”と表現されます。

⑧ x+または x+?は x、1回以上を示す。“67+”では“677777777…”と表現される。

⑨ x{n}または x{n}?は x、n回を示す。①で説明したように a{4}と表すと[aaaa]となる。

⑩ x{n,}または x{n,}?は x、n回以上を示す②で表したように b{5,}なら[bbbbb]や[bbbbbb

…]となる。

x{n,m}または x{n,m}?は x、n回以上、m回以下を示す。③で表したように c{3,5}なら

3回以上5回以下なので[ccc]、[cccc]、[ccccc]と表される。

その他の規則を図 30 に示す。

① ^は行の先頭を指す。“abc def”と“xyz abc”の二つの文字列を“^abc”で表すと

文字列の先頭が“abc”から始まっているものを指すので、“abc def”がマッチする

文字列であるといえる。

② $は行の末尾を指す。“abc def”と“xyz abc”の二つの文字列を“abc$”で表すと

文字列の末尾が“abc”で終わっているものを指すので、“xyz abc”がマッチしてい

る文字列であるといえる。

③ \b 単語の境界を表す。境界単語を構成する文字とそうでない文字との境目の子である。

Who are you?という文では行頭と“W”の間、“o”と空白の間、空白と“a”の間、“e”

と空白の間、空白と“y”の間, “u”と?の間のことを指す。“\byo“と指定した場合

は単語の境界から始まり“yo”と続いているかを示すのでこれはマッチしている。

④ \B 非単語の境界を表す。\bにマッチする以外の位置にマッチする。

⑤ \A は文字列の先頭を表す。“^”は行の先頭にマッチにしたのに対して、“\A”は文字

列の先頭にマッチする。

⑥ \G 前回の読み取った末尾を表す。

⑦ \Z 最後の行末記号がある場合は、それを除く入力の末尾を表す。“$”は行の末尾にマ

ッチしたのに対して、“\Z”は文字列の末尾にマッチする。

⑧ \z 入力の末尾を表す。⑦と同じで文字列の末尾を表す。“\Z”と\“z”の違いは、“\Z”

の場合は文字列の最後が行の末尾だった場合はその部分を除いた後の末尾にマッチす

る。“\z”の場合は文字列の最後が行の末尾だったとしても、関係なく文字列の末尾と

してマッチする。

⑨ XYは連続した正規表現のことである。

⑩ X|Y は Xまたは Yである。(This|That) is appleと表記すると This is appleまたは That

図 30 位置指定の表現とその他の表現

Page 25: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

25

is appleと表記される。

⑪ (X)は“()”で囲んだ X はいつのまとまりグループとみなされる。正規表現を“()”で

囲むことも可能である。

⑫ \n は番号指定による後方参照である。“()”でグループ化した文字列を、\n(nは1以

上の整数)で参照する。

第2節 本システムの GUI化

本節では GUI化について考察する.本プログラムは MVCモデルという設計法に基づいて

作成しており、Model、View、Controlクラスの他に Bdmクラスと CellsStatuasクラスがあ

る(図 31参照)。本プログラムの盤面のマスは旗、地雷などの表現は全て文字で行う CUI

で作成され、ゲームの進行もコマンドによって行われる。一般的なマインスイーパーは GUI

で作成されているため、マウスでクリックすることでゲームが進んでいく。本プログラム

の CUIと GUI の違いは、CUI は情報を全て文字で表現され、GUIはアイコンや画像を使い情

報を表現する。

本プログラムの描画の処理を行う Viewクラスを GUIに変更した場合、このクラスでは for

図 31 クラス図

Page 26: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

26

文や if文を使うことで描画の処理を行いコンソール画面上に描画していたが、System.

Drawing ライブラリを使用し、マスの描画はビットマップ画像を使って表現し、jpeg等の

画像を使って地雷や旗を表現し、Graphicsクラスでオリジナルのアイコンを作成し用いる

ことで GUIプログラムになる。

次に画像を表示するためのコードの説明をする。図 32の行番号2は Bitmap画像を描画

するためのオブジェクトを作成し、行番号3で Graphicsオブジェクトを作成する。ペイン

ト等で作成された画像を読み込み Imageオブジェクトとして取得するのは行番号4の

「Image img = Image.FromFile(@"C:\test\1.bmp");」で行う。この処理によって Testフ

ォルダ内にある1という画像を読み込み行番号5で指定した座標に描画する。設置した

PictureBoxに指定した座標で画像が描画される(図 32参照)。画像をペイントや既にある

画像を利用し作成することで文字のみの CUIより表現の幅が広がる(図 33参照)。本プロ

グラムは MVC モデルを用いて作成したため、Modelや Controlクラスに干渉せずに Viewク

ラスの変更が出来、System.Drawing を参照した Test Method()を Viewに差し替えることで

GUI を用いたプログラムとなる。

1:public void Test Method(){

2:Bitmap canvas = new Bitmap(PictureBox1.Width, PictureBox1.Height);

3:Graphics g = Graphics.FromImage(canvas);

4:Image img = Image.FromFile(@"C:\test\1.bmp");

5:g.DrawImage(img, 30, 30, img.Width, img.Height);

6:img.Dispose();

7:g.Dispose();

8:PictureBox1.Image = canvas;

図 32 画像を表示するコード

図 33 左が CUIの地雷 右が GUIの地雷

Page 27: マインスイーパーを使った MVC モデル の有効性に …hanakawa/soturon/2012/HirataTera...1 マインスイーパーを使ったMVCモデル の有効性について

27

第5章 まとめ

MVCを利用したマインスイーパーの作成をした。Model、View、Controlと MVCモデル

の設計手法に基づき、役割を 3つの担当に分けた。各クラスの独立性が高く、一部の描画

や設定の変更をしても対応しやすい設計方法である。

今後の課題として、一つ一つの処理を確認しあうためのコミュニケーションが大切であ

るといえる。役割分担もメソッド等の名前や各処理で使うコードの設定を統一しなければ

一人で作成するよりも時間がかかり、統合しても多くのミスやバグが発生するという要因

になるので綿密なコミュニケーションをとることが必要である。また、MVCモデルは多人数

で同時に開発するのに向いているため、一人で作成する際にどのプログラムも MVCモデル

で作成すると返って複雑化する原因になることが課題である。

参考文献

[1]JAVAコーディング規約 オブジェクト倶楽部 http://www.objectclub.jp

[2]マインスイーパーを楽しむ http://nn161655.tiyogami.com/sitemap.html

謝辞

同ゼミで共に励んだ菊池祐希氏に感謝します。同ゼミで共に励んだ北川照樹氏に感謝し

ます。同ゼミで共に励んだ五通佳来多氏に感謝します。同ゼミで共に励んだ内匠航一氏に

感謝します。同ゼミで共に励んだ竹田尚史氏に感謝します。同ゼミで共に励んだ寺杣直也

氏に感謝します。同ゼミで共に励んだ中川貴智氏に感謝します。同ゼミで共に励んだ中瀬

広宣氏に感謝します。同ゼミで共に励んだ西大輝氏に感謝します。同ゼミで共に励んだ播

本佳大氏に感謝します。同ゼミで共に励んだ菊池祐希氏に感謝します。同ゼミで共に励ん

だ松本有貴氏に感謝します。同ゼミで共に励んだ平田滉陽氏に感謝します。マインスイー

パー作成の時に全く知識が無い状態から一から優しく丁寧に根気よく教えてくれた松谷栄

輝氏に感謝します。他のプロジェクトで忙しいにも関わらず時間があればちょっとしたこ

とでも教えてくれた仙田友久氏に感謝します。 そして最後に御自身の論文や仕事で多忙な状態でも、どれだけ間違えても最後まで添削や

アドバイスをして頂いた花川典子教授に心から感謝致します。