Skip to content

Commit 99e9085

Browse files
committed
Board & Minimax adjustments
The board now uses the BoardState class. Anomalies in the victory condition of the BoardState class have been fixed. The method to detect draws in the BoardState class has been verified. The Minimax evaluation function has been adjusted to prioritize AI wins over player wins.
1 parent 9ae767e commit 99e9085

13 files changed

+110
-287
lines changed

.vsconfig

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"version": "1.0",
3+
"components": [
4+
"Microsoft.VisualStudio.Workload.ManagedGame"
5+
]
6+
}

Assets/Scenes/Connect4.unity

+6-6
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ Transform:
212212
m_GameObject: {fileID: 779514239}
213213
serializedVersion: 2
214214
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
215-
m_LocalPosition: {x: -0.8059627, y: 2.6086996, z: 0.004360976}
215+
m_LocalPosition: {x: 0, y: 0, z: 0}
216216
m_LocalScale: {x: 1, y: 1, z: 1}
217217
m_ConstrainProportionsScale: 0
218218
m_Children: []
@@ -482,7 +482,7 @@ Transform:
482482
m_GameObject: {fileID: 1532549261}
483483
serializedVersion: 2
484484
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
485-
m_LocalPosition: {x: -0.8059627, y: 2.6086996, z: 0.004360976}
485+
m_LocalPosition: {x: 0, y: 0, z: 0}
486486
m_LocalScale: {x: 1, y: 1, z: 1}
487487
m_ConstrainProportionsScale: 0
488488
m_Children: []
@@ -527,7 +527,7 @@ Transform:
527527
m_GameObject: {fileID: 1725896831}
528528
serializedVersion: 2
529529
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
530-
m_LocalPosition: {x: -0.8059627, y: 2.6086996, z: 0.004360976}
530+
m_LocalPosition: {x: 0, y: 0, z: 0}
531531
m_LocalScale: {x: 1, y: 1, z: 1}
532532
m_ConstrainProportionsScale: 0
533533
m_Children: []
@@ -674,7 +674,7 @@ Transform:
674674
m_GameObject: {fileID: 1757537500}
675675
serializedVersion: 2
676676
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
677-
m_LocalPosition: {x: -0.8059627, y: 2.6086996, z: 0.004360976}
677+
m_LocalPosition: {x: 0, y: 0, z: 0}
678678
m_LocalScale: {x: 1, y: 1, z: 1}
679679
m_ConstrainProportionsScale: 0
680680
m_Children: []
@@ -692,7 +692,7 @@ MonoBehaviour:
692692
m_Script: {fileID: 11500000, guid: a8d35e9f770d4acda152a9ae7c26e36a, type: 3}
693693
m_Name:
694694
m_EditorClassIdentifier:
695-
depth: 9
695+
depth: 5
696696
--- !u!1 &2104119595
697697
GameObject:
698698
m_ObjectHideFlags: 0
@@ -733,7 +733,7 @@ Transform:
733733
m_GameObject: {fileID: 2104119595}
734734
serializedVersion: 2
735735
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
736-
m_LocalPosition: {x: -0.8059627, y: 2.6086996, z: 0.004360976}
736+
m_LocalPosition: {x: 0, y: 0, z: 0}
737737
m_LocalScale: {x: 1, y: 1, z: 1}
738738
m_ConstrainProportionsScale: 0
739739
m_Children: []

Assets/Scripts/AI/MiniMax.cs

+23-90
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Linq;
43
using Board;
54
using Interaction;
65
using UnityEngine;
@@ -18,15 +17,11 @@ private struct MiniMaxValue
1817
{
1918
public int Value;
2019
public int Column;
21-
public int Alpha;
22-
public int Beta;
2320

24-
public MiniMaxValue(int value, int column, int alpha, int beta)
21+
public MiniMaxValue(int value, int column)
2522
{
2623
Value = value;
2724
Column = column;
28-
Alpha = alpha;
29-
Beta = beta;
3025
}
3126
}
3227

@@ -44,34 +39,34 @@ public Column ExecuteAlgorithm(BoardInfo boardInfo)
4439

