Ejemplo n.º 1
0
        public static Evaluation CalculateBoardScore(Con4Board board, int depth)
        {
            int        score = 0;
            BoardState bs    = BoardState.ongoing;

            score += CalulateRowScores(board, ref bs);
            score += CalculateColumnScores(board, ref bs);
            score += CalculateDiagonalScores(board, ref bs);
            if (bs == BoardState.playerWon)
            {
                score = winScore - depth;
            }
            else if (bs == BoardState.enemyWon)
            {
                score = -winScore + depth;
            }
            else if (IsDraw(board))
            {
                bs    = BoardState.draw;
                score = 0;
            }
            return(new Evaluation()
            {
                boardState = bs, score = score
            });
        }
Ejemplo n.º 2
0
        private static int CalculateDiagonalScores(Con4Board board, ref BoardState bs)
        {
            int        score = 0;
            List <int> seq;

            // Positive line slopes
            for (int i = 0; i < 4; i++)
            {
                seq    = GenerateDiagonalSequence(board, i, boardHeight - 1, true);
                score += CalculateSequenceScore(seq, ref bs);
            }

            seq    = GenerateDiagonalSequence(board, 0, boardHeight - 2, true);
            score += CalculateSequenceScore(seq, ref bs);

            seq    = GenerateDiagonalSequence(board, 0, boardHeight - 3, true);
            score += CalculateSequenceScore(seq, ref bs);

            // Negative line slopes
            for (int i = 0; i < 4; i++)
            {
                seq    = GenerateDiagonalSequence(board, i, 0, false);
                score += CalculateSequenceScore(seq, ref bs);
            }

            seq    = GenerateDiagonalSequence(board, 0, 1, false);
            score += CalculateSequenceScore(seq, ref bs);

            seq    = GenerateDiagonalSequence(board, 0, 2, false);
            score += CalculateSequenceScore(seq, ref bs);

            return(score);
        }
        // Returns best score found for current player
        private static int MiniMaxSearch(BoardNode currentNode, int player, int depth, int a, int b)
        {
            if (MainClass.timesUp)
            {
                return(0); // Will not be used as this whole iteration is aborted
            }
            // End game if max depth reached or game is over
            if (depth == maxDepth || currentNode.eval.boardState != BoardState.ongoing)
            {
                return(currentNode.eval.score);
            }

            // Create and evaluate children
            List <BoardNode> boardNodes = new List <BoardNode>();

            foreach (int move in currentNode.board.GetPossibleMoves())
            {
                Con4Board  nextBoard = currentNode.board.SimulateMove(player, move);
                Evaluation nextEval  = CalculateBoardScore(nextBoard, depth + 1);
                boardNodes.Add(new BoardNode {
                    board = nextBoard, eval = nextEval
                });
            }

            // Orden them, most promising first
            if (player == MAXIMIZING)
            {
                boardNodes = boardNodes.OrderByDescending(x => x.eval.score).ToList();
            }
            else
            {
                boardNodes = boardNodes.OrderBy(x => x.eval.score).ToList();
            }

            int searchScore = player == MAXIMIZING ? int.MinValue : int.MaxValue;

            foreach (BoardNode boardNode in boardNodes)
            {
                if (player == MAXIMIZING)
                {
                    searchScore = Math.Max(searchScore, MiniMaxSearch(boardNode, MINIMIZING, depth + 1, a, b));
                    a           = Math.Max(a, searchScore);
                    if (a >= b)
                    {
                        break;
                    }
                }
                else
                {
                    searchScore = Math.Min(searchScore, MiniMaxSearch(boardNode, MAXIMIZING, depth + 1, a, b));
                    b           = Math.Min(b, searchScore);
                    if (b <= a)
                    {
                        break;
                    }
                }
            }
            return(searchScore);
        }
Ejemplo n.º 4
0
 private static bool IsDraw(Con4Board board)
 {
     for (int x = 0; x < boardWidth; x++)
     {
         if (board.grid[x, 0] == 0)
         {
             return(false);
         }
     }
     return(true);
 }
