C# winform GDI+ 五子棋 (二):根据博弈算法写的人机AI(抄的别人的)
作者:互联网
白棋是ai,最后ai走赢了。
根据博弈算法的一个AI。遍历深度6层,下子很慢。其实我是从别人的代码里复制的算法,改到自己上面用了。
这个博弈算法
class GameAI { /// <summary> /// 符合条件的落子点(周围有棋子) /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> private bool hasne(int x, int y) { for (int i = (x - 2 > 0 ? x - 2 : 0); i <= x + 2 && i < 18; ++i) for (int j = (y - 2 > 0 ? y - 2 : 0); j <= y + 2 && j < 18; ++j) // if (i != 0 || j != 0) if (CheckBoard.ChessPieces[i][j] != 0) return true; return false; } /// <summary> /// 生成待分析数组 /// </summary> private void generatepoint() { CheckBoard.BlankPieces.Clear(); for (int i = 0; i < 18; ++i) for (int j = 0; j < 18; ++j) if (CheckBoard.ChessPieces[i][j] == 0 && hasne(i, j)) { CheckBoard.BlankPieces.Add(new Piece(i, j)); } } /// <summary> /// 分数评估 /// </summary> /// <param name="number"></param> /// <param name="empty1"></param> /// <returns></returns> private int scoretable(int number, int empty1) { if (number >= 5) return 100000; else if (number == 4) { if (empty1 == 2) return 10000;//活 else if (empty1 == 1) return 1000;//死 } else if (number == 3) { if (empty1 == 2) return 1000; else if (empty1 == 1) return 100; } else if (number == 2) { if (empty1 == 2) return 100; else if (empty1 == 1) return 10; } else if (number == 1 && empty1 == 2) return 10; return 0; } /// <summary> /// 正斜线、反斜线、横、竖,均转成一维数组来计算 /// </summary> /// <param name="pieces"></param> /// <param name="flag"></param> /// <returns></returns> private int countscore(Piece[] pieces, int flag) { int scoretmp = 0; int empty1 = 0;//死活 int number = 0; //1:黑子 2:白子 if (pieces[0].Flag == 0) ++empty1; else if (pieces[0].Flag == flag) number++; for (int i = 1; i < pieces.Length; i++) { if (pieces[i] == null) break; if (pieces[i].Flag == flag) { number++; } else if (pieces[i].Flag == 0) { if (number == 0) empty1 = 1; else { scoretmp += scoretable(number, empty1 + 1); empty1 = 1; number = 0; } } else { scoretmp += scoretable(number, empty1); empty1 = 0; number = 0; } } scoretmp += scoretable(number, empty1); return scoretmp; } /// <summary> /// 评估函数 /// </summary> /// <returns></returns> public int evaluate_minmax_noalphabeta() { int scorecomputer = 0; int scorehumber = 0; //横排们 for (int j = 0; j < 18; j++) { Piece[] pieces = new Piece[18]; for (int i = 0; i < 18; ++i) pieces[i] = new Piece(i, j); scorecomputer += countscore(pieces, 2); scorehumber += countscore(pieces, 1); } //竖排们 for (int i = 0; i < 18; i++) { Piece[] pieces = new Piece[18]; for (int j = 0; j < 18; j++) pieces[j] = new Piece(i, j); scorecomputer += countscore(pieces, 2); scorehumber += countscore(pieces, 1); } //上半正斜线们 for (int i = 0; i < 18; ++i) { Piece[] pieces = new Piece[18]; for (int x = i, y = 0; x < 18 && y < 18; x++, y++) pieces[y] = new Piece(x, y); scorecomputer += countscore(pieces, 2); scorehumber += countscore(pieces, 1); } //下半正斜线们 for (int j = 1; j < 18; ++j) { Piece[] pieces = new Piece[18]; for (int x = 0, y = j; x < 18 && y < 18; y++, x++) pieces[x] = new Piece(x, y); scorecomputer += countscore(pieces, 2); scorehumber += countscore(pieces, 1); } //上半反斜线们 for (int i = 0; i < 18; i++) { Piece[] pieces = new Piece[18]; for (int y = i, x = 0; y >= 0 && x < 18; y--, x++) pieces[x] = new Piece(x, y); scorecomputer += countscore(pieces, 2); scorehumber += countscore(pieces, 1); } //下半反斜线们 for (int i = 1; i < 18; i++) { Piece[] pieces = new Piece[18]; for (int y = i, x = 14; y < 18 && x >= 0; x--, y++) pieces[14 - x] = new Piece(y, x); scorecomputer += countscore(pieces, 2); scorehumber += countscore(pieces, 1); } return scorecomputer - scorehumber; } /// <summary> /// 当max(电脑)走步时,max(电脑)应该考虑最好的情况 /// </summary> /// <param name="depth">递归深度</param> /// <returns></returns> private int max_noalphabeta(int depth) { int res = evaluate_minmax_noalphabeta(); int best = res; if (depth <= 0) { return res; } else { for (int i = 0; i < CheckBoard.BlankPieces.Count; i++) { Piece p = CheckBoard.BlankPieces[i]; CheckBoard.ChessPieces[p.X][p.Y] = 1; if (CheckBoard.isover(p.X, p.Y)) { CheckBoard.ChessPieces[p.X][ p.Y] = 0; return int.MaxValue; } RemoveBlankPiece(p); int temp = min_noalphabeta(--depth); if (temp > best) best = temp; CheckBoard.BlankPieces.Insert(i, p); CheckBoard.ChessPieces[p.X][ p.Y] = 0; } return best; } } /// <summary> /// 当min(人)走步时,人的最好情况 /// </summary> /// <param name="depth">递归深度</param> /// <returns></returns> private int min_noalphabeta(int depth) { int res = evaluate_minmax_noalphabeta(); int best = res; if (depth <= 0) { return res; } else { for (int i = 0; i < CheckBoard.BlankPieces.Count; i++) { Piece p = CheckBoard.BlankPieces[i]; CheckBoard.ChessPieces[p.X][ p.Y] = 1; if (CheckBoard.isover(p.X, p.Y)) { CheckBoard.ChessPieces[p.X][p.Y] = 0; return int.MinValue; } RemoveBlankPiece(p); int temp = max_noalphabeta(--depth); if (temp < best) best = temp; CheckBoard.BlankPieces.Insert(i, p); CheckBoard.ChessPieces[p.X][ p.Y] = 0; } return best; } } /// <summary> /// 人机博弈 /// </summary> /// <param name="depth">递归深度</param> /// <returns></returns> public List<Piece> Machine_Man_Game(int depth) { generatepoint(); List<Piece> bftPieces = new List<Piece>(); int AI_best = int.MinValue; for (int i = 0; i < CheckBoard.BlankPieces.Count; i++) { Piece p = CheckBoard.BlankPieces[i]; CheckBoard.ChessPieces[p.X][p.Y] = 2; if (CheckBoard.isover(p.X, p.Y)) { CheckBoard.ChessPieces[p.X][p.Y] = 0; bftPieces.Add(p); return bftPieces; } RemoveBlankPiece(p); int temp = min_noalphabeta(depth - 1); if (temp == AI_best) bftPieces.Add(p); if (temp > AI_best) { AI_best = temp; bftPieces.Clear(); bftPieces.Add(p); } CheckBoard.BlankPieces.Insert(i, p); CheckBoard.ChessPieces[p.X][ p.Y] = 0; } return bftPieces; } /// <summary> /// 消除空子队列中的一个 /// </summary> /// <param name="p"></param> private void RemoveBlankPiece(Piece p) { for (int i = 0; i < CheckBoard.BlankPieces.Count; i++) { if (p.X == CheckBoard.BlankPieces[i].X && p.Y == CheckBoard.BlankPieces[i].Y) CheckBoard.BlankPieces.RemoveAt(i); } } }View Code
标签:empty1,C#,18,五子棋,++,pieces,AI,int,Piece 来源: https://www.cnblogs.com/HelloQLQ/p/16535308.html