滝の音

滝の音

名こそ流れてなお聞こえけれ

VBAでオセロをつくろう! その1

コードを書いていて思うことは。

目的の機能を書くことは難しくない。

抽象化して書くことは難しい。

ということ。

 

抽象化して書いているつもりでも

後で振り返ると無駄が多かったり。

重複した処理を書いていたり。

 

まだまだ修行中です。。

 

とりあえず。

オセロver01書きました。

 

  • できること

手動で対戦ゲームができます。

たぶん一番シンプルな機能です。

 

  • コード

メイン

Public rp As Range
Public field As Range
Public n As Integer
Public c As Range
Public stone As Variant
Public turn As Variant

Private Sub Worksheet_Activate()
 'シートの状態を設定
 Cells.ClearContents
 Call 基礎値共有(rp, n, field, c, stone, turn)
 Call フィールド形成(rp, field, stone, n)
 
 c.Value = 0
 c.Offset(1, 0) = turn(0)
End Sub

Private Sub Worksheet_SelectionChange(ByVal target As Range)
 
 Call 基礎値共有(rp, n, field, c, stone, turn)
 
 Dim flag As Boolean
 Dim tmp As String
 Dim d(1) As Integer
 Dim q(1) As Integer
 
 q(0) = c Mod 2
 q(1) = (c + 1) Mod 2
 '手番の表示
 c.Offset(1, 0) = turn(q(0))
 
 '場外判定
 flag = field_alart(target, field, flag)
 If flag = True Then
    Exit Sub
 End If
 
 'targetの周囲の認識
 
 For i = 0 To 8
    d(0) = i Mod 3 - 1
    d(1) = i \ 3 - 1
    tmp = target.Offset(d(0), d(1)).Value
    If tmp = stone(q(1)) Then
        '石を置けるのかの判定とおけた場合の処理
        Call 置けるかの判定(target, stone, d, q, n, flag)
    End If
 Next
 
 '石が置けない場合の処理
 If flag = False Then
    Exit Sub
 End If
 
 'クリック数と手番の更新
 Call クリック数のカウント(n, c)

 c.Offset(1, 0) = turn(q(1))
 'Call 手番の表示(c, turn, q)
 
End Sub

 

サブ

Sub 基礎値共有(rp, n, field, c, stone, turn)
 Set rp = Cells(2, 2)                           'フィールド形成の定点の定義
 n = 8                                          '盤面の大きさの定義
 Set field = Range(rp, rp.Offset(n - 1, n - 1)) 'フィールドの定義
 Set c = rp.Offset(0, n + 2)                    'カウントセルの指定
 stone = Array("●", "○")                      '黒石と白石の定義
 turn = Array("黒番", "白番")                   '手番プレートの定義

End Sub

Sub フィールド形成(rp, field, stone, n)
'フィールドのヴィジュアル定義
With field
    .ClearContents
    .Rows.RowHeight = 50
    .Columns.ColumnWidth = 8
    .Interior.Color = RGB(200, 200, 200)
    .Borders().LineStyle = xlContinuous
 End With

'初期配置
With rp
    .Offset(n / 2 - 1, n / 2 - 1) = stone(0)
    .Offset(n / 2, n / 2) = stone(0)
    .Offset(n / 2 - 1, n / 2) = stone(1)
    .Offset(n / 2, n / 2 - 1) = stone(1)
 End With
End Sub

Function field_alart(target, field, flag) As Boolean
 'targetがfield内の場合にtrueを返す
 If Application.Intersect(target, field) Is Nothing Then
    field_alart = True
 Else
    field_alart = False
 End If

End Function


Sub 置けるかの判定(target, stone, d, q, n, flag)
 Dim tmp As Range
 Dim stock As Range
 
 Set tmp = target
 mystone = stone(q(0))
 Set stock = tmp

 For i = 1 To n - 1
   
    Set tmp = tmp.Offset(d(0), d(1))
    Select Case tmp.Value
        Case Is = ""
            Exit For
        Case Is = mystone
            stock = mystone
            flag = True
            Exit For
        Case Else
            Set stock = Union(stock, tmp)
    End Select
 Next
 
End Sub

Sub クリック数のカウント(n, c)
 Dim tmp As Integer
 c.Value = c.Value + 1
End Sub

 

  • 思ったこと

オセロにおいては。

選んだ場所に石が置けるかどうか。

がミソです。

その場所がよい場所かどうか。

が次のポイントですね。

解析をするにしても仮想の敵を作るにしても。

  • 次の予定

次は仮想の相手を用意したいのですが。

いきなりは難しいかなと思うので。

 

次に置けるポイントを☆で示す。

それぞれのポイントの良し悪しを評価する要素を設ける。

 

の2点を書こうかなと思います。

ではでは。