/// <summary> /// Method called when the game passes control to this player /// </summary> /// <param name="game">Game object that this player belongs to</param> public override void PromptForMove(Game game) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Square bestSquare = null; float bestValue = float.MinValue; _playerOpponent = game.Players[0]; if (_playerOpponent == this) { _playerOpponent = game.Players[1]; } Random rand = new Random(); int equalSquares = 0; foreach (Square square in game.Board.Squares) { if (square.Owner == null) { square.Owner = this; float curValue = AlphaBetaPrune(game, int.MinValue, int.MaxValue, false); square.Owner = null; if (bestSquare == null || curValue > bestValue) { bestValue = curValue; bestSquare = square; equalSquares = 0; } else if (curValue == bestValue) { equalSquares++; if (rand.Next(0,equalSquares + 1) == 0) { bestValue = curValue; bestSquare = square; } } } } int curTurnTime = (int)stopwatch.ElapsedMilliseconds; int turnTimeDiff = _minTurnTime - curTurnTime; Move move = new Move(this, bestSquare); Action playMove = () => game.PlayMove(move); int sleepMs = Math.Max(0, turnTimeDiff); // Ensure that the AI waits at least the minTurnTime before playing a move, // making the AI seem more human-like in that it won't make all of its moves near instantaniously. _timer = new Timer(PlayMoveAfterDelayCallback, playMove, sleepMs, Timeout.Infinite); }