Exemple #1
0
        public override void onMyTurn()
        {
            base.onMyTurn();

            if (TotalTurn == 0)
            {
                System.Console.WriteLine($"AI Turn 1");
                bool isPutSuccessful = PutChess(GameDef.board_cell_length / 2, GameDef.board_cell_length / 2);

                RoleMgr.ChangeNextRole();
            }
            else
            {
                MinMaxSearchCount = 0;
                MinMaxSearchInfo bestPosInfo = MinMaxSearch(Model, MyChessType, true, 0, int.MinValue, int.MaxValue);

                System.Console.WriteLine($"MinMaxSearchCount = {MinMaxSearchCount.ToString()}");
                System.Console.WriteLine($"SearchHasResultCount = {SearchHasResultCount.ToString()}");
                System.Console.WriteLine($"Turn: {(TotalTurn + 1).ToString()}  {Name} Y = {bestPosInfo.Y.ToString()} X = {bestPosInfo.X.ToString() } Score = {bestPosInfo.Score.ToString()}");
                bestPosInfo.Model.PrintBoard();

                bool isPutSuccessful = PutChess(bestPosInfo.X, bestPosInfo.Y);
                RoleMgr.ChangeNextRole();
            }
        }
        public override void onMyTurn()
        {
            base.onMyTurn();

            if (TotalTurn == 1)
            {
                System.Console.WriteLine($"AI Turn 1");
                bool isPutSuccessful = PutChess(GameDef.board_cell_length / 2, GameDef.board_cell_length / 2);
            }
            else
            {
                MinMaxSearchCount = 0;
                MinMaxSearchInfo bestPosInfo = MinMaxSearch(Model, MyChessType, true, 0, int.MinValue, int.MaxValue);

                System.Console.WriteLine($"MinMaxSearchCount = {MinMaxSearchCount.ToString()}");
                System.Console.WriteLine($"SearchHasResultCount = {SearchHasResultCount.ToString()}");

                bool isPutSuccessful = PutChess(bestPosInfo.X, bestPosInfo.Y);
            }
        }
