Пример #1
0
        public override void Move(Board b)
        {
            {
                //Create a new game state for the root of the state space
                GameState gameState = new GameState(GameState.State.initial, b, this, null, cell, true);

                //Set the state as the root
                MiniMaxTree m = new MiniMaxTree(gameState);

                //Find children states if they exist
                m.GenerateStates(gameState, 4, true);

                //The value returned by the recursive minimax function
                int value = m.MiniMax(gameState, 4, true);

                cell = null;

                foreach(GameState child in gameState.GetChildren())
                {
                    if (child.GetHeuristicValue() == value)
                    {
                        cell = child.GetCell();
                    }
                }

                //Set the cell on the playing board
                b.getCell(cell.getRow(), cell.getColumn()).setState((int)cell.getState());

                //if a row exists above this cell, make it playable
                if (cell.getRow() != 0)
                {
                    b.getCell(cell.getRow() - 1, cell.getColumn()).isPlayable(true);
                }

                //Test if the game is over
                if(MiniMaxTree.TerminalTest(cell))
                {
                    b.printBoard();
                    Console.WriteLine("GameOver: " + this.getColorToString() + " wins");
                    b.isGameOver(true);
                }

                moveCount++;

            }
        }
Пример #2
0
        public GameState(State s, Board b, Player p, GameState parent, Cell c, Boolean mp)
        {
            maxPlayer = mp;
            state = s;
            cell = c;
            board = b;
            player = p;
            this.parent = parent;
            children = new List<GameState>();
            Region.findConnectedCells(b);
            b.UpdateCellObservers();

            if(MiniMaxTree.TerminalTest(cell) && state != GameState.State.initial)
            {
                state = GameState.State.terminal;

                if (maxPlayer)
                {
                    heuristicValue = MiniMaxTree.MIN_VALUE;
                }
                else
                    heuristicValue = MiniMaxTree.MAX_VALUE;
            }
        }
Пример #3
0
        public int FindHeuristicValue(GameState gs)
        {
            int value = 0;

            //The count of connectCells a cell contains
            int bestCount = 0;

            int connectR = Board.GetConnectR();

            if(gs.GetState().Equals(GameState.State.terminal))
            {
                return gs.GetHeuristicValue();
            }

            //if true it is maxPlayers turn and the board needs to be evaluate to minimize min's score
            if(gs.isMaxPlayer())
            {

                //check if max can make a killer move
                foreach(Cell cell in gs.GetBoard().getPlayerCells(gs.GetPlayer()))
                {
                    if(cell.isTerminal() > 0)
                    {
                        value = MAX_VALUE;
                        return value;
                    }
                }

                //check if it is impossible to prevent min from winning
                if(gs.GetCell().isTerminal() > 1)
                {
                    value = MIN_VALUE;
                    return value;
                }

                //check if min can make a killer move
                foreach (Cell cell in gs.GetBoard().getPlayerCells(gs.GetPlayer().getOpponent()))
                {
                    if (cell.isTerminal() == 1)
                    {
                        value = MIN_VALUE / 2;
                        return value;
                    }
                }

                //last resort - find the move that gives the most possibilites for connect 4
                foreach(Cell cell in gs.GetBoard().getPlayerCells(gs.GetPlayer()))
                {
                    int count = 0;

                    foreach(KeyValuePair<int, HashSet<Cell>> c in cell.GetObservers())
                    {
                        count = count + c.Value.Count;
                    }

                    foreach(KeyValuePair<int, List<Cell>> k in cell.GetConnectedCells())
                    {
                        count = count + k.Value.Count;
                    }

                    if(count > bestCount)
                    {
                        bestCount = count;
                    }
                }

                value = bestCount;

                return value;

            }

            //It is not max's turn
            else
            {

                //check if min can make a killer move
                foreach (Cell cell in gs.GetBoard().getPlayerCells(gs.GetPlayer().getOpponent()))
                {
                    if (cell.isTerminal() > 0)
                    {
                        value = MIN_VALUE;
                        return value;
                    }
                }

                //check if it is impossible to prevent max from winning
                if (gs.GetCell().isTerminal() > 1)
                {
                    value = MAX_VALUE;
                    return value;
                }

                //check if max can make a killer move
                foreach (Cell cell in gs.GetBoard().getPlayerCells(gs.GetPlayer()))
                {
                    if (cell.isTerminal() == 1)
                    {
                        value = MAX_VALUE / 2;
                        return value;
                    }
                }

            }

            //last resort - find the move that gives the most possibilites for connect 4
            foreach (Cell cell in gs.GetBoard().getPlayerCells(gs.GetPlayer().getOpponent()))
            {
                int count = 0;

                foreach (KeyValuePair<int, HashSet<Cell>> c in cell.GetObservers())
                {
                    count = count + c.Value.Count;
                }

                foreach (KeyValuePair<int, List<Cell>> k in cell.GetConnectedCells())
                {
                    count = count + k.Value.Count;
                }

                if (count > bestCount)
                {
                    bestCount = count;
                }
            }

            value = bestCount;
            return value;
        }
