public static Tuple <int, int> GetBlackBestMove(ReversiBoard board)
        {
            var availableMoves = board.GetAvailableMoves(Player.Black);

            if (!availableMoves.Any())
            {
                return(null);
            }

            var bestMove  = availableMoves.First();
            var bestScore = int.MinValue;
            var depth     = 0;

            foreach (var availableMove in availableMoves)
            {
                var moveRow    = availableMove.Item1;
                var moveColumn = availableMove.Item2;
                var boardCopy  = board.Clone();
                boardCopy.PlayMove(moveRow, moveColumn, Player.Black);
                var score = MaxPlay(boardCopy, depth + 1);
                if (score > bestScore)
                {
                    bestMove  = availableMove;
                    bestScore = score;
                }
            }

            return(new Tuple <int, int>(bestMove.Item1, bestMove.Item2));
        }
        private static int MinPlay(ReversiBoard board, int depth)
        {
            if (board.HasGameFinished() || depth == MaxDepthPerMove)
            {
                return(board.EvaluateScore());
            }

            var availableMoves = board.GetAvailableMoves(Player.White);
            var bestScore      = int.MaxValue;

            foreach (var availableMove in availableMoves)
            {
                var boardCopy = board.Clone();
                boardCopy.PlayMove(availableMove.Item1, availableMove.Item2, Player.White);
                var score = MaxPlay(boardCopy, depth + 1);
                if (score < bestScore)
                {
                    bestScore = score;
                }
            }

            return(bestScore);
        }