• 検索結果がありません。

Public Grid As ReverseGrid Public Position As Point ' 論理位置 Public Rectangle As Rectangle ' 物理位置 Status; 黒 白 なしの状態 Grid; オセロの盤面 Position; 盤面内の説明 Rectan

N/A
N/A
Protected

Academic year: 2021

シェア "Public Grid As ReverseGrid Public Position As Point ' 論理位置 Public Rectangle As Rectangle ' 物理位置 Status; 黒 白 なしの状態 Grid; オセロの盤面 Position; 盤面内の説明 Rectan"

Copied!
14
0
0

読み込み中.... (全文を見る)

全文

(1)

04-1 31204

プログラミング

3605 井上 寛晶 3531 松井 佑樹 3635 宮地 翼 要旨 各自でフリーソフトを作成、インターネット上に公開することを目的とし、 Visual Basic2008、2010 を使い、二年生までは「ちんちろりん」という簡単なゲームを作ったが、今回はより難度が高い「オセ ロ」の作成に成功した。 本文 1. 目的 情報化が進んだ現代において、社会に出ていくためにはパソコンの一つや二つ、軽く扱えなけれ ばならない。さらに、資源の乏しい日本においては今後、情報技術の発展することが望ましいと考 える。私たちのグループでは、SE(システムエンジニア)等の職に就き、今後の日本のみならず情 報技術によって世界に貢献できる人材となるべく、プログラミング技術の習得を目的とした。 また、今回はIA(人工知能)が必要となる対戦型オセロゲームを作成することを目的とし、より 高度なプログラミング技術の取得を目的とした。 2. 使用した器具・装置など (1)使用言語 Visual Basic

(2)開発ソフト Microsoft Visual Studio 2008 Microsoft Visual Studio 2010 使用マシン FMV K5290 Intel LB-D701S 3. 研究・実験の手順 一年生から積み上げてきたVisual Basic の知識を生かし、以下のソフトを開発 ・対戦型オセロゲーム 4. 結果 ◎プログラムの説明

Cell,txt のプログラム

Public Class cell

(2)

04-2 Public Grid As ReverseGrid

Public Position As Point '論理位置 Public Rectangle As Rectangle '物理位置 ↑ Status; 黒、白、なしの状態 Grid;オセロの盤面 Position;盤面内の説明 Rectangle;描画を行う四角形の領域 '■コンストラクタ ''' <summary>論理位置を指定してセルを作成します。</summary> ''' <param name="Grid">セルが属するグリッドを指定します。</param> ''' <param name="Position">セルの論理位置を指定します。</param> Public Sub New(ByVal Grid As ReverseGrid, ByVal Position As Point) Me.Grid = Grid

Me.Position = Position Dim Rect As New Rectangle

'論理位置から物理位置を求めます。

Rect.X = Position.X * ReverseGrid.CellSize Rect.Y = Position.Y * ReverseGrid.CellSize Rect.Width = ReverseGrid.CellSize

Rect.Height = ReverseGrid.CellSize Me.Rectangle = Rect

End Sub

Dim FrontBrush As New SolidBrush(Color.Black) Dim BackBrush As New SolidBrush(Color.White) '■Draw

''' <summary>現在の状態を描画します。</summary>

''' <param name="g">描画対象の Graphics オブジェクトを指定します。</param> Public Sub Draw(ByVal g As Graphics)

Dim CellRect As Rectangle '描画領域 ↑

(3)

04-3 '▼描画領域の算定 'セルいっぱいに描画するとぎちぎちになるので範囲を-2 する。 CellRect = Me.Rectangle CellRect.Inflate(-2, -2) '▼描画状態の設定

Select Case Me.Status Case CellStatus.Black FrontBrush.Color = Color.Black '表を黒に設定 BackBrush.Color = Color.White '裏を白に設定 Case CellStatus.White FrontBrush.Color = Color.White '表を白に設定 BackBrush.Color = Color.Black '裏を黒に設定 End Select ↑黒の石は表を黒、裏を白に、 白の石は表を白、裏を黒に設定する '▼描画実行

If Me.Status <> CellStatus.Nothing Then '裏面描画 CellRect.Y += 2 '裏と表をちょっとずらして立体的に見せる g.FillEllipse(BackBrush, CellRect) '表面描画 CellRect.Y -= 2 g.FillEllipse(FrontBrush, CellRect) End If ↑石の状態が有色(石が置かれている)であれば、石の表、裏を描画する。この時、裏表を若干ずらし て立体的に見せる。 '▼アクティブな場合は枠を描画する If Me.Focused Then g.DrawRectangle(Pens.Orange, CellRect) End If ↑下記の赤色の変更を適応するコード

(4)

04-4 End Sub

