/// <summary> /// Makes a move on this Connect 4 board at the specified move position /// </summary> /// <param name="move">The move to make</param> /// <returns>A reference to this Connect 4 board</returns> public override Board MakeMove(Move move) { C4Move m = (C4Move)move; //Make a move in the first available row in the column for (int y = 0; y < Height; y++) { if (boardContents[m.X, y] == 0) { //Make the move on this board boardContents[m.X, y] = CurrentPlayer; //Set the y position of the move m.SetY(y); //If this move made a column full, remove this column from the list of possible moves if (y == Height - 1) { possibleMoves.Remove(m); } //Determine if there is a winner DetermineWinner(m); //Swap out the current player CurrentPlayer = NextPlayer; //Call the MakeMove method on the Board base class, to save the last move made on this board return(base.MakeMove(move)); } } //If there are no available rows, raise an exception throw new InvalidMoveException("Tried to make a move in a full column"); }
/// <summary> /// Equality override for a Connect 4 move <para/> /// Two moves are equal if their x positions are equal /// </summary> /// <param name="obj">The other C4Move instance to compare this one too</param> /// <returns>True if the objects are equal, false otherwise</returns> public override bool Equals(object obj) { if (obj is C4Move) { C4Move other = (C4Move)obj; return(other.X == X); } return(false); }
/// <summary> /// Determine if the current game is over <para/> /// Uses knowledge of the last move to save computation time /// </summary> /// <param name="move">The last move made</param> protected override void DetermineWinner(Move move) { //This method seems a bit confusing, but it is just changing the worst case number of win checks from 196 to 16 C4Move m = (C4Move)move; //Get the current cells value int currentCell; //Check for a horizontal win //Check 3 cells infront and behind of this cell to determine if there is a winner for (int x = m.X; x >= m.X - 3 && x >= 0; x--) { currentCell = boardContents[x, m.Y]; if (x < Width - 3) { if (boardContents[x + 1, m.Y] == currentCell && boardContents[x + 2, m.Y] == currentCell && boardContents[x + 3, m.Y] == currentCell) { winner = CurrentPlayer; return; } } } //Check for a vertical win //Check 3 cells up and down from this cell to determine if there is a winner for (int y = m.Y; y >= m.Y - 3 && y >= 0; y--) { currentCell = boardContents[m.X, y]; if (y < Height - 3) { if (boardContents[m.X, y + 1] == currentCell && boardContents[m.X, y + 2] == currentCell && boardContents[m.X, y + 3] == currentCell) { winner = CurrentPlayer; return; } } } //Check for an upwards diagonal win //Check 3 cells down and left and 3 cells up and right from this cell to determine if there is a winner for (int y = m.Y, x = m.X; x >= m.X - 3 && y >= m.Y - 3 && x >= 0 && y >= 0; x--, y--) { currentCell = boardContents[x, y]; if (x < Width - 3 && y < Height - 3) { if (boardContents[x + 1, y + 1] == currentCell && boardContents[x + 2, y + 2] == currentCell && boardContents[x + 3, y + 3] == currentCell) { winner = CurrentPlayer; return; } } } //Check for a downwards diagonal win //Check 3 cells up and left and 3 cells down and right from this cell to determine if there is a winner for (int y = m.Y, x = m.X; x >= m.X - 3 && y <= m.Y + 3 && x >= 0 && y < Height; x--, y++) { currentCell = boardContents[x, y]; if (x < Width - 3 && y > 2) { if (boardContents[x + 1, y - 1] == currentCell && boardContents[x + 2, y - 2] == currentCell && boardContents[x + 3, y - 3] == currentCell) { winner = CurrentPlayer; return; } } } //If there are no possible moves left and there is still no winner, the game is a draw if (possibleMoves.Count == 0) { winner = 0; } }