4540
int alpha = int.MinValue, beta = int.MaxValue;
4641
MiniMaxValue result = MiniMaxAlgorithm(startNode, depth-1, alpha, beta, Player.Max);
47-
Debug.Log($"Final:\n value: {result.Value}, column: {result.Column}");
42+
// Debug.Log($"Final:\n value: {result.Value}, column: {result.Column}");
4843
return boardInfo.Columns[result.Column];
4944
}
5045

5146
private MiniMaxValue MiniMaxAlgorithm(Node currentNode, int actualDepth, int alpha, int beta, Player player)
5247
{
53-
Debug.Log($"Depth: {actualDepth}");
48+
int column = 0;
49+
// Debug.Log($"Depth: {actualDepth}");
5450

5551
// Suspend
5652
if (currentNode.Draw() || actualDepth == 0)
5753
{
5854
int value = currentNode.Evaluate();
59-
int column = currentNode.ColumnSelected;
55+
column = currentNode.ColumnSelected;
6056

61-
Debug.Log($"Value: {value}");
62-
return new MiniMaxValue(value, column, alpha, beta);
57+
// Debug.Log($"Value: {value}");
58+
return new MiniMaxValue(value, column);
6359
}
6460

6561
List<Node> nodes = currentNode.CreateNodes();
66-
Debug.Log($"nodes: {nodes.Count}");
62+
// Debug.Log($"nodes: {nodes.Count}");
6763

6864
if (player == Player.Min)
6965
{
7066
int minEval = int.MaxValue;
71-
int column = 0;
7267
for (int i = 0; i < nodes.Count; ++i)
7368
{
74-
Debug.Log($"node: {nodes[i]}");
69+
// Debug.Log($"node: {nodes[i]}");
7570
if(nodes[i] == null) continue;
7671
MiniMaxValue eval = MiniMaxAlgorithm(nodes[i], actualDepth-1, alpha, beta, Player.Max);
7772
if (minEval > eval.Value)
@@ -81,19 +76,18 @@ private MiniMaxValue MiniMaxAlgorithm(Node currentNode, int actualDepth, int alp
8176
}
8277
beta = Math.Min(beta, eval.Value);
8378

84-
Debug.Log($"Depth: {actualDepth}, alpha: {alpha}, beta: {beta}, i: {i}");
79+
// Debug.Log($"Depth: {actualDepth}, alpha: {alpha}, beta: {beta}, i: {i}");
8580
if (alpha >= beta)
86-
return new MiniMaxValue(minEval,column,beta,alpha);
81+
return new MiniMaxValue(minEval,column);
8782
}
88-
return new MiniMaxValue(minEval,column,beta,alpha);
83+
return new MiniMaxValue(minEval,column);
8984
}
9085
else
9186
{
9287
int maxEval = int.MinValue;
93-
int column = 0;
9488
for (int i = 0; i < nodes.Count; ++i)
9589
{
96-
Debug.Log($"node: {nodes[i]}");
90+
// Debug.Log($"node: {nodes[i]}");
9791
if(nodes[i] == null) continue;
9892
MiniMaxValue eval = MiniMaxAlgorithm(nodes[i], actualDepth-1, alpha, beta, Player.Min);
9993
if (maxEval < eval.Value)
@@ -103,75 +97,14 @@ private MiniMaxValue MiniMaxAlgorithm(Node currentNode, int actualDepth, int alp
10397
}
10498
alpha = Math.Max(alpha, eval.Value);
10599

106-
Debug.Log($"Depth: {actualDepth}, alpha: {alpha}, beta: {beta}, " +
107-
$"column: {column}, maxEval: {maxEval} i: {i}");
100+
// Debug.Log($"Depth: {actualDepth}, alpha: {alpha}, beta: {beta}, " +
101+
// $"column: {column}, maxEval: {maxEval} i: {i}");
108102
if (alpha >= beta)
109-
return new MiniMaxValue(maxEval,column,beta,alpha);
103+
return new MiniMaxValue(maxEval,column);
110104
}
111-
return new MiniMaxValue(maxEval,column,beta,alpha);
105+
return new MiniMaxValue(maxEval,column);
112106
}
113107
}
114-
115-
private (int, int) MiniValue(Node currentNode, int actualDepth, int alpha, int beta)
116-
{
117-
Debug.Log($"Depth: {actualDepth}");
118-
119-
// Suspend
120-
if (currentNode.Draw() || actualDepth == 0)
121-
{
122-
int value = currentNode.Evaluate();
123-
Debug.Log($"Value: {value}");
124-
return (value, beta);
125-
}
126-
127-
List<Node> nodes = currentNode.CreateNodes();
128-
129-
int nodeAlpha = alpha;
130-
int nodeBeta = beta;
131-
132-
for (int i = 0; i < nodes.Count; ++i)
133-
{
134-
if(nodes[i] == null) continue;
135-
var (newBeta, newAlpha) = MaxValue(nodes[i], actualDepth-1, nodeAlpha, nodeBeta);
136-
beta = Math.Min(beta, newBeta);
137-
alpha = newAlpha;
138-
Debug.Log($"Depth: {actualDepth}, alpha: {alpha}, beta: {beta}");
139-
if (alpha >= beta)
140-
return (beta, alpha);
141-
}
142-
return (beta, alpha);
143-
}
144-
145-
private (int, int) MaxValue(Node currentNode, int actualDepth, int alpha, int beta)
146-
{
147-
Debug.Log($"Depth: {actualDepth}");
148-
149-
// Suspend
150-
if (currentNode.Draw() || actualDepth == 0)
151-
{
152-
int value = currentNode.Evaluate();
153-
Debug.Log($"Value: {value}");
154-
return (alpha, value);
155-
}
156-
157-
List<Node> nodes = currentNode.CreateNodes();
158-
159-
int nodeAlpha = alpha;
160-
int nodeBeta = beta;
161-
162-
for (int i = 0; i < nodes.Count; ++i)
163-
{
164-
if(nodes[i] == null) continue;
165-
166-
var (newBeta, newAlpha) = MiniValue(nodes[i], actualDepth-1, nodeAlpha, nodeBeta);
167-
alpha = Math.Max(alpha, newAlpha);
168-
beta = newBeta;
169-
Debug.Log($"Depth: {actualDepth}, alpha: {alpha}, beta: {beta}");
170-
if (alpha >= beta)
171-
return (beta, alpha);
172-
}
173-
return (beta, alpha);
174-
}
175108
}
176109