Public Focused As Boolean '■Focus

''' <summary>セルをアクティブにします。</summary>

''' <remarks>アクティブなセルとは Focused プロパティが True のセルです。

''' このメソッドを呼び出すと同じ盤に属するその他のセルのFocused プロパティを False にします。 ''' アクティブであることにそれ以上の効果はありませんが、

''' 描画の際に Focused プロパティが True のセルに枠線を描画します。 ''' </remarks>

Public Sub Focus() Dim X As Integer Dim Y As Integer

'同じグリッドに属する自分以外のセルを非アクティブにする。 For X = 0 To ReverseGrid.XCount - 1

For Y = 0 To ReverseGrid.YCount - 1 Grid.Cells(X, Y).Focused = False Next Next '自分自身をアクティブにする。 Me.Focused = True End Sub ↑マスの上にマウスを置いたときに枠線を表示する(Form1 の MouseMove イベントと対応) *こちらではマウスが来たときに枠を描く準備を行う。⇒実際に描画しているのはPaint イベントの Draw イベント(上の青色の部分)

(5)

04-5

computer3 のプログラム

Public Class Computer3 Dim Grid As ReverseGrid Public Standard As CellStatus

ReverseGrid;オセロの盤面を表し、石を置く、ひっくり返すことや、それに関するイベント、セルの管 理、描画処理を行う。

Cellstatus;石のもと(白、黒、なし、の三つの状態を表す) Grid はオセロの盤面、Standard は黒、白、なしの三色と宣言

Public Sub New(ByVal Grid As ReverseGrid, ByVal Standard As CellStatus) Me.Grid = Grid

Me.Standard = Standard End Sub

Public Sub Put()

↑コンピュータに石を置かせる Dim X As Integer Dim Y As Integer

Dim PlayerColor As CellStatus '角に置けるなら角におく

If Grid.CanPut(Standard, 0, 0) Then Grid.Put(Standard, 0, 0)

Return End If

If Grid.CanPut(Standard, 0, ReverseGrid.YCount - 1) Then Grid.Put(Standard, 0, ReverseGrid.YCount - 1)

Return End If

If Grid.CanPut(Standard, ReverseGrid.XCount - 1, 0) Then Grid.Put(Standard, ReverseGrid.XCount - 1, 0)

Return End If

(6)

04-6

If Grid.CanPut(Standard, ReverseGrid.XCount - 1, ReverseGrid.YCount - 1) Then Grid.Put(Standard, ReverseGrid.XCount - 1, ReverseGrid.YCount - 1)

Return End If

↑右上、右下、左上、左下に置くことが可能な時はその置けるところに石を置かせる なお、角を図1のように定義している

図1

If Standard = CellStatus.Black Then PlayerColor = CellStatus.White Else PlayerColor = CellStatus.Black End If ↑コンピュータの使う色が黒ならプレイヤーの石の色は白、それ以外(白)なら、プレイヤーの石は黒。 '順番に見ていってはじめに置けるところを探す

Dim ImageGrid As ReverseGrid Dim Puts As New ArrayList

↑ImageGrid はオセロの盤面、Puts は新しいコレクションと宣言 For Y = 0 To ReverseGrid.YCount - 1

For X = 0 To ReverseGrid.XCount - 1

If Grid.CanPut(Standard, X, Y) Then

Puts.Add(New Point(X, Y))

(7)

04-7

'▼まず、コピーのグリッドに石を置いてみる ImageGrid = Grid.Copy

ImageGrid.Put(Standard, X, Y)

'この状態で相手に角を取られる可能性があるか検証する Select Case True

Case ImageGrid.CanPut(PlayerColor, 0, 0) '左上の角を取られてしまうので何もしない

Case ImageGrid.CanPut(PlayerColor, 0, ReverseGrid.YCount - 1) '左下の角を取られてしまうので何もしない

Case ImageGrid.CanPut(PlayerColor, ReverseGrid.XCount - 1, 0) '右上の角を取られてしまうので何もしない

Case ImageGrid.CanPut(PlayerColor, ReverseGrid.XCount - 1, ReverseGrid.YCount - 1) '右下の角を取られてしまうので何もしない Case Else '角を取られる心配がないのでこの位置に石を置く Grid.Put(Standard, X, Y) Return End Select End If Next Next '角を取られる位置にしか置けない場合、仕方ないので置く Dim Pos As Point = DirectCast(Puts(0), Point)

Grid.Put(Standard, Pos.X, Pos.Y)

End Sub

End Class

↑置く場所を考える場合、コピーの盤面をAI が考え、それぞれの角を取られる場合を考える。⇒それ

(8)

04-8

Constant のプログラム

'■CellStatus

