Esempio n. 1
0
 protected Player(BoardColors boardColor)
 {
     if ((boardColor != BoardColors.Black) && (boardColor != BoardColors.White))
     {
         throw new ArgumentException("Invalid board color.");
     }
     this.boardColor = boardColor;
 }
Esempio n. 2
0
        /// <summary>
        /// Calculate the heuristic for the state of the board, recursively.
        /// </summary>
        /// <param name="board">The current state of the board in the search.</param>
        /// <param name="depth">The current depth of the search.</param>
        /// <param name="nodesVisitedCount">The total number of nodes visited.</param>
        /// <param name="move">The best move.</param>
        /// <returns>The heuristic for this node in the search.</returns>
        private int CalculateMiniMaxHeuristic(Board board, int depth,
                                              ref int nodesVisitedCount, out Move move)
        {
            // safety-check the board parameter
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }

            bool        myTurn       = board.CurrentColor == BoardColor;
            BoardColors currentColor = myTurn ? BoardColor :
                                       (BoardColor == BoardColors.White ? BoardColors.Black : BoardColors.White);
            int heuristic = myTurn ? Int32.MaxValue * -1 : Int32.MaxValue;

            nodesVisitedCount++;
            move = new Move(-1, -1);

            // cut short the algorithm if it's time to give up
            if (nodesVisitedCount >= nodesVisitedLimit)
            {
                return(0);
            }

            // at the bottom of the tree, just calculate the value
            if (depth <= 0)
            {
                return(CalculateMiniMaxHeuristic(board));
            }

            for (int row = 0; row < board.BoardSize; row++)
            {
                for (int column = 0; column < board.BoardSize; column++)
                {
                    Move  newMove  = new Move(row, column);
                    Board newBoard = board.CheckMove(BoardColor, newMove);
                    if (newBoard != null)
                    {
                        Move deeperMove;                         // we only care about moves in the top level
                        int  newHeuristic = CalculateMiniMaxHeuristic(newBoard,
                                                                      depth - 1, ref nodesVisitedCount, out deeperMove);
                        if (nodesVisitedCount >= nodesVisitedLimit)
                        {
                            move = newMove;
                            return(0);
                        }
                        if ((myTurn && (newHeuristic > heuristic)) ||
                            (!myTurn && (newHeuristic < heuristic)))
                        {
                            move      = newMove;
                            heuristic = newHeuristic;
                        }
                    }
                }
            }

            return(heuristic);
        }
Esempio n. 3
0
		/// <summary>
		/// Create a new LocalPlayer object.
		/// </summary>
		/// <param name="boardColor">The color of this player.</param>
		/// <param name="playerIndex">The player index for this color.</param>
		/// <param name="boardSize"></param>
		public LocalPlayer( BoardColors boardColor, PlayerIndex playerIndex,
			int boardSize )
			: base( boardColor ) {
			if( ( playerIndex != PlayerIndex.One ) && ( playerIndex != PlayerIndex.Two ) ) {
				throw new ArgumentException( "Invalid player index." );
			}
			this.playerIndex = playerIndex;

			// start in the center of the board
			cursorPosition = new Point( boardSize / 2, boardSize / 2 );
		}
Esempio n. 4
0
        /// <summary>
        /// Create a new LocalPlayer object.
        /// </summary>
        /// <param name="boardColor">The color of this player.</param>
        /// <param name="playerIndex">The player index for this color.</param>
        /// <param name="boardSize"></param>
        public LocalPlayer(BoardColors boardColor, PlayerIndex playerIndex,
                           int boardSize)
            : base(boardColor)
        {
            if ((playerIndex != PlayerIndex.One) && (playerIndex != PlayerIndex.Two))
            {
                throw new ArgumentException("Invalid player index.");
            }
            this.playerIndex = playerIndex;

            // start in the center of the board
            cursorPosition = new Point(boardSize / 2, boardSize / 2);
        }