Ejemplo n.º 5
0
        private static List <int> GenerateDiagonalSequence(Con4Board board, int x, int y, bool positiveSlope)
        {
            List <int> seq = new List <int>();

            while (LegalPos(x, y))
            {
                seq.Add(board.grid[x, y]);
                x++;
                y += positiveSlope ? -1 : 1;
            }
            return(seq);
        }
Ejemplo n.º 6
0
        private static int CalculateColumnScores(Con4Board board, ref BoardState bs)
        {
            int score = 0;

            for (int x = 0; x < boardWidth; x++)
            {
                List <int> seq = new List <int>(boardHeight);
                for (int y = 0; y < boardHeight; y++)
                {
                    seq.Add(board.grid[x, y]);
                }
                score += CalculateSequenceScore(seq, ref bs);
            }
            return(score);
        }
Ejemplo n.º 7
0
        public override bool Equals(object obj) {
            /*Con4Board other = obj as Con4Board;
            if (other == null)
                return false;
                */
            if (obj.GetType() != GetType())
                return false;
            Con4Board other = obj as Con4Board;
            /*for (int x = 0; x < WIDTH; x++)
                for (int y = 0; y < HEIGHT; y++)
                    if (other.grid[x, y] != grid[x, y])
                        return false;*/

            // Iteration order to find differences early
            for(int y = HEIGHT-1; y >= 0; y--)
                for(int x = 0; x < WIDTH; x++)
                    if (other.grid[x, y] != grid[x, y])
                        return false;

            return true;
        }
Ejemplo n.º 8
0
 public Con4Board SimulateMove(int player, int move) {
     simulations++;
     Con4Board deepCopy = new Con4Board(grid);
     deepCopy.PlayMove(player, move);
     return deepCopy;
 }
        // Calls minimax for each possible move and returns best move
        public static int FindBestMove(Connect4Game connect4, Con4Board startBoard, int maxDepth)
        {
            MiniMaxAlphaBetaHeuristic.maxDepth = maxDepth;
            MiniMaxAlphaBetaHeuristic.connect4 = connect4;
            int player = MAXIMIZING;
            int a      = int.MinValue;
            int b      = int.MaxValue;

            List <MoveBoardNode> moveBoardNodes = new List <MoveBoardNode>();

            foreach (int move in startBoard.GetPossibleMoves())
            {
                Con4Board  nextBoard = startBoard.SimulateMove(player, move);
                Evaluation nextEval  = CalculateBoardScore(nextBoard, 1);
                BoardNode  boardNode = new BoardNode {
                    board = nextBoard, eval = nextEval
                };
                moveBoardNodes.Add(new MoveBoardNode {
                    move = move, boardNode = boardNode
                });
            }

            moveBoardNodes = moveBoardNodes.OrderByDescending(x => x.boardNode.eval.score).ToList(); // player is maximizing

            Console.WriteLine("\tMove scores {move, score}: ");
            Console.Write("\t");
            List <MoveScore> results = new List <MoveScore>();

            foreach (MoveBoardNode moveBoardNode in moveBoardNodes)
            {
                int searchScore = MiniMaxSearch(moveBoardNode.boardNode, MINIMIZING, 1, a, b);
                a = Math.Max(a, searchScore);
                if (a >= b)
                {
                    break;
                }

                Console.Write("{" + moveBoardNode.move + ", " + searchScore + "} ,  ");

                results.Add(new MoveScore()
                {
                    move = moveBoardNode.move, score = searchScore
                });
            }
            int maxScore = results.Max(x => x.score);

            if (Math.Abs(maxScore) > 900) // Either confident in win or in loss, don't search deeper
            {
                MainClass.gameOutcomeFinal = true;
            }
            if (results.Count(x => x.score > -900) == 1) // Only 1 viable option, just do it!
            {
                MainClass.gameOutcomeFinal = true;
            }
            int bestMove = results.Find(x => x.score == maxScore).move;

            //int decidedMove = DecideMove(results);
            Console.WriteLine("\tBest move: " + bestMove);
            Console.WriteLine("\tSimulations: " + Con4Board.simulations);
            Con4Board.simulations = 0;
            return(bestMove);
        }