Exemple #3
0
        private MinMaxSearchInfo MinMaxSearch(Model pModel, ChessType chessType, bool isMaxLayer, int depth, int alpha, int beta)
        {
            MinMaxSearchCount++;
            int bestScore = isMaxLayer ? int.MinValue : int.MaxValue;
            MinMaxSearchInfo bestPosInfo = new MinMaxSearchInfo(-1, -1, bestScore);
            //Console.WriteLine($"depth: {depth} isMaxLayer: {isMaxLayer} MinMaxSearchCount: {MinMaxSearchCount.ToString()} alpha: {alpha.ToString()} beta: {beta}");

            //          y,   x,  score
            List <Tuple <int, int, int> > OrderPosScoreList = GetPossibleBestPosOrderList(pModel, chessType);

            foreach (Tuple <int, int, int> PosScoreTuple in OrderPosScoreList)
            {
                int y = PosScoreTuple.Item1;
                int x = PosScoreTuple.Item2;

                Model cloneModel = pModel.Clone() as Model;
                cloneModel.PutChessToBoard(x, y, chessType);

                bool isWin = false;
                bool isTie = false;

                int   tmpScore = 0;
                Model tmpModel;

                //when anyone win or tie, stop search
                ConnectStrategy connectStrategy = new ConnectStrategy(cloneModel);
                isWin = connectStrategy.IsWin(chessType);
                isTie = connectStrategy.IsTie();

                if (isWin)
                {
                    Console.WriteLine($"win happen");
                    SearchHasResultCount++;

                    MinMaxSearchInfo Info = new MinMaxSearchInfo(x, y, isMaxLayer ? int.MaxValue - 1 : int.MinValue + 1);
                    Info.Model = cloneModel;

                    return(Info);
                }

                if (depth == MinMaxSearchDepth || isTie)
                {
                    SearchHasResultCount++;
                    tmpScore = MyEvaluation.GetScore(cloneModel, MyChessType);

                    tmpModel = cloneModel;

                    //cloneModel.PrintBoard();
                    //Console.WriteLine($"y: {y}  x: {x} score: {score}");
                }
                else
                {
                    ChessType        nextChessType = Utility.GetOppositeChessType(chessType);
                    MinMaxSearchInfo info          = MinMaxSearch(cloneModel, nextChessType, !isMaxLayer, depth + 1, alpha, beta);

                    //===== alpha beta pruning =====
                    if (isMaxLayer)
                    {
                        alpha = Math.Max(alpha, info.Score);
                    }
                    else
                    {
                        beta = Math.Min(beta, info.Score);
                    }

                    if (alpha >= beta)
                    {
                        return(info);
                    }
                    //===============================

                    tmpScore = info.Score;
                    tmpModel = info.Model;
                }

                if (isMaxLayer)
                {
                    if (tmpScore > bestPosInfo.Score)
                    {
                        bestPosInfo.Score = tmpScore;
                        bestPosInfo.X     = x;
                        bestPosInfo.Y     = y;
                        bestPosInfo.Model = tmpModel;
                    }
                }
                else
                {
                    if (tmpScore < bestPosInfo.Score)
                    {
                        bestPosInfo.Score = tmpScore;
                        bestPosInfo.X     = x;
                        bestPosInfo.Y     = y;
                        bestPosInfo.Model = tmpModel;
                    }
                }


                if (depth == 0)
                {
                    Console.WriteLine($"y: {y}  x: {x} score: {tmpScore} depth: {depth}  MinMaxSearchCount = {MinMaxSearchCount.ToString()}");
                    //bestModel.PrintBoard();
                }
            }

            #region Not use find order list

            /*
             * for (int y = 0; y < GameDef.board_cell_length; y++)
             * {
             *  for (int x = 0; x < GameDef.board_cell_length; x++)
             *  {
             *      List<List<ChessType>> board = pModel.GetBoardByCopy();
             *      if (board[y][x] == ChessType.None && IsPosNeedSearch(board, x, y))
             *      {
             *          Model cloneModel = pModel.Clone() as Model;
             *          cloneModel.PutChessToBoard(x, y, chessType);
             *
             *          bool isWin = false;
             *
             *          int score = 0;
             *
             *          if (depth == MinMaxSearchDepth)
             *          {
             *              SearchHasResultCount++;
             *              score = MyEvaluation.GetScore(cloneModel, MyChessType);
             *
             *              //cloneModel.PrintBoard();
             *              //Console.WriteLine($"y: {y}  x: {x} score: {score}");
             *          }
             *          else
             *          {
             *              ConnectStrategy connectStrategy = new ConnectStrategy(cloneModel);
             *              isWin = connectStrategy.IsWin(chessType) || connectStrategy.IsTie();
             *
             *              //when anyone win, stop search
             *              //isWin = MyEvaluation.IsEndSearch(cloneModel, chessType);
             *
             *              if (isWin)
             *              {
             *                  score = MyEvaluation.GetScore(cloneModel, MyChessType);
             *              }
             *              else
             *              {
             *                  ChessType nextChessType = Utility.GetOppositeChessType(chessType);
             *                  MinMaxSearchInfo info = MinMaxSearch(cloneModel, nextChessType, !isMaxLayer, depth + 1, alpha, beta);
             *
             *                  if (isMaxLayer)
             *                      alpha = Math.Max(alpha, info.Score);
             *                  else
             *                      beta = Math.Min(beta, info.Score);
             *
             *                  if (alpha >= beta)
             *                      return info;
             *
             *                  score = info.Score;
             *              }
             *
             *          }
             *
             *          if (depth == 0)
             *          {
             *              Console.WriteLine($"y: {y}  x: {x} score: {score} depth: {depth}");
             *          }
             *
             *          if (isWin)
             *          {
             *              Console.WriteLine($"Win happen y: {y}  x: {x} score: {score} depth: {depth}");
             *          }
             *
             *          if (isMaxLayer)
             *          {
             *              if (score > bestPosInfo.Score)
             *              {
             *                  bestPosInfo.Score = score;
             *                  bestPosInfo.X = x;
             *                  bestPosInfo.Y = y;
             *              }
             *          }
             *          else
             *          {
             *              if (score < bestPosInfo.Score)
             *              {
             *                  bestPosInfo.Score = score;
             *                  bestPosInfo.X = x;
             *                  bestPosInfo.Y = y;
             *              }
             *          }
             *      }
             *  }
             * }
             */
            #endregion

            return(bestPosInfo);
        }
        private MinMaxSearchInfo MinMaxSearch(Model pModel, ChessType chessType, bool isMaxLayer, int depth, int alpha, int beta)
        {
            MinMaxSearchCount++;
            int bestScore = isMaxLayer ? -999 : 999;
            MinMaxSearchInfo bestPosInfo = new MinMaxSearchInfo(-1, -1, bestScore);

            Console.WriteLine($"depth: {depth} isMaxLayer: {isMaxLayer} MinMaxSearchCount: {MinMaxSearchCount.ToString()} alpha: {alpha.ToString()} beta: {beta}");

            for (int y = 0; y < GameDef.board_cell_length; y++)
            {
                for (int x = 0; x < GameDef.board_cell_length; x++)
                {
                    var board = pModel.GetBoardByCopy();
                    if (board[y][x] == ChessType.None)
                    {
                        Model cloneModel = pModel.Clone() as Model;
                        cloneModel.PutChessToBoard(x, y, chessType);

                        int         score       = 0;
                        BoradStatus boradStatus = GetBoardStatus(cloneModel, chessType);

                        if (boradStatus == BoradStatus.Nothing) //沒有勝負 繼續往下找
                        {
                            ChessType        nextChessType = Utility.GetOppositeChessType(chessType);
                            MinMaxSearchInfo info          = MinMaxSearch(cloneModel, nextChessType, !isMaxLayer, depth + 1, alpha, beta);

                            //--------- alpha-beta pruning ---------
                            if (isMaxLayer)
                            {
                                alpha = Math.Max(alpha, info.Score);
                            }
                            else
                            {
                                beta = Math.Min(beta, info.Score);
                            }

                            if (alpha >= beta)
                            {
                                return(info);
                            }
                            //--------------------------------------

                            score = info.Score;
                        }
                        else if (boradStatus == BoradStatus.Winlose)
                        {
                            SearchHasResultCount++;
                            score = MyChessType == chessType  ? 1 : -1;//If chess is mychessType get 1 point else get -1 point
                        }
                        else if (boradStatus == BoradStatus.Tie)
                        {
                            SearchHasResultCount++;
                            score = 0;
                        }

                        if (isMaxLayer)
                        {
                            if (score > bestPosInfo.Score)
                            {
                                bestPosInfo.Score = score;
                                bestPosInfo.X     = x;
                                bestPosInfo.Y     = y;
                            }
                        }
                        else
                        {
                            if (score < bestPosInfo.Score)
                            {
                                bestPosInfo.Score = score;
                                bestPosInfo.X     = x;
                                bestPosInfo.Y     = y;
                            }
                        }
                    }
                }
            }

            return(bestPosInfo);
        }