Esempio n. 5
0
        /// <summary>
        /// Get the number of pieces for the other color than the one passed.
        /// </summary>
        /// <param name="boardColor">The board color - black or white.</param>
        /// <returns>The number of spaces that don't the argument.</returns>
        public int GetOppositeColorCount(BoardColors boardColor)
        {
            switch (boardColor)
            {
            case BoardColors.Black:
                return(WhitePieceCount);

            case BoardColors.White:
                return(BlackPieceCount);

            default:
                throw new ArgumentException("Invalid board color.");
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Checks if a player has any valid move on the board.
 /// </summary>
 /// <param name="boardColor">The color of the player to check.</param>
 /// <returns>If true, a valid move exists.</returns>
 public bool HasValidMove(BoardColors boardColor)
 {
     for (int row = 0; row < boardSize; row++)
     {
         for (int column = 0; column < boardSize; column++)
         {
             if (IsValidMove(boardColor, new Move(row, column)))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
Esempio n. 7
0
        /// <summary>
        /// Checks if a move is valid.
        /// </summary>
        /// <param name="boardColor">The color of the player making the move.</param>
        /// <param name="move">The move.</param>
        /// <returns>If true, the move is valid.</returns>
        public bool IsValidMove(BoardColors boardColor, Move move)
        {
            // if it's not the right turn, it's not a valid move
            if (boardColor != currentColor)
            {
                return(false);
            }

            // if it's not empty, then it's never a possible move
            if (this[move.Row, move.Column] != BoardColors.Empty)
            {
                return(false);
            }

            // check for possible lines
            BoardColors otherColor = (currentColor == BoardColors.White) ?
                                     BoardColors.Black : BoardColors.White;

            for (int directionRow = -1; directionRow <= 1; directionRow++)
            {
                for (int directionColumn = -1; directionColumn <= 1; directionColumn++)
                {
                    int currentRow    = move.Row + 1 + directionRow;
                    int currentColumn = move.Column + 1 + directionColumn;
                    while (spaces[currentRow, currentColumn] == otherColor)
                    {
                        if (spaces[currentRow + directionRow,
                                   currentColumn + directionColumn] == currentColor)
                        {
                            return(true);
                        }
                        else if (spaces[currentRow + directionRow,
                                        currentColumn + directionColumn] == otherColor)
                        {
                            currentRow    += directionRow;
                            currentColumn += directionColumn;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 8
0
        /// <summary>
        /// Create an alternate version of the board where a certain move was made.
        /// </summary>
        /// <param name="boardColor">The color of the player making the move.</param>
        /// <param name="move">The move.</param>
        /// <returns>The board as of the new move.</returns>
        /// <remarks>Useful for previewing and AI algorithms.</remarks>
        public Board CheckMove(BoardColors boardColor, Move move)
        {
            // make sure it's a valid move
            if (!IsValidMove(boardColor, move))
            {
                return(null);
            }

            // create a copy of the existing board
            Board board = new Board(boardSize);

            board.blackPieceCount = blackPieceCount;
            board.whitePieceCount = whitePieceCount;
            board.currentColor    = currentColor;
            // array is of value type, so shallow is fine
            board.spaces = spaces.Clone() as BoardColors[, ];

            board.ApplyMove(boardColor, move);

            return(board);
        }
Esempio n. 9
0
        /// <summary>
        /// Pass to the next player instead of making a move.
        /// </summary>
        /// <param name="player">The color of the player passing.</param>
        public void Pass(BoardColors boardColor)
        {
            // safety-check the player
            if (boardColor != currentColor)
            {
                throw new InvalidOperationException("Move made out of turn.");
            }

            switch (boardColor)
            {
            case BoardColors.Black:
                blackPassed  = true;
                currentColor = BoardColors.White;
                break;

            case BoardColors.White:
                whitePassed  = true;
                currentColor = BoardColors.Black;
                break;
            }
        }
Esempio n. 10
0
 /// <summary>
 /// Create a new AI player object.
 /// </summary>
 /// <param name="boardColor">The color of this player.</param>
 public AiPlayer(BoardColors boardColor) : base(boardColor)
 {
 }
Esempio n. 11
0
		/// <summary>
		/// Apply a move to the board.
		/// </summary>
		/// <param name="boardColor">The color of the player making the move.</param>
		/// <param name="move">The move.</param>
		/// <remarks>
		/// The move is assumed to be valid before entering this function.
		/// </remarks>
		public void ApplyMove( BoardColors boardColor, Move move ) {
			// safety-check the player
			if( boardColor != currentColor ) {
				throw new InvalidOperationException( "Move made out of turn." );
			}

			// set the new piece
			lastMove = move;
			this[ move.Row, move.Column ] = currentColor;

			// flip lines in all directions
			BoardColors otherColor = BoardColors.Black;
			switch( boardColor ) {
				case BoardColors.Black:
					blackPassed = false;
					otherColor = BoardColors.White;
					break;

				case BoardColors.White:
					whitePassed = false;
					otherColor = BoardColors.Black;
					break;
			}
			for( int directionRow = -1; directionRow <= 1; directionRow++ ) {
				for( int directionColumn = -1; directionColumn <= 1; directionColumn++ ) {
					// use the spaces array to check as it includes the illegal boundary
					int currentRow = move.Row + 1 + directionRow;
					int currentColumn = move.Column + 1 + directionColumn;
					while( spaces[ currentRow, currentColumn ] == otherColor ) {
						if( spaces[ currentRow + directionRow,
							currentColumn + directionColumn ] == currentColor ) {
							while( spaces[ currentRow, currentColumn ] == otherColor ) {
								this[ currentRow - 1, currentColumn - 1 ] = currentColor;
								currentRow -= directionRow;
								currentColumn -= directionColumn;
							}
							break;
						} else if( spaces[ currentRow + directionRow,
							currentColumn + directionColumn ] == otherColor ) {
							currentRow += directionRow;
							currentColumn += directionColumn;
						} else {
							break;
						}
					}
				}
			}

			// it's now the other player's turn
			currentColor = otherColor;
		}
Esempio n. 12
0
		/// <summary>
		/// Checks if a move is valid.
		/// </summary>
		/// <param name="boardColor">The color of the player making the move.</param>
		/// <param name="move">The move.</param>
		/// <returns>If true, the move is valid.</returns>
		public bool IsValidMove( BoardColors boardColor, Move move ) {
			// if it's not the right turn, it's not a valid move
			if( boardColor != currentColor ) {
				return false;
			}

			// if it's not empty, then it's never a possible move
			if( this[ move.Row, move.Column ] != BoardColors.Empty ) {
				return false;
			}

			// check for possible lines
			BoardColors otherColor = ( currentColor == BoardColors.White ) ?
				BoardColors.Black : BoardColors.White;
			for( int directionRow = -1; directionRow <= 1; directionRow++ ) {
				for( int directionColumn = -1; directionColumn <= 1; directionColumn++ ) {
					int currentRow = move.Row + 1 + directionRow;
					int currentColumn = move.Column + 1 + directionColumn;
					while( spaces[ currentRow, currentColumn ] == otherColor ) {
						if( spaces[ currentRow + directionRow,
							currentColumn + directionColumn ] == currentColor ) {
							return true;
						} else if( spaces[ currentRow + directionRow,
							currentColumn + directionColumn ] == otherColor ) {
							currentRow += directionRow;
							currentColumn += directionColumn;
						} else {
							break;
						}
					}
				}
			}

			return false;
		}
Esempio n. 13
0
		/// <summary>
		/// Checks if a player has any valid move on the board.
		/// </summary>
		/// <param name="boardColor">The color of the player to check.</param>
		/// <returns>If true, a valid move exists.</returns>
		public bool HasValidMove( BoardColors boardColor ) {
			for( int row = 0; row < boardSize; row++ ) {
				for( int column = 0; column < boardSize; column++ ) {
					if( IsValidMove( boardColor, new Move( row, column ) ) ) {
						return true;
					}
				}
			}
			return false;
		}
Esempio n. 14
0
		protected Player( BoardColors boardColor ) {
			if( ( boardColor != BoardColors.Black ) && ( boardColor != BoardColors.White ) ) {
				throw new ArgumentException( "Invalid board color." );
			}
			this.boardColor = boardColor;
		}
Esempio n. 15
0
		/// <summary>
		/// Create an alternate version of the board where a certain move was made.
		/// </summary>
		/// <param name="boardColor">The color of the player making the move.</param>
		/// <param name="move">The move.</param>
		/// <returns>The board as of the new move.</returns>
		/// <remarks>Useful for previewing and AI algorithms.</remarks>
		public Board CheckMove( BoardColors boardColor, Move move ) {
			// make sure it's a valid move
			if( !IsValidMove( boardColor, move ) ) {
				return null;
			}

			// create a copy of the existing board
			Board board = new Board( boardSize );
			board.blackPieceCount = blackPieceCount;
			board.whitePieceCount = whitePieceCount;
			board.currentColor = currentColor;
			// array is of value type, so shallow is fine
			board.spaces = spaces.Clone() as BoardColors[ , ];

			board.ApplyMove( boardColor, move );

			return board;
		}
Esempio n. 16
0
		/// <summary>
		/// Get the number of pieces for the other color than the one passed.
		/// </summary>
		/// <param name="boardColor">The board color - black or white.</param>
		/// <returns>The number of spaces that don't the argument.</returns>
		public int GetOppositeColorCount( BoardColors boardColor ) {
			switch( boardColor ) {
				case BoardColors.Black:
					return WhitePieceCount;

				case BoardColors.White:
					return BlackPieceCount;

				default:
					throw new ArgumentException( "Invalid board color." );
			}
		}
Esempio n. 17
0
		/// <summary>
		/// Pass to the next player instead of making a move.
		/// </summary>
		/// <param name="player">The color of the player passing.</param>
		public void Pass( BoardColors boardColor ) {
			// safety-check the player
			if( boardColor != currentColor ) {
				throw new InvalidOperationException( "Move made out of turn." );
			}

			switch( boardColor ) {
				case BoardColors.Black:
					blackPassed = true;
					currentColor = BoardColors.White;
					break;

				case BoardColors.White:
					whitePassed = true;
					currentColor = BoardColors.Black;
					break;
			}
		}
Esempio n. 18
0
        /// <summary>
        /// Apply a move to the board.
        /// </summary>
        /// <param name="boardColor">The color of the player making the move.</param>
        /// <param name="move">The move.</param>
        /// <remarks>
        /// The move is assumed to be valid before entering this function.
        /// </remarks>
        public void ApplyMove(BoardColors boardColor, Move move)
        {
            // safety-check the player
            if (boardColor != currentColor)
            {
                throw new InvalidOperationException("Move made out of turn.");
            }

            // set the new piece
            lastMove = move;
            this[move.Row, move.Column] = currentColor;

            // flip lines in all directions
            BoardColors otherColor = BoardColors.Black;

            switch (boardColor)
            {
            case BoardColors.Black:
                blackPassed = false;
                otherColor  = BoardColors.White;
                break;

            case BoardColors.White:
                whitePassed = false;
                otherColor  = BoardColors.Black;
                break;
            }
            for (int directionRow = -1; directionRow <= 1; directionRow++)
            {
                for (int directionColumn = -1; directionColumn <= 1; directionColumn++)
                {
                    // use the spaces array to check as it includes the illegal boundary
                    int currentRow    = move.Row + 1 + directionRow;
                    int currentColumn = move.Column + 1 + directionColumn;
                    while (spaces[currentRow, currentColumn] == otherColor)
                    {
                        if (spaces[currentRow + directionRow,
                                   currentColumn + directionColumn] == currentColor)
                        {
                            while (spaces[currentRow, currentColumn] == otherColor)
                            {
                                this[currentRow - 1, currentColumn - 1] = currentColor;
                                currentRow    -= directionRow;
                                currentColumn -= directionColumn;
                            }
                            break;
                        }
                        else if (spaces[currentRow + directionRow,
                                        currentColumn + directionColumn] == otherColor)
                        {
                            currentRow    += directionRow;
                            currentColumn += directionColumn;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            // it's now the other player's turn
            currentColor = otherColor;
        }