''' <summary>セルの状態を表します。</summary> Public Enum CellStatus

[Nothing] 'なし Black '黒 White '白 End Enum '■ScanDirection ''' <summary>方向を表します。</summary> Public Enum ScanDirection

Left Right Up Down LeftUp LeftDown RightUp RightDown End Enum

form1 のプログラム

Public Class Form1

Dim WithEvents Grid As New ReverseGrid

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Grid.Initialize() lblBlackCount.Text = Grid.Count(CellStatus.Black) lblWhiteCount.Text = Grid.Count(CellStatus.White) lblWhiteTurn.Visible = False ↑ゲーム開始時に現在のターンをラベルを使って表示

(9)

04-9 End Sub

Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click

'マウスの座標を PictureBox1 のコントロール座標に変換する。

Dim Pos As Point = PictureBox1.PointToClient(Windows.Forms.Cursor.Position)

↑マウスで表される座標(PC 上の画面での座標)を盤面上のマスの座標に変換 Dim ThisCell As cell

ThisCell = Grid.CellFromPoint(Pos.X, Pos.Y)

If Grid.Put(Turn, ThisCell.Position.X, ThisCell.Position.Y) Then ChangeTurn() End If ↑石を置いたときにターンを交代させる。また、ReverseGrid の Canput で設定した置けるマスのみに 石を置けるようにする。 End Sub ''' <summary>マウスの移動に伴ってセルにアクティブを示す枠を描画する</summary> Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As

System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove

Dim ThisCell As cell

'マウスがある位置のセルを取得

ThisCell = Grid.CellFromPoint(e.X, e.Y)

If Not IsNothing(ThisCell) Then

'セルが取得できた場合は、セルにアクティブを示す枠を描画 ThisCell.Focus() '現在の状態を描画(PictureBox1 の Paint イベントを発生させる) PictureBox1.Invalidate() '←実際の描画はすべてここで行う End If ↑Cell の Focus と対応(こっちでは、マウスがある位置等を取得)

(10)

04-10 End Sub

Dim Turn As CellStatus = CellStatus.Black '今どっちの順番か Dim PlayerColor As CellStatus = CellStatus.Black 'プレイヤーの色 '■ChangeTurn

''' <summary>ターン交代</summary> Public Sub ChangeTurn()

'現在の状態を描画(PictureBox1 の Paint イベントを発生させる) PictureBox1.Invalidate() ↑paint イベントを強制的に発生させる ▼勝敗判定 ①すべてのマスに石が置かれる ②マスはまだ空いているが石を置けない状況 ③すべての色が同じ色になる ① If Grid.Count(CellStatus.Nothing) = 0 Then 石の置けるマスが0になり '全セルへの配置が終了した場合は勝敗判定して終了

If Grid.Count(CellStatus.Black) > Grid.Count(CellStatus.White) Then←黒のほうが多 かったら

MsgBox("黒の勝ちです!")

ElseIf Grid.Count(CellStatus.Black) < Grid.Count(CellStatus.White) Then←白のほう が多かったら MsgBox("白の勝ちです!") Else MsgBox("引き分けです!!") End If ↑マスすべてに石が置かれ、どちらの石の数が多いか調べた後、それぞれのメッセージを表示 Return

ElseIf Grid.PuttableCount(CellStatus.Black) = 0 AndAlso Grid.PuttableCount(CellStatus.White) = 0 Then

② '空いているセルがあるのに黒も白も置けない場合

If Grid.Count(CellStatus.Black) > Grid.Count(CellStatus.White) Then MsgBox("黒の勝ちです!")

ElseIf Grid.Count(CellStatus.Black) < Grid.Count(CellStatus.White) Then MsgBox("白の勝ちです!")

Else

MsgBox("引き分けです!!") End If

(11)

04-11

↑石を置くことのできるマスがなくなり、どちらが多いかを調べた後、それぞれのメッセージを表示 ElseIf Grid.Count(CellStatus.Black) = 0 Then

③ 'すべての石が白になった場合(=黒の石が 0 個の場合) MsgBox("白の勝ちです!")

Return

ElseIf Grid.Count(CellStatus.White) = 0 Then

'すべての石が黒になった場合(=白の石が 0 個の場合) MsgBox("黒の勝ちです!") Return End If ↑石すべてが白または黒になったらそれぞれのメッセージを表示 '▼次のターンの決定

If Turn = CellStatus.Black Then Turn = CellStatus.White lblBlackTurn.Visible = False lblWhiteTurn.Visible = True Else Turn = CellStatus.Black lblBlackTurn.Visible = True lblWhiteTurn.Visible = False End If ↑石が黒のターンなら次は白に、白なら次は黒に⇒ターンの交代を処理 また、黒のターン、白のターンであることを示す線を表示させる '▼置ける場所があるか判定 If Grid.PuttableCount(Turn) = 0 Then '置く場所がなければパスして次のターン ChangeTurn() End If '▼人間かコンピュータかで処理を分岐 If Turn = PlayerColor Then