177110
public class Node
@@ -185,23 +118,23 @@ public Node(BoardInfo boardInfo, int turn)
185118
_boardState = new BoardState(boardInfo);
186119
_turn = turn;
187120
}
188-
189-
public Node(BoardState boardState, int turn)
121+
122+
private Node(BoardState boardState, int turn)
190123
{
191124
_boardState = new BoardState(boardState);
192125
_turn = turn;
193126
}
194127

195-
public bool Draw() => _boardState.Draw();
128+
public bool Draw() => false;
196129

197130
public int Evaluate()
198131
{
199132
bool player = _boardState.Winner((int)Player.Min);
200133
bool ai = _boardState.Winner((int)Player.Max);
201134

202-
Debug.Log($"{player}, {ai}");
203-
if(player) return -1000;
135+
// Debug.Log($"{player}, {ai}");
204136
if(ai) return 1000;
137+
if(player) return -1000;
205138
return UnityEngine.Random.Range(-100,100);
206139
}
207140

@@ -225,7 +158,7 @@ public List<Node> CreateNodes()
225158
Node node = new Node(_boardState, nextTurn);
226159
int disc = node._boardState.FirstDiscInColumn(i);
227160

228-
Debug.Log($"Disc: {disc}, Column: {_columnSelected}");
161+
// Debug.Log($"Disc: {disc}, Column: {_columnSelected}");
229162
node._boardState.AddDisc(disc, nextTurn);
230163
node._columnSelected = i;
231164
list.Add(node);

0 commit comments

Comments
 (0)