Пример #4
0
 public MiniMaxTree(GameState gs)
 {
     root = gs;
 }
Пример #5
0
        public int MiniMax(GameState gs, int depth, Boolean maxPlayer)
        {
            //base case
            if (depth == 0 || gs.GetState().Equals(GameState.State.terminal))
            {
                return FindHeuristicValue(gs);
            }

            if(maxPlayer)
            {
                int bestValue = MIN_VALUE;

                foreach(GameState child in gs.GetChildren())
                {
                    int value = MiniMax(child, depth - 1, false);

                    if (value.CompareTo(bestValue) > 0)
                    {
                        gs.SetHeuristicValue(value);
                        bestValue = value;
                    }
                }

                return bestValue;
            }
            else
            {
                int bestValue = MAX_VALUE;

                foreach (GameState child in gs.GetChildren())
                {
                    int value = MiniMax(child, depth - 1, true);

                    if(value.CompareTo(bestValue) < 0)
                    {
                        gs.SetHeuristicValue(value);
                        bestValue = value;
                    }
                }

                return bestValue;
            }
        }
Пример #6
0
        public void GenerateStates(GameState gs, int depth, Boolean maxPlayer)
        {
            if(depth == 0 || gs.GetState().Equals(GameState.State.terminal))
            {
                return;
            }

               gs.FindChildrenStates(maxPlayer);

               foreach(GameState child in gs.GetChildren())
               {
               if (maxPlayer)
               {
                   GenerateStates(child, depth - 1, false);
               }
               else
                   GenerateStates(child, depth - 1, true);
            }
        }
        // private methods
        private void gameOverCheck(int row, int column, out GameState gameState)
        {
            gameState = GameState.notWon;

            // check horizontal for a win
            checkHorizontal(row, column, out gameState);

            // check vertical for a win
            if (gameState == GameState.notWon)
            {
                checkVertical(row, column, out gameState);
            } // end if

            // check diagonal (up and right, down and left) for a win
            if (gameState == GameState.notWon)
            {
                checkDiagonal(row, column, out gameState);
            } // end if

            // check antidiagonal (up and left, down and right) for a win
            if (gameState == GameState.notWon)
            {
                checkAntiDiagonal(row, column, out gameState);
            } // end if

            // check to see if it is a draw
            if (gameState == GameState.notWon && numberOfMoves >= 42)
            {
                gameState = GameState.draw;
            } // end if
        }
        private void checkVertical(int row, int column, out GameState gameState)
        {
            gameState = GameState.notWon;
            int numberInARow = 1;
            bool noBreaks = true;

            // compare to the next one up
            int nextRow = row + 1; // row is y
            int nextColumn = column; // column is x

            while ((nextRow < gameBoard.GetLength(ROW)) && (numberInARow < 4) && (noBreaks)) // check up
            {
                compareColors(row, column, nextRow, nextColumn, ref numberInARow, ref noBreaks);
                nextRow++; // look at the next space up
            } // end while

            // reset the row to compare to the next one down
            nextRow = row - 1; // row is y
            noBreaks = true; // reset so we can look the other direction

            while ((nextRow >= 0) && (numberInARow < 4) && (noBreaks)) // check down
            {
                compareColors(row, column, nextRow, nextColumn, ref numberInARow, ref noBreaks);
                nextRow--; // look at the next space down
            } // end while

            if (numberInARow >= 4)
            {
                gameState = GameState.won;
            } // end if
        }
        private void checkHorizontal(int row, int column, out GameState gameState)
        {
            gameState = GameState.notWon;
            int numberInARow = 1;
            bool noBreaks = true;

            // compare to the next one on the right
            int nextRow = row; // row is y
            int nextColumn = column + 1; // column is x

            while ((nextColumn < gameBoard.GetLength(COLUMN)) && (numberInARow < 4) && (noBreaks)) // check to the right
            {
                compareColors(row, column, nextRow, nextColumn, ref numberInARow, ref noBreaks);
                nextColumn++; // look at the next space to the right
            } // end while

            // reset the column to compare to the next one on the left
            nextColumn = column - 1; // column is x
            noBreaks = true; // reset so we can look the other direction

            while ((nextColumn >= 0) && (numberInARow < 4) && (noBreaks)) // check to the left
            {
                compareColors(row, column, nextRow, nextColumn, ref numberInARow, ref noBreaks);
                nextColumn--; // look at the next space to the left
            } // end while

            if (numberInARow >= 4)
            {
                gameState = GameState.won;
            } // end if
        }