'人間の番ならば、PictureBox を使用可能にする。 PictureBox1.Enabled = True Else ↑プレイヤーの番は盤面の操作を可能にし、コンピュータの番のときは盤面の操作を不可能にする。 'コンピュータの番ならば、PictureBox を使用不可にする。 PictureBox1.Enabled = False

(12)

04-12 'ちょっと時間をおく Application.DoEvents() System.Threading.Thread.Sleep(500) ↑0.5秒の間を空ける 'コンピュータに石を置かせる。どのセルに置くかはコンピュータ(AI)が決定する。 Computer.Put() ChangeTurn() 'プレイヤーの番へ End If ↑コンピュータが石を置きターンを交代する End Sub

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint Grid.Draw(e.Graphics)

End Sub

''' <summary>石を置いたときに発生するイベント</summary>

Private Sub Grid_PutNew(ByVal sender As Object, ByVal e As System.EventArgs) Handles Grid.PutNew

Call Grid_Reversed(sender, e) End Sub

''' <summary>石がひっくり返されたときに発生するイベント</summary>

Private Sub Grid_Reversed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Grid.Reversed

'現在の状態を描画(PictureBox1 の Paint イベントを発生させる) PictureBox1.Invalidate()

(13)

04-13 lblBlackCount.Text = Grid.Count(CellStatus.Black) lblWhiteCount.Text = Grid.Count(CellStatus.White) ↑黒石、白石の数をラベルに表示し、paint イベントを発生させ、描画を行う。 'ちょっと時間をおく Application.DoEvents() System.Threading.Thread.Sleep(500) ↑石をひっくり返す動作をする際に、毎回0.5 秒の間を空ける⇒瞬時に変わるとゲーム性が損なわれ る! End Sub '■Start ''' <summary>ゲームを開始します。</summary> ''' <param name="PlayerColor">人間の石の色を指定します。</param> ''' <remarks>黒が先手になります。</remarks>

Private Sub Start(ByVal PlayerColor As CellStatus) Grid.Initialize()

Me.PlayerColor = PlayerColor '人間の色 If PlayerColor = CellStatus.Black Then

Computer.Standard = CellStatus.White 'コンピュータの色は白 Else Computer.Standard = CellStatus.Black 'コンピュータの色は黒 End If ↑プレイヤー、コンピュータの色を設定。 '現在の黒と白の駒の数を表示する lblBlackCount.Text = Grid.Count(CellStatus.Black) lblWhiteCount.Text = Grid.Count(CellStatus.White) ↑ラベルに黒石、白石の数を表示 'ChangeTurn を呼び出して黒の番を開始する。そのために仮に今は白の番であることにする。 Turn = CellStatus.White ChangeTurn() End Sub

Private Sub btnStartBlack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartBlack.Click

(14)

04-14

Start(CellStatus.Black)

End Sub

Private Sub btnStartWhite_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartWhite.Click

Start(CellStatus.White) End Sub ↑黒、白で始まるかを選択するボタンの処理 5. 結果に対する考察・わかったこと、感想 人工知能というと、難しいイメージがあったが一つ一つ見ていくと角に置けるかを確認するプログ ラム、右上から左下まで置けるところを探すプログラム、実際に仮の盤面に置くプログラム、相手 に角を取られないことを確認するプログラム、実際に置くプログラムと、単純なことの積み重ねだ ったので、理解できた。この経験を生かして今後もプログラムの道に精進したい。 6. 参考文献、引用文献 http://homepage1.nifty.com/rucio/main/main.htm

参照

関連したドキュメント

(13 ページ 「Position(位置)」 参照)。また、「リファレンス」の章を参照してくだ さい。(85 ページ 「水平軸」

見た目 無色とう明 あわが出ている 無色とう明 無色とう明 におい なし なし つんとしたにおい つんとしたにおい 蒸発後 白い固体

存在が軽視されてきたことについては、さまざまな理由が考えられる。何よりも『君主論』に彼の名は全く登場しない。もう一つ

② 現地業務期間中は安全管理に十分留意してください。現地の治安状況に ついては、

なお、保育所についてはもう一つの視点として、横軸を「園児一人あたりの芝生

運航当時、 GPSはなく、 青函連絡船には、 レーダーを利用した独自開発の位置測定装置 が装備されていた。 しかし、

にちなんでいる。夢の中で考えたことが続いていて、眠気がいつまでも続く。早朝に出かけ

ア.×