public void MiniMax() { FirstPlayer = -1; // FirstPlayer = -1; var s = new State(FirstPlayer); for (int i = 0; i < 9; i++) { Console.WriteLine(s.CreateScreen()); Console.WriteLine("Turn = {0}", s.NextPlayer == 1 ? '<' : '>'); int bestCard, bestY, bestX; if (i % 2 == 0) { SearchCount = 0; int score = alphaBeta(s, 9, int.MinValue, int.MaxValue, out bestCard, out bestY, out bestX); Console.WriteLine("score = {0}, search = {1}", score, SearchCount); } else { randomNextState(s); bestCard = MoveCard; bestY = MoveY; bestX = MoveX; } s = s.SetCardCopy(bestY, bestX, bestCard); Rule.Apply(s, bestY, bestX); s.FlipTurn(); } Console.WriteLine(s.CreateScreen()); }
private int alphaBeta(State state, int depth, int alpha, int beta, out int bestCard, out int bestY, out int bestX) { bestCard = -1; bestY = -1; bestX = -1; if (depth == 0 || isEnd(state)) { SearchCount++; return evaluate(state); } int bestScore = int.MinValue; int card, y, x; foreach (var next in nextState(state)) { int tmpCard = MoveCard, tmpY = MoveY, tmpX = MoveX; alpha = Math.Max(alpha, -alphaBeta(next, depth - 1, -beta, -alpha, out card, out y, out x)); if (bestScore < alpha) { bestScore = alpha; bestCard = tmpCard; bestY = tmpY; bestX = tmpX; } if (alpha >= beta) break; } return alpha; }
private static bool isEnd(State state) { for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { if (state.StagePlayer[y, x] == 0) return false; } } return true; }
public State(State state) { this.NextPlayer = state.NextPlayer; state.MyUsed.CopyTo(this.MyUsed, 0); state.EnUsed.CopyTo(this.EnUsed, 0); for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { this.StageOwner[y, x] = state.StageOwner[y, x]; this.StagePlayer[y, x] = state.StagePlayer[y, x]; this.StageCard[y, x] = state.StageCard[y, x]; } } }
private int evaluate(State state) { int my = 0, en = 0; for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { if (state.StagePlayer[y, x] == 1) my++; if (state.StagePlayer[y, x] == -1) en++; } } if (FirstPlayer == 1) { en++; } if (FirstPlayer == -1) { my++; } if (isEnd(state)) { return (my - en) * 100 * state.NextPlayer; } return (my - en) * state.NextPlayer; }
private State randomNextState(State state) { bool[] used; if (state.NextPlayer == 1) used = state.MyUsed; else used = state.EnUsed; var ret = new List<Func<State>>(); for (int card = 0; card < 5; card++) { if (used[card]) continue; for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { if (state.StagePlayer[y, x] != 0) continue; var next = state.SetCardCopy(y, x, card); Rule.Apply(next, y, x); next.FlipTurn(); int tmpCard = card; int tmpY = y; int tmpX = x; ret.Add(() => { MoveCard = tmpCard; MoveY = tmpY; MoveX = tmpX; return next; }); } } } return ret[rnd.Next(ret.Count)](); }
private IEnumerable<State> nextState(State state) { bool[] used; if (state.NextPlayer == 1) used = state.MyUsed; else used = state.EnUsed; for (int card = 0; card < 5; card++) { if (used[card]) continue; for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { if (state.StagePlayer[y, x] != 0) continue; var next = state.SetCardCopy(y, x, card); Rule.Apply(next, y, x); next.FlipTurn(); MoveCard = card; MoveY = y; MoveX = x; yield return next; } } } }
public State SetCardCopy(int y, int x, int cardIndex) { #if DEBUG checkYX(y, x); if (cardIndex < 0 || cardIndex >= 5) { throw new ArgumentException("cardIndex < 0 || cardIndex >= 5"); } if (StageOwner[y, x] != 0) { throw new ArgumentException("StageOwner[y, x] != 0"); } if (StagePlayer[y, x] != 0) { throw new ArgumentException("StagePlayer[y, x] != 0"); } if (NextPlayer == 1 && MyUsed[cardIndex]) { throw new ArgumentException("NextPlayer == 1 && MyUsed[cardIndex]"); } if (NextPlayer == -1 && EnUsed[cardIndex]) { throw new ArgumentException("NextPlayer == -1 && EnUsed[cardIndex]"); } #endif var state = new State(this); if (NextPlayer == 1) { state.MyUsed[cardIndex] = true; } else { state.EnUsed[cardIndex] = true; } state.StageOwner[y, x] = NextPlayer; state.StagePlayer[y, x] = NextPlayer; state.StageCard[y, x] = cardIndex; return state; }
public override void Apply(State state, int y, int x) { bool enemyExist = false; for (int i = 0; i < 4; i++) { int ny = y + dy[i]; int nx = x + dx[i]; if (isOutOfRange(ny, nx)) continue; if (state.StagePlayer[ny, nx] != state.NextPlayer * -1) continue; enemyExist = true; int mypower = state.GetPower(y, x, i); int enpower = state.GetPower(ny, nx, (i + 2) % 4); if (mypower > enpower) { state.FlipCard(ny, nx); } } if (enemyExist == false) return; bool applyPlus = false; int[] sum = new int[21]; for (int i = 0; i < 4; i++) { int ny = y + dy[i]; int nx = x + dx[i]; if (isOutOfRange(ny, nx)) continue; if (state.StagePlayer[ny, nx] == 0) continue; int mypower = state.GetPower(y, x, i); int enpower = state.GetPower(ny, nx, (i + 2) % 4); #if DEBUG if (mypower + enpower < 2) throw new Exception("mypower + enpower < 2"); if (mypower + enpower > 20) throw new Exception("mypower + enpower > 20"); #endif sum[mypower + enpower]++; } for (int i = 0; i <= 20; i++) { if (sum[i] >= 2) applyPlus = true; } if (applyPlus == false) return; for (int i = 0; i < 4; i++) { int ny = y + dy[i]; int nx = x + dx[i]; if (isOutOfRange(ny, nx)) continue; if (state.StagePlayer[ny, nx] == 0) continue; int mypower = state.GetPower(y, x, i); int enpower = state.GetPower(ny, nx, (i + 2) % 4); #if DEBUG if (mypower + enpower > 20) throw new Exception("mypower + enpower > 20"); #endif if (sum[mypower + enpower] < 2) continue; if (state.StagePlayer[ny, nx] == state.NextPlayer * -1) { state.FlipCard(ny, nx); } for (int j = 0; j < 4; j++) { int my = ny + dy[i]; int mx = nx + dx[i]; if (isOutOfRange(my, mx)) continue; if (state.StagePlayer[my, mx] != state.NextPlayer * -1) continue; int mypower2 = state.GetPower(ny, nx, j); int enpower2 = state.GetPower(my, mx, (j + 2) % 4); if (mypower2 > enpower2) { state.FlipCard(my, mx); } } } }
public abstract void Apply(State state, int y, int x);