/// <summary> /// Undoes the last move, restoring the game to its state before the move was applied. /// </summary> public void UndoLastMove() { OthelloMove m = mMoveHistory.Last(); // Note: there is a bug in this code. if (!m.IsPass) { // Reset the board at the move's position. SetPlayerAtPosition(m.Position, 0); // Iterate through the move's recorded flipsets. foreach (var flipSet in mFlipSets.Last()) { BoardPosition pos = m.Position; // For each flipset, walk along the flipset's direction resetting pieces. for (int i = 0; i < flipSet.Count; i++) { pos = pos.Translate(flipSet.Direction); // At this moment, CurrentPlayer is actually the enemy of the move that // we are undoing, whose pieces we must restore. SetPlayerAtPosition(pos, CurrentPlayer); } } // Check to see if the second-to-last move was a pass; if so, set PassCount. if (mMoveHistory.Count > 1 && mMoveHistory[mMoveHistory.Count - 2].IsPass) { PassCount = 1; } } else { PassCount--; } // Reset the remaining game state. SetAdvantage(); mCurrentPlayer = -mCurrentPlayer; mMoveHistory.RemoveAt(mMoveHistory.Count - 1); mFlipSets.RemoveAt(mFlipSets.Count - 1); }
/// <summary> /// Undoes the last move, restoring the game to its state before the move was applied. /// </summary> public void UndoLastMove() { OthelloMove m = MoveHistory[MoveHistory.Count - 1]; // Note: there is a bug in this code. if (!m.IsPass) { // Reset the board at the move's position. mBoard[m.Position.Row, m.Position.Col] = 0; Value += mCurrentPlayer; // Iterate through the move's recorded flipsets. foreach (var flipSet in m.FlipSets) { BoardPosition pos = m.Position; // For each flipset, walk along the flipset's direction resetting pieces. for (int i = 1; i <= flipSet.Count; i++) { pos = pos.Translate(flipSet.RowDelta, flipSet.ColDelta); mBoard[pos.Row, pos.Col] = (sbyte)mCurrentPlayer; Value += 2 * mCurrentPlayer; } } // Check to see if the second-to-last move was a pass; if so, set PassCount. if (MoveHistory.Count > 1 && MoveHistory[MoveHistory.Count - 2].IsPass) { PassCount = 1; } } else { PassCount--; } // Reset the remaining game state. mCurrentPlayer = -mCurrentPlayer; MoveHistory.RemoveAt(MoveHistory.Count - 1); }
public void ApplyMove(OthelloMove m) { if (m == null) { throw new ArgumentNullException(nameof(m)); } List <FlipSet> currentFlips = new List <FlipSet>(); m.Player = CurrentPlayer; // If the move is a pass, then we do very little. if (m.IsPass) { PassCount++; } else { PassCount = 0; // Otherwise update the board at the move's position with the current player. SetPlayerAtPosition(m.Position, CurrentPlayer); mAdvantageValue += mCurrentPlayer; // Iterate through all 8 directions radially from the move's position. foreach (BoardDirection dir in BoardDirection.CardinalDirections) { // Repeatedly move in the selected direction, as long as we find "enemy" squares. BoardPosition newPos = m.Position; int steps = 0; do { newPos = newPos.Translate(dir); steps++; } while (PositionIsEnemy(newPos, CurrentPlayer)); // This is a valid direction of flips if we moved at least 2 squares, and ended in bounds and on a // "friendly" square. if (steps > 1 && GetPlayerAtPosition(newPos) == CurrentPlayer) { // Record a FlipSet for this direction currentFlips.Add(new FlipSet(dir, (sbyte)(steps - 1))); var reverse = -dir; // Repeatedly walk back the way we came, updating the board with the current player's piece. do { newPos = newPos.Translate(reverse); SetPlayerAtPosition(newPos, CurrentPlayer); mAdvantageValue += 2 * mCurrentPlayer; steps--; }while (steps > 1); } } } // Update the rest of the board state. mCurrentPlayer = -mCurrentPlayer; SetAdvantage(); mMoveHistory.Add(m); mFlipSets.Add(currentFlips); }
/// <summary> /// Applies the given move to the board state. /// </summary> /// <param name="m">a move that is assumed to be valid</param> public void ApplyMove(OthelloMove m) { // If the move is a pass, then we do very little. if (m.IsPass) { PassCount++; } else { PassCount = 0; // Otherwise update the board at the move's position with the current player. mBoard[m.Position.Row, m.Position.Col] = (sbyte)mCurrentPlayer; Value += mCurrentPlayer; // Iterate through all 8 directions radially from the move's position. for (int rDelta = -1; rDelta <= 1; rDelta++) { for (int cDelta = -1; cDelta <= 1; cDelta++) { if (rDelta == 0 && cDelta == 0) { continue; } // Repeatedly move in the selected direction, as long as we find "enemy" squares. BoardPosition newPos = m.Position; int steps = 0; do { newPos = newPos.Translate(rDelta, cDelta); steps++; } while (PositionInBounds(newPos) && PositionIsEnemy(newPos, mCurrentPlayer)); // This is a valid direction of flips if we moved at least 2 squares, and ended in bounds and on a // "friendly" square. if (steps > 1 && PositionInBounds(newPos) && mBoard[newPos.Row, newPos.Col] == mCurrentPlayer) { // Record this direction in the move's flipsets so the move can be undone. m.AddFlipSet( new OthelloMove.FlipSet() { RowDelta = rDelta, ColDelta = cDelta, Count = steps - 1 }); // The FlipSet constructor takes no parameters; this syntax allows us to construct a FlipSet // and initialize many of its properties in one expression. // Repeatedly walk back the way we came, updating the board with the current player's piece. newPos = newPos.Translate(-rDelta, -cDelta); while (steps > 1) { mBoard[newPos.Row, newPos.Col] = (sbyte)mCurrentPlayer; Value += 2 * mCurrentPlayer; newPos = newPos.Translate(-rDelta, -cDelta); steps--; } } } } } // Update the rest of the board state. mCurrentPlayer = -mCurrentPlayer; MoveHistory.Add(m); }