/// <summary> /// 根据当前棋盘状态以及寻路玩家生成哈希字符串 /// </summary> /// <param name="ToHashChessBoard">当前棋盘状态</param> /// <param name="LookupPlayer">寻路玩家</param> /// <returns>哈希字符串</returns> public string GetHashCode_String(ChessBoard ToHashChessBoard, EnumNowPlayer LookupPlayer) { string HashBuff = ""; HashBuff += "P"; if (LookupPlayer == EnumNowPlayer.Player1) { HashBuff += "1"; } else { HashBuff += "2"; } HashBuff += "V"; HashBuff += ToHashChessBoard.VerticalBoardHashCode.ToString(); HashBuff += "H"; HashBuff += ToHashChessBoard.HorizontalBoardHashCode.ToString(); HashBuff += "P1L"; HashBuff += ToHashChessBoard.Player1Location.X.ToString(); HashBuff += ToHashChessBoard.Player1Location.Y.ToString(); HashBuff += "P2L"; HashBuff += ToHashChessBoard.Player2Location.X.ToString(); HashBuff += ToHashChessBoard.Player2Location.Y.ToString(); return(HashBuff); }
/// <summary> /// 根据当前局面拓展一个未拓展节点 /// </summary> /// <param name="ThisChessBoard">当前局面棋盘</param> /// <param name="FatherNode">父节点</param> public void Expand(ChessBoard ThisChessBoard, MonteCartoTreeNode FatherNode) { if (SonNode.Count == 0)//未拓展节点 { EnumNowPlayer PlayerSave = NowQuoridor.ReversePlayer(FatherNode.NodePlayer); NowQuoridor.Player_Now = PlayerSave; List <QuoridorAction> QABuff = NowQuoridor.ActionList; // QABuff = NowQuoridor.CreateActionList(ThisChessBoard, EnumNowPlayer.Player2); //QABuff = NowQuoridor.CreateActionList_ALL(ThisChessBoard); /*完全拓展*/ foreach (QuoridorAction QA in QABuff) { MonteCartoTreeNode MTSonNode = new MonteCartoTreeNode(); MTSonNode.NodePlayer = PlayerSave; MTSonNode.NodeAction = QA.PlayerAction; MTSonNode.ActionLocation.X = QA.ActionPoint.X; MTSonNode.ActionLocation.Y = QA.ActionPoint.Y; MTSonNode._P = QA.WholeScore; MTSonNode.FatherNode = FatherNode; SonNode.Add(MTSonNode); //if (QA.PlayerAction == NowAction.Action_PlaceHorizontalBoard || QA.PlayerAction == NowAction.Action_PlaceVerticalBoard) //{ // if (QA.OpponentScore - QA.SelfScore >= 5) // { // MTSonNode.IfWin = true; // SonNode = new List<MonteCartoTreeNode>(); // SonNode.Add(MTSonNode); // break; // } //} } } }
public QuoridorAction GetNextPolicy(Enum_PlayerType PlayerType, EnumNowPlayer Player, out string ErrorHint) { ErrorHint = ""; QuoridorAction NextPolicy = new QuoridorAction(NowAction.Action_Wait, new Point(-1, -1)); #region 玩家决策 if (PlayerType == Enum_PlayerType.Human) { while (!HumanPolicyFinish) { } ErrorHint = MousePointToPolicyPoint(HumanMouseClickPoint); if (ErrorHint == "OK") { NextPolicy.ActionPoint = HumanPolicyLocation; if (HumanPolicyAction == NowAction.Action_Move_Player1 || HumanPolicyAction == NowAction.Action_Move_Player2) { if (Player == EnumNowPlayer.Player1) { HumanPolicyAction = NowAction.Action_Move_Player1; } else { HumanPolicyAction = NowAction.Action_Move_Player2; } } NextPolicy.PlayerAction = HumanPolicyAction; HumanPolicyFinish = false; } } #endregion # region AI决策 else if (PlayerType == Enum_PlayerType.AI)
/// <summary> /// 创建一棵博弈树 /// </summary> /// <param name="RootNode">待生成树的根节点</param> /// <param name="ChessBoard_Init">初始棋盘状态</param> /// <param name="DepthMax_Set">博弈树深度</param> /// <param name="IfShowDebugLog">是否显示调试日志,默认不显示</param> public static void CreateGameTree(EnumNowPlayer PolicyPlayer, GameTreeNode RootNode, ChessBoard ChessBoard_Init, int DepthMax_Set, bool IfShowDebugLog = false) { try { Exception E = new Exception("最大深度设定错误!请设置为偶数!"); if (DepthMax_Set % 2 != 0)//必须是偶数 { throw E; } } catch (Exception e) { throw; } DepthMax = DepthMax_Set - 1; RootNode.PolicyPlayer = PolicyPlayer; if (SearchFrameWork == Enum_GameTreeSearchFrameWork.MinMax) { RootNode.ExpandNode_MinMax(ChessBoard_Init, RootNode);//3W数量级节点数 double MaxScore = -1000; foreach (GameTreeNode GTN in RootNode.SonNode) { if (MaxScore < GTN.score) { MaxScore = GTN.score; RootNode.NodePlayer = GTN.NodePlayer; RootNode.NodeAction = GTN.NodeAction; RootNode.score = MaxScore; } } } else { RootNode.NodeHashCode = GameTreeNode.InitChessBoardHashCode; RootNode.ExpandNode_ABPruning(ChessBoard_Init, RootNode, GameTreeNode.IfUseTanslationTable); double MaxScore = -1000; foreach (GameTreeNode GTN in RootNode.SonNode) { if (MaxScore < GTN.beta) { MaxScore = GTN.beta; RootNode.NodePlayer = GTN.NodePlayer; RootNode.NodeAction = GTN.NodeAction; RootNode.score = MaxScore; RootNode.NodeHashCode = GTN.NodeHashCode; } } InitChessBoardHashCode = RootNode.NodeHashCode; } if (IfShowDebugLog) { PrintGameTree(RootNode); } }
/// <summary> /// 构造函数,用来设定该博弈树节点的信息 /// </summary> public GameTreeNode(QuoridorAction Action_set, EnumNowPlayer Player_set, int depth_set, double alpha_set, double beta_set, double score_set) { NodeAction = Action_set; NodePlayer = Player_set; depth = depth_set; alpha = alpha_set; beta = beta_set; score = score_set; InitTranslationTable(); }
public QuoridorDecisionSystem(EnumNowPlayer PolicyPlayer_Set, Enum_DecisionAlgorithm UsedAlgorithm_Set, ABPurningPara ABPurningPara_Set) { UsedAlgorithm = UsedAlgorithm_Set; if (UsedAlgorithm == Enum_DecisionAlgorithm.AlphaBetaPurning) { ThisABPurningPara = ABPurningPara_Set; } PolicyPlayer = PolicyPlayer_Set; FormulaeListInit(); }
/// <summary> /// 计算某点的距离 /// </summary> /// <param name="Player">要检测哪个玩家会被这步挡板堵死</param> /// <param name="Location_row">某点的行</param> /// <param name="Location_col">某点的列</param> /// <returns></returns> public int CalDistance(ChessBoard ThisChessBoard, EnumNowPlayer Player, int Location_row, int Location_col) { int Row_Destination = 0; switch (Player) { case EnumNowPlayer.Player1: Row_Destination = 6; break; case EnumNowPlayer.Player2: Row_Destination = 0; break; default: break; } int Num_VBoard = 0, Num_HBoard = 0; for (int i = Location_row + 1; i <= Row_Destination; i++)//下扫 { if (ThisChessBoard.ChessBoardAll[i, Location_col].IfUpBoard) { Num_HBoard++; } } for (int i = Location_row - 1; i >= Row_Destination; i--)//上扫 { if (ThisChessBoard.ChessBoardAll[i + 1, Location_col].IfUpBoard) { Num_HBoard++; } } for (int i = Location_col - 1; i >= 0; i--)//左扫 { if (ThisChessBoard.ChessBoardAll[Location_row, i + 1].IfLeftBoard) { Num_VBoard++; } } for (int i = Location_col + 1; i <= 6; i++)//右扫 { if (ThisChessBoard.ChessBoardAll[Location_row, i - 1].IfLeftBoard) { Num_VBoard++; } } return(Num_HBoard + Num_VBoard); }
/// <summary> /// 将棋盘玩家位置状态转换成字符串 /// </summary> public string ChessBoardLocationToString(ChessBoard ThisChessBoard, EnumNowPlayer Player) { string LStr = ""; Point PlayerLocation = ThisChessBoard.Player1Location; if (Player == EnumNowPlayer.Player2) { PlayerLocation = ThisChessBoard.Player2Location; } if (Player == EnumNowPlayer.Player1) { LStr = "P1:"; } else { LStr = "P2:"; } LStr += PlayerLocation.X.ToString() + "," + PlayerLocation.Y.ToString(); return(LStr); }
/// <summary> /// 进行一次模拟(Simluation) /// </summary> /// <param name="InitChessBoard">当前决策节点局面</param> /// <param name="RootNode">根节点</param> public static void SimluationOnce(ChessBoard InitChessBoard, MonteCartoTreeNode RootNode) { #region 暂存挡板数量 int Board1Save = InitChessBoard.NumPlayer1Board; int Board2Save = InitChessBoard.NumPlayer2Board; #endregion if (RootNode.SonNode.Count == 0) //初始根节点 { RootNode.Expand(InitChessBoard, RootNode); //先拓展一次 } ChessBoard SimluationChessBoard = new ChessBoard(); ChessBoard.SaveChessBoard(ref SimluationChessBoard, InitChessBoard);//相当于拷贝了 MonteCartoTreeNode NextExpandNode = RootNode; while (true) { #region 提前终止局面检测 if (NextExpandNode.SonNode.Count == 1) { if (NextExpandNode.SonNode[0].IfWin) { double leaf_value = -1; if (JudgePlayer != NextExpandNode.SonNode[0].NodePlayer) { leaf_value = 1; } NextExpandNode.BackPropagation(leaf_value); break; } } #endregion /*选择*/ NextExpandNode = Select(NextExpandNode); #region 模拟落子 string Hint = NowQuoridor.QuoridorRule.Action(ref SimluationChessBoard , NextExpandNode.ActionLocation.X, NextExpandNode.ActionLocation.Y, NextExpandNode.NodeAction); try { if (Hint != "OK") { Exception e = new Exception(); } } catch (Exception) { throw; } if (NextExpandNode.NodePlayer == EnumNowPlayer.Player1) { if (NextExpandNode.NodeAction == NowAction.Action_PlaceVerticalBoard || NextExpandNode.NodeAction == NowAction.Action_PlaceHorizontalBoard) { SimluationChessBoard.NumPlayer1Board -= 2; } } else if (NextExpandNode.NodePlayer == EnumNowPlayer.Player2) { if (NextExpandNode.NodeAction == NowAction.Action_PlaceVerticalBoard || NextExpandNode.NodeAction == NowAction.Action_PlaceHorizontalBoard) { SimluationChessBoard.NumPlayer2Board -= 2; } } #endregion //SimluationChessBoard.DrawNowChessBoard(ref Form1.Gr, Form1.form1.ChessWhitePB, Form1.form1.ChessBlackPB); //Form1.form1.ChessBoardPB.Refresh(); //System.Threading.Thread.Sleep(500); string SucessHint = RuleEngine.CheckResult(SimluationChessBoard); if (SucessHint != "No success")//搜索到胜利节点了 { double leaf_value = -1; if (JudgePlayer == EnumNowPlayer.Player1 && SucessHint == "Player1 Success!") { leaf_value = 1; } if (JudgePlayer == EnumNowPlayer.Player2 && SucessHint == "Player2 Success!") { leaf_value = 1; } NextExpandNode.BackPropagation(leaf_value); break; } double dis_player1 = RuleEngine.AstarEngine.AstarRestart(SimluationChessBoard, EnumNowPlayer.Player1 , SimluationChessBoard.Player1Location.X, SimluationChessBoard.Player1Location.Y); double dis_player2 = RuleEngine.AstarEngine.AstarRestart(SimluationChessBoard, EnumNowPlayer.Player2 , SimluationChessBoard.Player2Location.X, SimluationChessBoard.Player2Location.Y); EnumNowPlayer Winner = EnumNowPlayer.Player1; # region 必赢必输局面检测 //if (dis_player1 >= 14 || dis_player2 >= 14)//某人步数过大 //{ // if (dis_player2 - dis_player1 >= 5) // { // Winner = EnumNowPlayer.Player2; // } //} //else if (SimluationChessBoard.NumPlayer2Board == 0 && SimluationChessBoard.NumPlayer1Board == 0)//挡板已用完 //{ // #region 是否存在跳棋检测(未写) // #endregion // if (dis_player2 - dis_player1 > 0) // { // Winner = EnumNowPlayer.Player2; // } //} //double leaf_value2 = -1; //if (JudgePlayer == EnumNowPlayer.Player1 && Winner == EnumNowPlayer.Player1)//下一步是P2走 //{ // leaf_value2 = 1; //} //if (JudgePlayer == EnumNowPlayer.Player2 && Winner == EnumNowPlayer.Player2)//下一步是P1走 //{ // leaf_value2 = 1; //} //NextExpandNode.BackPropagation(leaf_value2); #endregion /*拓展*/ NextExpandNode.Expand(SimluationChessBoard, NextExpandNode); }
/// <summary> /// 检测该挡板是否能被放下 /// </summary> /// <param name="WhichBoard">放置哪种挡板</param> /// <param name="Player">检测哪个玩家会被堵死</param> /// <param name="Location_row">玩家的位置行</param> /// <param name="Location_col">玩家的位置列</param> /// <returns>检测挡板结果</returns> public CheckBoardResult CheckBoard(ChessBoard ChessBoard_ToCheck, NowAction WhichBoard, EnumNowPlayer Player, int Location_row, int Location_col) { CheckBoardResult Result = new CheckBoardResult(); ChessBoard ThisChessBoard = ChessBoard_ToCheck; //if (WhichBoard == NowAction.Action_Move_Player1 || WhichBoard == NowAction.Action_Move_Player2) //{ // Result.HintStr = "OK"; // return Result; //} if (WhichBoard != NowAction.Action_Move_Player1 && WhichBoard != NowAction.Action_Move_Player2) { if (Player == EnumNowPlayer.Player1 && ChessBoard_ToCheck.NumPlayer1Board <= 0) { Result.HintStr = "Player1 No Board"; return(Result); } else if (Player == EnumNowPlayer.Player2 && ChessBoard_ToCheck.NumPlayer2Board <= 0) { Result.HintStr = "Player2 No Board"; return(Result); } } ///为了不改变原状态而暂存原状态以便后续恢复 ChessBoard ChessBoardBuff = new ChessBoard(); ChessBoard.SaveChessBoard(ref ChessBoardBuff, ThisChessBoard); //假设能放挡板 string Hint = Action(ref ThisChessBoard, Location_row, Location_col, WhichBoard); if (Hint == "OK") { int disbuff1 = 0, disbuff2 = 0; disbuff1 = AstarEngine.AstarRestart(ThisChessBoard, EnumNowPlayer.Player1 , ThisChessBoard.Player1Location.X, ThisChessBoard.Player1Location.Y); disbuff2 = AstarEngine.AstarRestart(ThisChessBoard, EnumNowPlayer.Player2 , ThisChessBoard.Player2Location.X, ThisChessBoard.Player2Location.Y); Result.P1Distance = disbuff1; Result.P2Distance = disbuff2; if (disbuff1 >= 999 && disbuff2 < 999) { Hint = "Player1 No Road!"; } else if (disbuff2 >= 999 && disbuff1 < 999) { Hint = "Player2 No Road!"; } else if (disbuff1 >= 999 && disbuff2 >= 999) { Hint = "Player1&Player2 No Road!"; } } if (Hint != "OK") { ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff); Result.HintStr = Hint; return(Result); } ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff); Result.HintStr = "OK"; return(Result); }
public static int DepthMax = 1000;///博弈树最大深度 /// <summary> /// 以极大极小搜索框架生成博弈树 /// </summary> /// <param name="ThisChessBoard">当前棋盘状态</param> /// <param name="ThisNode">当前博弈树节点</param> public void ExpandNode_MinMax(ChessBoard ThisChessBoard, GameTreeNode ThisNode) { ///暂存一些量以便恢复 EnumNowPlayer PlayerSave = NowQuoridor.ReversePlayer(ThisNode.NodePlayer); NowQuoridor.Player_Now = PlayerSave; List <QuoridorAction> QABuff = NowQuoridor.ActionList; QABuff = NowQuoridor.CreateActionList(ThisChessBoard, GameTreePlayer , ThisNode.NodeAction.ActionCheckResult.P1Distance , ThisNode.NodeAction.ActionCheckResult.P2Distance); foreach (QuoridorAction QA in QABuff) { #region 保存棋盘状态 ChessBoard ChessBoardBuff = new ChessBoard(); ChessBoard.SaveChessBoard(ref ChessBoardBuff, ThisChessBoard); #endregion #region 模拟落子 string Hint = NowQuoridor.QuoridorRule.Action(ref ThisChessBoard, QA.ActionPoint.X, QA.ActionPoint.Y, QA.PlayerAction); try { if (Hint != "OK") { Exception e = new Exception(); } } catch (Exception) { throw; } #endregion if (ThisNode.depth <= DepthMax) { CreateNewSon(ThisNode, new GameTreeNode(QA , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, ThisNode.beta, ThisNode.beta)); ExpandNode_MinMax(ThisChessBoard, ThisNode.SonNode.Last()); } else { CreateNewSon(ThisNode, new GameTreeNode(QA , PlayerSave, ThisNode.depth + 1, QA.WholeScore, QA.WholeScore, QA.WholeScore)); } #region 恢复棋盘状态 ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff); #endregion } if (ThisNode.NodePlayer == NowQuoridor.PlayerBuff)//MIN层 { double minvalue = 99999; foreach (GameTreeNode Son in ThisNode.SonNode) { if (Son.score < minvalue) { minvalue = Son.score; ThisNode.score = minvalue; } } } else //MAX层 { double maxvalue = -10000; foreach (GameTreeNode Son in ThisNode.SonNode) { if (Son.score > maxvalue) { maxvalue = Son.score; ThisNode.score = maxvalue; if (ThisNode.depth == 0)//根节点层 { ThisNode.NodeAction = Son.NodeAction; ThisNode.NodePlayer = Son.NodePlayer; } } } } }
/// <summary> /// 以Alpha-Beta剪枝框架并使用TranslationTable生成博弈树 /// </summary> /// <param name="ThisChessBoard">当前棋盘状态</param> /// <param name="ThisNode">当前博弈树节点</param> public void ExpandNode_ABPruning(ChessBoard ThisChessBoard, GameTreeNode ThisNode, bool IfUseTT = true) { if (IfUseTT) { bool IfInTT = false; TranslationTable.GameTreeNodeForHash HashNode1 = new TranslationTable.GameTreeNodeForHash(); HashNode1 = NodeTranslationTable.Search(ThisNode.NodeHashCode, ref IfInTT); if (ThisNode.depth != 0 && IfInTT && ThisNode.depth + RootDepth <= HashNode1.depth) { ThisNode.alpha = HashNode1.alpha; ThisNode.beta = HashNode1.beta; return; } } ///暂存一些量以便恢复 EnumNowPlayer PlayerSave = NowQuoridor.ReversePlayer(ThisNode.NodePlayer); NowQuoridor.Player_Now = PlayerSave; List <QuoridorAction> QABuff = NowQuoridor.ActionList; //QABuff = NowQuoridor.CreateActionList_ALL(ThisChessBoard, ThisNode.P1Distance, ThisNode.P2Distance); QABuff = NowQuoridor.CreateActionList(ThisChessBoard, GameTreePlayer , ThisNode.NodeAction.ActionCheckResult.P1Distance , ThisNode.NodeAction.ActionCheckResult.P2Distance); foreach (QuoridorAction QA in QABuff) { #region 保存棋盘状态 ChessBoard ChessBoardBuff = new ChessBoard(); ChessBoard.SaveChessBoard(ref ChessBoardBuff, ThisChessBoard); #endregion #region 模拟落子 string Hint = NowQuoridor.QuoridorRule.Action(ref ThisChessBoard, QA.ActionPoint.X, QA.ActionPoint.Y, QA.PlayerAction); try { if (Hint != "OK") { Exception e = new Exception(); } } catch (Exception) { throw; } if (QA.PlayerAction == NowAction.Action_PlaceHorizontalBoard || QA.PlayerAction == NowAction.Action_PlaceVerticalBoard) { if (PlayerSave == EnumNowPlayer.Player1) { ThisChessBoard.NumPlayer1Board -= 2; } else { ThisChessBoard.NumPlayer2Board -= 2; } } #endregion if (ThisNode.depth <= DepthMax) { CreateNewSon(ThisNode, new GameTreeNode(QA , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, ThisNode.beta, ThisNode.score)); if (IfUseTT) { long HashCodeBuff = NodeTranslationTable.NodeGetHashCode(ThisNode.NodeHashCode, QA, ChessBoardBuff);//ThisChessBoard已变,不能作为原棋盘传入,只能上一步的棋盘ChessBoardBuff ThisNode.SonNode.Last().NodeHashCode = HashCodeBuff; } ExpandNode_ABPruning(ThisChessBoard, ThisNode.SonNode.Last(), IfUseTT); } else { CreateNewSon(ThisNode, new GameTreeNode(QA , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, QA.WholeScore, QA.WholeScore)); } ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff); #region Min层 if (ThisNode.NodePlayer == PolicyPlayer) { if (ThisNode.SonNode.Last().alpha < ThisNode.beta) { ThisNode.beta = ThisNode.SonNode.Last().alpha; ThisNode.score = ThisNode.SonNode.Last().alpha; } } #endregion #region Max层 else { if (ThisNode.SonNode.Last().beta > ThisNode.alpha) { ThisNode.alpha = ThisNode.SonNode.Last().beta; ThisNode.score = ThisNode.SonNode.Last().beta; } } #endregion if (ThisNode.depth <= DepthMax && ThisNode.beta <= ThisNode.alpha)//剪枝 { #region 存入置换表 if (IfUseTT) { /*剪枝break前这个时刻该节点已经遍历完毕,可以加入置换表*/ TranslationTable.GameTreeNodeForHash HashNodeBuff = new TranslationTable.GameTreeNodeForHash(); HashNodeBuff.alpha = ThisNode.alpha; HashNodeBuff.beta = ThisNode.beta; HashNodeBuff.depth = ThisNode.depth + RootDepth; NodeTranslationTable.Add(ThisNode.NodeHashCode, HashNodeBuff); } #endregion break; } } #region 存入置换表 if (IfUseTT) { /*遍历完整个动作列表后可以加入置换表*/ TranslationTable.GameTreeNodeForHash HashNodeBuff2 = new TranslationTable.GameTreeNodeForHash(); HashNodeBuff2.alpha = ThisNode.alpha; HashNodeBuff2.beta = ThisNode.beta; HashNodeBuff2.depth = ThisNode.depth + RootDepth; NodeTranslationTable.Add(ThisNode.NodeHashCode, HashNodeBuff2); } #endregion }
public void QuoridorGame_Do() { #region 配置初始棋盘 //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[0, 3].GridStatus = Grid.GridInsideStatus.Empty; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[1, 3].GridStatus = Grid.GridInsideStatus.Have_Player1; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[6, 3].GridStatus = Grid.GridInsideStatus.Empty; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[5, 3].GridStatus = Grid.GridInsideStatus.Have_Player2; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[1, 3].IfUpBoard = true; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[1, 4].IfUpBoard = true; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[6, 2].IfUpBoard = true; //NowGame.QuoridorEva.ThisChessBoard.ChessBoardAll[6, 3].IfUpBoard = true; ////NowQuoridor.ThisChessBoard.ChessBoardAll[2, 3].IfLeftBoard = true; ////NowQuoridor.ThisChessBoard.ChessBoardAll[3, 3].IfLeftBoard = true; ////NowQuoridor.ThisChessBoard.ChessBoardAll[2, 4].IfLeftBoard = true; ////NowQuoridor.ThisChessBoard.ChessBoardAll[3, 4].IfLeftBoard = true; //NowGame.QuoridorEva.ThisChessBoard.NumPlayer1Board = 16 - 2; //NowGame.QuoridorEva.ThisChessBoard.NumPlayer2Board = 16 - 2; //NowGame.QuoridorEva.ThisChessBoard.Player1Location = new Point(1, 3); //NowGame.QuoridorEva.ThisChessBoard.Player2Location = new Point(5, 3); #endregion BlackBoardNumLB.Text = NowGame.QuoridorEva.ThisChessBoard.NumPlayer2Board.ToString(); WhiteBoardNumLB.Text = NowGame.QuoridorEva.ThisChessBoard.NumPlayer1Board.ToString(); //刷新初始棋盘 NowGame.QuoridorEva.ThisChessBoard.DrawNowChessBoard(ref Gr, ChessWhitePB, ChessBlackPB); ChessBoardPB.Refresh(); EnumNowPlayer NowPlayer = EnumNowPlayer.Player1; while (true) { string Hint = NowGame.DoOncePolicy(ref NowPlayer); if (Hint == "Player1 Success!" || Hint == "Player2 Success!") { NowGame.QuoridorEva.ThisChessBoard.DrawNowChessBoard(ref Gr, ChessWhitePB, ChessBlackPB); ChessBoardPB.Refresh(); MessageBox.Show(Hint); System.Environment.Exit(0); break; } else if (Hint != "OK") { TestTB.Text = Hint; #region 取消放置挡板 IfPlaceBoard = false; if (NowPlayer == EnumNowPlayer.Player1) { PlayerNowAction = NowAction.Action_Move_Player1; } if (NowPlayer == EnumNowPlayer.Player2) { PlayerNowAction = NowAction.Action_Move_Player2; } PlaceVerticalBoardBTN.Enabled = true; PlaceHorizontalBoardBTN.Enabled = true; IfShowFollow = false; VBoardPB.Visible = false; VBoardPB.Location = new Point(837, 569); HBoardPB.Visible = false; HBoardPB.Location = new Point(837, 569); #endregion continue; } #region 取消放置挡板 IfPlaceBoard = false; if (NowPlayer == EnumNowPlayer.Player1) { PlayerNowAction = NowAction.Action_Move_Player1; } if (NowPlayer == EnumNowPlayer.Player2) { PlayerNowAction = NowAction.Action_Move_Player2; } PlaceVerticalBoardBTN.Enabled = true; PlaceHorizontalBoardBTN.Enabled = true; IfShowFollow = false; VBoardPB.Visible = false; VBoardPB.Location = new Point(837, 569); HBoardPB.Visible = false; HBoardPB.Location = new Point(837, 569); #endregion if (NowPlayer == EnumNowPlayer.Player2 && NowGame.P1Type == QuoridorGame.Enum_PlayerType.AI) { NowGame.PolicyRootNodeList.Add(NowGame.NodeToTreeView); } else if (NowPlayer == EnumNowPlayer.Player1 && NowGame.P2Type == QuoridorGame.Enum_PlayerType.AI) { NowGame.PolicyRootNodeList.Add(NowGame.NodeToTreeView); } TestTB.Text = Hint; NowGame.QuoridorEva.ThisChessBoard.DrawNowChessBoard(ref Gr, ChessWhitePB, ChessBlackPB); ChessBoardPB.Refresh(); #region 更新状态提示界面 if (NowPlayer == EnumNowPlayer.Player1) { ActionPlayerLabel.Text = "白子"; BlackBoardNumLB.Text = NowGame.QuoridorEva.ThisChessBoard.NumPlayer2Board.ToString(); WhiteBoardNumLB.Text = NowGame.QuoridorEva.ThisChessBoard.NumPlayer1Board.ToString(); } if (NowPlayer == EnumNowPlayer.Player2) { ActionPlayerLabel.Text = "黑子"; BlackBoardNumLB.Text = NowGame.QuoridorEva.ThisChessBoard.NumPlayer2Board.ToString(); WhiteBoardNumLB.Text = NowGame.QuoridorEva.ThisChessBoard.NumPlayer1Board.ToString(); } #endregion } }
/// <summary> /// 重启A*寻路,最短路径保存在Player1MinRoad或Player2MinRoad中,返回最短路径长度 /// </summary> /// <param name="Player">寻路玩家</param> /// <param name="Location_row">该玩家所在位置行</param> /// <param name="Location_col">该玩家所在位置列</param> /// <returns>最短路径长度</returns> public int AstarRestart(ChessBoard ToAstarSearch, EnumNowPlayer Player, int Location_row, int Location_col) { //bool IfContains = false; System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); // 开始监视代码运行时间 /***************待测代码段****************/ //int TableSearchResult = 0; //string BoardHashCode = LookupRoadAlgorithm.ResultSaveTable.GetHashCode_String( // ToAstarSearch, Player); //if (ResultSaveTable.Search(BoardHashCode, ref TableSearchResult)) //{ // Console.WriteLine("此局面已在存储表中!K值:" + BoardHashCode + "V值:" + TableSearchResult.ToString()); // /***************待测代码段****************/ // stopwatch.Stop(); // 停止监视 // TimeSpan timespan = stopwatch.Elapsed; // 获取当前实例测量得出的总时间 // Console.WriteLine("存储表命中寻路用时:" + timespan.TotalMilliseconds.ToString() + "ms"); // //return TableSearchResult; // IfContains = true; //} //else //{ // /***************待测代码段****************/ // stopwatch.Stop(); // 停止监视 // TimeSpan timespan2 = stopwatch.Elapsed; // 获取当前实例测量得出的总时间 // Console.WriteLine("存储表查询费时:" + timespan2.TotalMilliseconds.ToString() + "ms"); //} //stopwatch.Restart(); /***************待测代码段****************/ Min_DistanceLength = 999; List <AstarList> InitAList = new List <AstarList>(); Astar_Stop = false; AstarList InitGrid = new AstarList(6, 0, 6, Location_row, Location_col); InitAList.Add(InitGrid); int distance = LookupRoad_Astar(ToAstarSearch, Player, InitGrid, 1, new List <AstarList>(), InitAList); /***************待测代码段****************/ stopwatch.Stop(); // 停止监视 TimeSpan timespan3 = stopwatch.Elapsed; // 获取当前实例测量得出的总时间 if (QuoridorEvalution.AIRunTime.Astar_s == 0) { QuoridorEvalution.AIRunTime.Astar_s = timespan3.TotalMilliseconds; } else { QuoridorEvalution.AIRunTime.Astar_s += timespan3.TotalMilliseconds; QuoridorEvalution.AIRunTime.Astar_s /= 2; } QuoridorEvalution.AIRunTime.AstarNum++; //if (!IfContains) // LookupRoadAlgorithm.ResultSaveTable.Add(BoardHashCode, Min_DistanceLength); return(Min_DistanceLength); }
/// <summary> /// 寻找路径长度——贪婪方法 /// </summary> /// <param name="Player"></param> /// <param name="Location_row"></param> /// <param name="Location_col"></param> /// <returns></returns> public int LookupRoad_Greedy(ChessBoard ThisChessBoard, EnumNowPlayer Player, int Location_row, int Location_col, List <Point> MovedPoint) { int Row_Destination = 0; #region 设置目的地行 switch (Player) { case EnumNowPlayer.Player1: Row_Destination = 6; break; case EnumNowPlayer.Player2: Row_Destination = 0; break; default: break; } #endregion #region 扫描是否有木板,用来减少搜索空间 bool flag_NoBoard = true; bool flag_UpNowBoard = true; bool flag_DownNowBoard = true; for (int i = Location_row + 1; i <= Row_Destination; i++)//下扫 { if (ThisChessBoard.ChessBoardAll[i, Location_col].IfUpBoard) { flag_DownNowBoard = false; break; } } for (int i = Location_row - 1; i >= Row_Destination; i--)//上扫 { if (ThisChessBoard.ChessBoardAll[i + 1, Location_col].IfUpBoard) { flag_UpNowBoard = false; break; } } if (flag_DownNowBoard && flag_UpNowBoard) { flag_NoBoard = true; } else { flag_NoBoard = false; } if (flag_NoBoard) { return(Math.Abs((Row_Destination - Location_row))); } #endregion #region 检查四周能移动的位置添加进P_List_Enable列表 //计算四周能移动的位置的距离 List <Point> P_List_Enable = new List <Point>(); //左 if (Location_col > 0 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col].IfLeftBoard) && !MovedPoint.Contains(new Point(Location_row, Location_col - 1))) { P_List_Enable.Add(new Point(Location_row, Location_col - 1)); } //右 if (Location_col < 6 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col + 1].IfLeftBoard) && !MovedPoint.Contains(new Point(Location_row, Location_col + 1))) { P_List_Enable.Add(new Point(Location_row, Location_col + 1)); } //上 if (Location_row > 0 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col].IfUpBoard) && !MovedPoint.Contains(new Point(Location_row - 1, Location_col))) { P_List_Enable.Add(new Point(Location_row - 1, Location_col)); } //下 if (Location_row < 6 && !(ThisChessBoard.ChessBoardAll[Location_row + 1, Location_col].IfUpBoard) && !MovedPoint.Contains(new Point(Location_row + 1, Location_col))) { P_List_Enable.Add(new Point(Location_row + 1, Location_col)); } if (P_List_Enable.Count == 0) { return(999); } #endregion #region 搜索树搜索策略——贪婪 int[] P_Dis = new int[P_List_Enable.Count]; int mindis = 999; int minindex = 0; //选择距离最近的点尝试 for (int i = 0; i < P_List_Enable.Count; i++) { P_Dis[i] = CalDistance(ThisChessBoard, Player, P_List_Enable[i].X, P_List_Enable[i].Y); if (P_Dis[i] < mindis) { mindis = P_Dis[i]; minindex = i; } } MovedPoint.Add(new Point(P_List_Enable[minindex].X, P_List_Enable[minindex].Y)); int dissum = 0; int disbuff = LookupRoad_Greedy(ThisChessBoard, Player, P_List_Enable[minindex].X, P_List_Enable[minindex].Y, MovedPoint); #endregion if (disbuff != 999) { dissum += disbuff; return(dissum); } return(999); }
/// <summary> /// A*寻路,最短路径保存在Player1MinRoad或Player2MinRoad中,返回最短路径长度 /// </summary> /// <param name="Player">寻路玩家</param> /// <param name="NowGrid">当前寻路的格子</param> /// <param name="num_renew">迭代次数</param> /// <param name="OpenList">Open列表</param> /// <param name="CloseList">Close列表</param> /// <returns></returns> public int LookupRoad_Astar(ChessBoard ThisChessBoard, EnumNowPlayer Player, AstarList NowGrid, int num_renew, List <AstarList> OpenList, List <AstarList> CloseList) { int Location_row = NowGrid.Grid_row; int Location_col = NowGrid.Grid_col; if (Astar_Stop == true) { return(Min_DistanceLength); } int Row_Destination = 0; #region 设置目的地行 switch (Player) { case EnumNowPlayer.Player1: Row_Destination = 6; break; case EnumNowPlayer.Player2: Row_Destination = 0; break; default: break; } #endregion #region 检查四周能移动的位置添加进P_List_Enable列表 //计算四周能移动的位置的距离 List <Point> P_List_Enable = new List <Point>(); //左 if (Location_col > 0 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col].IfLeftBoard)) { P_List_Enable.Add(new Point(Location_row, Location_col - 1)); } //右 if (Location_col < 6 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col + 1].IfLeftBoard)) { P_List_Enable.Add(new Point(Location_row, Location_col + 1)); } //上 if (Location_row > 0 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col].IfUpBoard)) { P_List_Enable.Add(new Point(Location_row - 1, Location_col)); } //下 if (Location_row < 6 && !(ThisChessBoard.ChessBoardAll[Location_row + 1, Location_col].IfUpBoard)) { P_List_Enable.Add(new Point(Location_row + 1, Location_col)); } #endregion #region 扫描是否有木板,用来减少搜索空间 bool flag_NoBoard = true; bool flag_UpNowBoard = true; bool flag_DownNowBoard = true; for (int k = Location_row + 1; k <= Row_Destination; k++)//下扫 { if (ThisChessBoard.ChessBoardAll[k, Location_col].IfUpBoard) { flag_DownNowBoard = false; break; } } for (int k = Location_row - 1; k >= Row_Destination; k--)//上扫 { if (ThisChessBoard.ChessBoardAll[k + 1, Location_col].IfUpBoard) { flag_UpNowBoard = false; break; } } if (flag_DownNowBoard && flag_UpNowBoard) { flag_NoBoard = true; } else { flag_NoBoard = false; } if (flag_NoBoard) { Astar_Stop = true; Min_DistanceLength = Math.Abs((Row_Destination - Location_row)) + CloseList.Last().G; #region 迭代寻找最短路径 List <Point> MinRoad; if (Player == EnumNowPlayer.Player1) { Player1MinRoad = new List <Point>(); MinRoad = Player1MinRoad; } else { Player2MinRoad = new List <Point>(); MinRoad = Player2MinRoad; } if (Location_row < Row_Destination) { for (int i = Row_Destination; i >= Location_row; i--) { MinRoad.Add(new Point(i, Location_col)); } } else { for (int i = Row_Destination; i <= Location_row; i++) { MinRoad.Add(new Point(i, Location_col)); } } AstarList ALBuff = CloseList.Last(); while (true) { if (ALBuff.Father != null) { MinRoad.Add(new Point(ALBuff.Father.Grid_row, ALBuff.Father.Grid_col)); ALBuff = ALBuff.Father; } else { break; } } #endregion return(Min_DistanceLength); } #endregion #region 搜索树搜索策略——A*算法 List <int> P_Dis = new List <int>(); for (int i = 0; i < P_List_Enable.Count; i++) { P_Dis.Add(999); } int minF = 9999; int minindex = 0; for (int i = 0; i < P_List_Enable.Count && i >= 0; i++) { int Hbuff = Math.Abs(P_List_Enable[i].X - Row_Destination); P_Dis[i] = Hbuff; int Gbuff = num_renew; int Fbuff = Hbuff + Gbuff; bool flag_InClose = false; //检测是否在Close列表里 for (int j = 0; j < CloseList.Count; j++) { if (P_List_Enable[i].X == CloseList[j].Grid_row && P_List_Enable[i].Y == CloseList[j].Grid_col) { P_List_Enable.Remove(P_List_Enable[i]); P_Dis.Remove(P_Dis[i]); i--; flag_InClose = true; break; } } if (flag_InClose) { continue; } bool flag_InOpen = false; //检测是否在Open列表里 for (int j = 0; j < OpenList.Count; j++) { if (P_List_Enable[i].X == OpenList[j].Grid_row && P_List_Enable[i].Y == OpenList[j].Grid_col) { P_List_Enable.Remove(P_List_Enable[i]); P_Dis.Remove(P_Dis[i]); i--; flag_InOpen = true; if (Gbuff < OpenList[j].G) { OpenList[j].G = Gbuff; OpenList[j].F = Fbuff; OpenList[j].H = Hbuff; OpenList[j].Father = NowGrid; } break; } } if (!flag_InOpen && !flag_InClose) { AstarList NewGrid = new AstarList(Hbuff, Gbuff, Fbuff, P_List_Enable[i].X, P_List_Enable[i].Y); NewGrid.Father = NowGrid; OpenList.Add(NewGrid); } } AstarList MinFGrid = new AstarList(-1, -1, -1, -1, -1); for (int i = 0; i < OpenList.Count; i++) { int Fbuff = OpenList[i].F; if (Fbuff < minF) { minF = Fbuff; minindex = i; MinFGrid = OpenList[i]; } } CloseList.Add(MinFGrid); int dislengthbuff = 0; if (MinFGrid.Grid_row == Row_Destination && Astar_Stop == false) { Min_DistanceLength += MinFGrid.G; Astar_Stop = true; return(Min_DistanceLength); } else { if (OpenList.Count > 0) { OpenList.Remove(MinFGrid); dislengthbuff = LookupRoad_Astar(ThisChessBoard, Player, MinFGrid, MinFGrid.G + 1, OpenList, CloseList); } else { return(999); } } #endregion return(dislengthbuff); }