オセロのゲーム
@@ -10,10 +10,11 @@ | ||
10 | 10 | Next |
11 | 11 | End Sub |
12 | 12 | |
13 | - Public Function GetData(ByVal color As DiscColor) As CornerParam | |
14 | - Return _data(color + 1) | |
15 | - End Function | |
16 | - | |
13 | + Default Public ReadOnly Property GetData(ByVal color As DiscColor) As CornerParam | |
14 | + Get | |
15 | + Return _data(color + 1) | |
16 | + End Get | |
17 | + End Property | |
17 | 18 | End Class |
18 | 19 | |
19 | 20 | End Namespace |
@@ -45,6 +45,14 @@ | ||
45 | 45 | Me.CMove += e.CMove |
46 | 46 | End Sub |
47 | 47 | |
48 | + Public Sub [Set](ByVal e As EdgeParam) | |
49 | + Me.Stable = e.Stable | |
50 | + Me.Wing = e.Wing | |
51 | + Me.Mountain = e.Mountain | |
52 | + Me.CMove = e.CMove | |
53 | + End Sub | |
54 | + | |
55 | + | |
48 | 56 | End Class |
49 | 57 | End Namespace |
50 | 58 |
@@ -1,11 +1,48 @@ | ||
1 | 1 | Namespace AI.Level2 |
2 | 2 | |
3 | 3 | Public Class Weight |
4 | + | |
5 | + ''' <summary> | |
6 | + ''' 着手可能数の重み | |
7 | + ''' </summary> | |
8 | + ''' <value></value> | |
9 | + ''' <returns></returns> | |
10 | + ''' <remarks></remarks> | |
4 | 11 | Public Property MobilityWeight As Integer |
12 | + ''' <summary> | |
13 | + ''' 開放度の重み | |
14 | + ''' </summary> | |
15 | + ''' <value></value> | |
16 | + ''' <returns></returns> | |
17 | + ''' <remarks></remarks> | |
5 | 18 | Public Property LibertyWeight As Integer |
19 | + ''' <summary> | |
20 | + ''' 確定石の重み | |
21 | + ''' </summary> | |
22 | + ''' <value></value> | |
23 | + ''' <returns></returns> | |
24 | + ''' <remarks></remarks> | |
6 | 25 | Public Property StableWeight As Integer |
26 | + ''' <summary> | |
27 | + ''' ウィングの重み | |
28 | + ''' </summary> | |
29 | + ''' <value></value> | |
30 | + ''' <returns></returns> | |
31 | + ''' <remarks></remarks> | |
7 | 32 | Public Property WingWeight As Integer |
33 | + ''' <summary> | |
34 | + ''' X打ちの重み | |
35 | + ''' </summary> | |
36 | + ''' <value></value> | |
37 | + ''' <returns></returns> | |
38 | + ''' <remarks></remarks> | |
8 | 39 | Public Property XMoveWeight As Integer |
40 | + ''' <summary> | |
41 | + ''' C打ちの重み | |
42 | + ''' </summary> | |
43 | + ''' <value></value> | |
44 | + ''' <returns></returns> | |
45 | + ''' <remarks></remarks> | |
9 | 46 | Public Property CMoveWeight As Integer |
10 | 47 | End Class |
11 | 48 |
@@ -7,15 +7,19 @@ | ||
7 | 7 | |
8 | 8 | Const TABLE_SIZE As Integer = CInt(3 ^ 8) |
9 | 9 | |
10 | - Private Shared EdgeTable(TABLE_SIZE) As EdgeStat | |
11 | - Private Shared TableInit As Boolean = False | |
10 | + Private Shared _edgeTable(TABLE_SIZE - 1) As EdgeStat | |
11 | + Private Function EdgeTable(ByVal index As Integer) As EdgeStat | |
12 | + Debug.Assert(0 <= index AndAlso index < TABLE_SIZE) | |
13 | + Return _edgeTable(index) | |
14 | + End Function | |
15 | + Private Shared _tableInit As Boolean = False | |
12 | 16 | |
13 | 17 | Sub New() |
14 | - If Not TableInit Then | |
18 | + If Not _tableInit Then | |
15 | 19 | '初期起動時にテーブルを生成 |
16 | - Dim line(Board.SIZE_X) As Integer | |
20 | + Dim line(Board.SIZE_X - 1) As Integer | |
17 | 21 | GenerateEdge(line, 0) |
18 | - TableInit = True | |
22 | + _tableInit = True | |
19 | 23 | End If |
20 | 24 | EvalWeight = New Weight |
21 | 25 | EvalWeight.MobilityWeight = 67 |
@@ -27,21 +31,130 @@ | ||
27 | 31 | End Sub |
28 | 32 | |
29 | 33 | Private Sub GenerateEdge(ByVal edge() As Integer, ByVal count As Integer) |
34 | + Debug.Assert(edge.Count >= count) | |
35 | + If count >= 8 Then | |
36 | + Dim stat As New EdgeStat | |
37 | + stat(DiscColor.BLACK).Set(evalEdge(edge, DiscColor.BLACK)) | |
38 | + stat(DiscColor.WHITE).Set(evalEdge(edge, DiscColor.WHITE)) | |
39 | + _edgeTable(IdxLine(edge)) = stat | |
40 | + Return | |
41 | + End If | |
30 | 42 | |
43 | + edge(count) = DiscColor.EMPTY | |
44 | + GenerateEdge(edge, count + 1) | |
45 | + edge(count) = DiscColor.BLACK | |
46 | + GenerateEdge(edge, count + 1) | |
47 | + edge(count) = DiscColor.WHITE | |
48 | + GenerateEdge(edge, count + 1) | |
49 | + | |
31 | 50 | End Sub |
32 | 51 | |
33 | - Public Function Evaluate(board As AIBoard) As Integer Implements Evaluator.Evaluate | |
34 | - 'Dim edgestat As EdgeStat | |
35 | - 'Dim cornerstat As CornerStat | |
36 | - 'Dim result As Integer | |
52 | + Private Function evalEdge(ByVal line() As Integer, ByVal color As DiscColor) As EdgeParam | |
53 | + Debug.Assert(line.Count = Board.SIZE_X) | |
54 | + Dim edgeparam As New EdgeParam | |
55 | + If line(0) = DiscColor.EMPTY AndAlso line(7) = DiscColor.EMPTY Then | |
56 | + Dim x As Integer = 2 | |
57 | + While x <= 5 | |
58 | + If line(x) <> color Then | |
59 | + Exit While | |
60 | + End If | |
61 | + x += 1 | |
62 | + End While | |
63 | + If x = 6 Then | |
64 | + '少なくともブロックができている。 | |
65 | + If line(1) = color AndAlso line(6) = DiscColor.EMPTY Then | |
66 | + edgeparam.Wing = 1 | |
67 | + ElseIf line(1) = DiscColor.EMPTY AndAlso line(6) = color Then | |
68 | + edgeparam.Wing = 1 | |
69 | + ElseIf line(1) = color AndAlso line(6) = color Then | |
70 | + edgeparam.Mountain = 1 | |
71 | + End If | |
72 | + Else | |
73 | + If line(1) = color Then | |
74 | + edgeparam.CMove += 1 | |
75 | + End If | |
76 | + If line(6) = color Then | |
77 | + edgeparam.CMove += 1 | |
78 | + End If | |
79 | + End If | |
80 | + End If | |
81 | + For x As Integer = 0 To line.Count - 1 | |
82 | + If line(x) <> color Then | |
83 | + Exit For | |
84 | + End If | |
85 | + edgeparam.Stable += 1 | |
86 | + Next | |
87 | + If edgeparam.Stable < 8 Then | |
88 | + For x = line.Count - 1 To 0 Step -1 | |
89 | + If line(x) <> color Then | |
90 | + Exit For | |
91 | + End If | |
92 | + edgeparam.Stable += 1 | |
93 | + Next | |
94 | + End If | |
37 | 95 | |
38 | - 'edgestat = EdgeTable(idxTop(board)) | |
96 | + Return edgeparam | |
97 | + End Function | |
39 | 98 | |
40 | - Dim liberty As ColorStorage = CountLiberty(board) | |
41 | - Return EvalWeight.LibertyWeight * board.CurrentColor * liberty(DiscColor.BLACK) - liberty(DiscColor.WHITE) | |
99 | + Private Function EvalCourner(ByVal board As AIBoard) As CornerStat | |
100 | + Dim stat As New CornerStat | |
101 | + stat(DiscColor.BLACK).Corner = 0 | |
102 | + stat(DiscColor.BLACK).XMove = 0 | |
103 | + stat(DiscColor.WHITE).Corner = 0 | |
104 | + stat(DiscColor.WHITE).XMove = 0 | |
42 | 105 | |
106 | + stat(board.Cells(1, 1)).Corner += 1 | |
107 | + If board.Cells(1, 1) = DiscColor.EMPTY Then | |
108 | + stat(board.Cells(2, 2)).XMove += 1 | |
109 | + End If | |
110 | + | |
111 | + stat(board.Cells(8, 1)).Corner += 1 | |
112 | + If board.Cells(8, 1) = DiscColor.EMPTY Then | |
113 | + stat(board.Cells(7, 2)).XMove += 1 | |
114 | + End If | |
115 | + | |
116 | + stat(board.Cells(8, 8)).Corner += 1 | |
117 | + If board.Cells(8, 8) = DiscColor.EMPTY Then | |
118 | + stat(board.Cells(7, 7)).XMove += 1 | |
119 | + End If | |
120 | + | |
121 | + stat(board.Cells(1, 8)).Corner += 1 | |
122 | + If board.Cells(1, 8) = DiscColor.EMPTY Then | |
123 | + stat(board.Cells(2, 7)).XMove += 1 | |
124 | + End If | |
125 | + | |
126 | + Return stat | |
43 | 127 | End Function |
44 | 128 | |
129 | + Public Function Evaluate(ByVal board As AIBoard) As Integer Implements Evaluator.Evaluate | |
130 | + Dim edgestat As EdgeStat = New EdgeStat | |
131 | + edgestat.Add(EdgeTable(IdxTop(board))) | |
132 | + edgestat.Add(EdgeTable(IdxBottom(board))) | |
133 | + edgestat.Add(EdgeTable(IdxRight(board))) | |
134 | + edgestat.Add(EdgeTable(IdxLeft(board))) | |
135 | + | |
136 | + Dim cornerstat As CornerStat = EvalCourner(board) | |
137 | + | |
138 | + '確定石に関して、隅の石を2回数えているので補正 | |
139 | + edgestat(DiscColor.BLACK).Stable -= cornerstat(DiscColor.BLACK).Corner | |
140 | + edgestat(DiscColor.WHITE).Stable -= cornerstat(DiscColor.WHITE).Corner | |
141 | + | |
142 | + Dim result As Integer = | |
143 | + (edgestat(DiscColor.BLACK).Stable - edgestat(DiscColor.WHITE).Stable) * EvalWeight.StableWeight + | |
144 | + (edgestat(DiscColor.BLACK).Wing - edgestat(DiscColor.WHITE).Wing) * EvalWeight.WingWeight + | |
145 | + (cornerstat(DiscColor.BLACK).XMove - cornerstat(DiscColor.WHITE).XMove) * EvalWeight.XMoveWeight + | |
146 | + (edgestat(DiscColor.BLACK).CMove - edgestat(DiscColor.WHITE).CMove) * EvalWeight.CMoveWeight | |
147 | + If EvalWeight.LibertyWeight <> 0 Then | |
148 | + Dim liberty As ColorStorage = CountLiberty(board) | |
149 | + result += (liberty(DiscColor.BLACK) - liberty(DiscColor.WHITE)) * EvalWeight.LibertyWeight | |
150 | + End If | |
151 | + | |
152 | + result += board.CurrentColor * board.MovablePostions.Count * EvalWeight.MobilityWeight | |
153 | + | |
154 | + Return result | |
155 | + | |
156 | + End Function | |
157 | + | |
45 | 158 | Private Function IdxTop(ByVal board As AIBoard) As Integer |
46 | 159 | Dim index As Integer = 0 |
47 | 160 | Dim m As Integer = 1 |
@@ -16,9 +16,11 @@ | ||
16 | 16 | Next |
17 | 17 | End Sub |
18 | 18 | |
19 | - Public Function GetData(ByVal color As DiscColor) As EdgeParam | |
20 | - Return data(color + 1) | |
21 | - End Function | |
19 | + Default ReadOnly Property GetData(ByVal color As DiscColor) As EdgeParam | |
20 | + Get | |
21 | + Return data(color + 1) | |
22 | + End Get | |
23 | + End Property | |
22 | 24 | |
23 | 25 | End Class |
24 | 26 |
@@ -1,5 +1,7 @@ | ||
1 | -Imports Microsoft.VisualStudio.TestTools.UnitTesting | |
1 | +Imports ReversiGame | |
2 | 2 | |
3 | +Imports Microsoft.VisualStudio.TestTools.UnitTesting | |
4 | + | |
3 | 5 | Imports ReversiGame.AI.Level2 |
4 | 6 | |
5 | 7 |
@@ -65,4 +67,46 @@ | ||
65 | 67 | Assert.AreEqual(1603, MidEvaluator.IdxLine({-1, 1, -1, 0, 1, 0, -1, 0})) |
66 | 68 | |
67 | 69 | End Sub |
70 | + | |
71 | + | |
72 | + '''<summary> | |
73 | + '''GenerateEdge のテスト | |
74 | + '''</summary> | |
75 | + <TestMethod(), _ | |
76 | + DeploymentItem("ReversiGame.exe")> _ | |
77 | + Public Sub GenerateEdgeTest() | |
78 | + Dim target As MidEvaluator_Accessor = New MidEvaluator_Accessor() ' TODO: 適切な値に初期化してください | |
79 | + Dim edge() As Integer = {0, 0, 0, 0, 0, 0, 0, 0} | |
80 | + target.GenerateEdge(edge, 0) | |
81 | + Assert.IsNotNull(target.EdgeTable(0)) | |
82 | + Assert.AreEqual(8, target.EdgeTable(0)(DiscColor.WHITE).Stable) | |
83 | + Assert.AreEqual(0, target.EdgeTable(0)(DiscColor.BLACK).Stable) | |
84 | + Assert.AreEqual(0, target.EdgeTable(0)(DiscColor.WHITE).CMove) | |
85 | + Assert.AreEqual(0, target.EdgeTable(0)(DiscColor.BLACK).CMove) | |
86 | + Assert.AreEqual(0, target.EdgeTable(3280)(DiscColor.BLACK).CMove) | |
87 | + | |
88 | + End Sub | |
89 | + | |
90 | + '''<summary> | |
91 | + '''evalEdge のテスト | |
92 | + '''</summary> | |
93 | + <TestMethod(), _ | |
94 | + DeploymentItem("ReversiGame.exe")> _ | |
95 | + Public Sub evalEdgeTest() | |
96 | + Dim target As MidEvaluator_Accessor = New MidEvaluator_Accessor() ' TODO: 適切な値に初期化してください | |
97 | + Dim line() As Integer = {0, 0, 0, 0, 0, 0, 0, 0} | |
98 | + Dim actual As EdgeParam | |
99 | + actual = target.evalEdge(line, DiscColor.BLACK) | |
100 | + Assert.AreEqual(0, actual.Stable) | |
101 | + Assert.AreEqual(0, actual.CMove) | |
102 | + Assert.AreEqual(0, actual.Wing) | |
103 | + Assert.AreEqual(0, actual.Mountain) | |
104 | + line = {0, 1, 0, 0, 0, 0, 1, 0} | |
105 | + actual = target.evalEdge(line, DiscColor.BLACK) | |
106 | + Assert.AreEqual(0, actual.Stable) | |
107 | + Assert.AreEqual(2, actual.CMove) | |
108 | + Assert.AreEqual(0, actual.Wing) | |
109 | + Assert.AreEqual(0, actual.Mountain) | |
110 | + | |
111 | + End Sub | |
68 | 112 | End Class |
@@ -86,12 +86,12 @@ | ||
86 | 86 | e.GetData(DiscColor.WHITE).Stable = 7 |
87 | 87 | e.GetData(DiscColor.BLACK).Wing = 9 |
88 | 88 | target.Add(e) |
89 | - Assert.AreEqual(0, target.GetData(DiscColor.BLACK).Stable) | |
90 | - Assert.AreEqual(4, target.GetData(DiscColor.BLACK).CMove) | |
91 | - Assert.AreEqual(0, target.GetData(DiscColor.BLACK).Mountain) | |
92 | - Assert.AreEqual(9, target.GetData(DiscColor.BLACK).Wing) | |
93 | - Assert.AreEqual(7, target.GetData(DiscColor.EMPTY).Mountain) | |
94 | - Assert.AreEqual(11, target.GetData(DiscColor.WHITE).Stable) | |
89 | + Assert.AreEqual(0, target(DiscColor.BLACK).Stable) | |
90 | + Assert.AreEqual(4, target(DiscColor.BLACK).CMove) | |
91 | + Assert.AreEqual(0, target(DiscColor.BLACK).Mountain) | |
92 | + Assert.AreEqual(9, target(DiscColor.BLACK).Wing) | |
93 | + Assert.AreEqual(7, target(DiscColor.EMPTY).Mountain) | |
94 | + Assert.AreEqual(11, target(DiscColor.WHITE).Stable) | |
95 | 95 | |
96 | 96 | End Sub |
97 | 97 | End Class |
@@ -65,7 +65,7 @@ | ||
65 | 65 | target.GetData(DiscColor.BLACK).Corner = 1 |
66 | 66 | target.GetData(DiscColor.WHITE).XMove = 2 |
67 | 67 | |
68 | - Assert.AreEqual(1, target.GetData(DiscColor.BLACK).Corner) | |
69 | - Assert.AreEqual(2, target.GetData(DiscColor.WHITE).XMove) | |
68 | + Assert.AreEqual(1, target(DiscColor.BLACK).Corner) | |
69 | + Assert.AreEqual(2, target(DiscColor.WHITE).XMove) | |
70 | 70 | End Sub |
71 | 71 | End Class |