Пример #10
0
        private void checkDiagonal(int row, int column, out GameState gameState)
        {
            gameState = GameState.notWon;
            int numberInARow = 1;
            bool noBreaks = true;

            // row is y, column is x
            if (((row - column) < 3) && ((row + (6 - column)) > 2)) // make sure we are not comparing if it is in the top left or bottom right corner
            {
                // compare to the next one up and right
                int nextRow = row + 1; // row is y
                int nextColumn = column + 1; // column is x

                while (((nextRow < gameBoard.GetLength(ROW)) && (nextColumn < gameBoard.GetLength(COLUMN))) && (numberInARow < 4) && (noBreaks)) // check up and right
                {
                    compareColors(row, column, nextRow, nextColumn, ref numberInARow, ref noBreaks);
                    nextRow++; // look at the next space up
                    nextColumn++; // look at the next space to the right
                } // end while

                // reset the row to compare to the next one down and left
                nextRow = row - 1; // row is y
                nextColumn = column - 1;
                noBreaks = true; // reset so we can look the other direction

                while (((nextRow >= 0) && (nextColumn >= 0)) && (numberInARow < 4) && (noBreaks)) // check down and left
                {
                    compareColors(row, column, nextRow, nextColumn, ref numberInARow, ref noBreaks);
                    nextRow--; // look at the next space down
                    nextColumn--; // look at the next space to the left
                } // end while

                if (numberInARow >= 4)
                {
                    gameState = GameState.won;
                } // end if
            } // end if
        }
Пример #11
0
        public void FindChildrenStates(Boolean maxPlayer)
        {
            GameState gs;

            for(int i = 0; i < board.GetWidth(); i++)
            {
                for(int j = 0; j < board.GetLength(); j++)
                {
                    if(board.getCell(j,i).getState().Equals(Cell.CellState.empty))
                    {
                        if (board.getCell(j, i).isPlayable())
                        {
                            Board b = new Board(board);

                            Cell cell = b.getCell(j, i);

                            if (maxPlayer)
                            {
                                cell.setState(player.getColor());
                            }
                            else
                            {
                                cell.setState(player.getOpponent().getColor());
                            }

                            if (j != 0)
                            {
                                b.getCell(j - 1, i).isPlayable(true);
                            }

                            gs = new GameState(GameState.State.transition, b, player, this, cell, !maxPlayer);

                            children.Add(gs);
                        }
                    }
                    else
                        break;
                }

            }
        }
Пример #12
0
 public void SetState(GameState.State s)
 {
     state = s;
 }