Untitled
unknown
plain_text
2 years ago
7.7 kB
6
Indexable
using Piskvorky_JanNeuC3a;
using System;
using System.Threading.Tasks;
namespace Piskvorky_JanNeuC3a
{
class ComputerPlayer : Player
{
private const Int32 BEST_VALUE = 1000;
private const Int32 WORST_VALUE = -1000;
private const Int32 VICTORY_VALUE = 10;
private event Action<Move> BestMoveFound;
private bool _isFirstTurn = true;
private Board.ElementType _computer = Board.ElementType.O;
private Board.ElementType _opponent = Board.ElementType.X;
private DifficultyType _difficulty;
public ComputerPlayer(DifficultyType difficulty)
{
_difficulty = difficulty;
BestMoveFound += ComputerPlayer_BestMoveFound;
}
private void ComputerPlayer_BestMoveFound(Move bestMove)
{
CurrentBoard[bestMove.Row, bestMove.Col] = _computer;
CurrentBoard.UpdateBoardUI();
}
protected override Task MakeTurnAsync()
{
Action action = () =>
{
if (PlayersTurn == TicTacToe.Turn.PlayerX)
{
_computer = Board.ElementType.X;
_opponent = Board.ElementType.O;
}
else
{
_isFirstTurn = false;
_computer = Board.ElementType.O;
_opponent = Board.ElementType.X;
}
var bestMove = new Move();
if (_isFirstTurn)
{
bestMove = Move.Random(0, 3, 0, 3);
_isFirstTurn = false;
}
else
{
var maxDepth = 0;
switch (_difficulty)
{
case DifficultyType.Easy:
maxDepth = 1;
break;
case DifficultyType.Medium:
maxDepth = 4;
break;
case DifficultyType.Hard:
maxDepth = 7;
break;
default:
break;
}
bestMove = FindBestMove(CurrentBoard, maxDepth);
}
BestMoveFound.Invoke(bestMove);
};
var task = Task.Factory.StartNew(action);
return task;
}
public override void OnPlayerMoved()
{
throw new NotImplementedException();
}
#region BestMoveCalculation
private Move FindBestMove(Board board, Int32 maxDepth)
{
Int32 bestVal = WORST_VALUE;
Move bestMove = new Move
{
Row = -1,
Col = -1
};
for (var i = 0; i < board.WIDTH; i++)
{
for (var j = 0; j < board.HEIGHT; j++)
{
if (board[i, j] == Board.ElementType.Empty)
{
board[i, j] = _computer;
Int32 moveVal = Minimax(board, 0, maxDepth, false);
board[i, j] = Board.ElementType.Empty;
if (moveVal > bestVal)
{
bestMove.Row = i;
bestMove.Col = j;
bestVal = moveVal;
}
}
}
}
return bestMove;
}
private Int32 Minimax(Board board, Int32 depth, Int32 maxDepth, bool isMax)
{
Int32 score = Evaluate(board);
if (score == VICTORY_VALUE || score == -VICTORY_VALUE)
return score - depth;
if (!board.IsMovesLeft() || depth == maxDepth)
return 0;
if (isMax)
{
Int32 best = WORST_VALUE;
for (Int32 i = 0; i < board.WIDTH; i++)
{
for (Int32 j = 0; j < board.HEIGHT; j++)
{
if (board[i, j] == Board.ElementType.Empty)
{
board[i, j] = _computer;
best = Math.Max(best,
Minimax(board, depth + 1, maxDepth, !isMax));
board[i, j] = Board.ElementType.Empty;
}
}
}
return best;
}
else
{
Int32 best = BEST_VALUE;
for (Int32 i = 0; i < board.WIDTH; i++)
{
for (Int32 j = 0; j < board.HEIGHT; j++)
{
if (board[i, j] == Board.ElementType.Empty)
{
board[i, j] = _opponent;
best = Math.Min(best, Minimax(board, depth + 1, maxDepth, !isMax));
board[i, j] = Board.ElementType.Empty;
}
}
}
return best;
}
}
private Int32 Evaluate(Board board)
{
for (var row = 0; row < board.WIDTH; row++)
{
if (board[row, 0] == board[row, 1] &&
board[row, 1] == board[row, 2])
{
if (board[row, 0] == _computer)
return VICTORY_VALUE;
else if (board[row, 0] == _opponent)
return -VICTORY_VALUE;
}
}
for (Int32 col = 0; col < board.HEIGHT; col++)
{
if (board[0, col] == board[1, col] &&
board[1, col] == board[2, col])
{
if (board[0, col] == _computer)
return VICTORY_VALUE;
else if (board[0, col] == _opponent)
return -VICTORY_VALUE;
}
}
if (board[0, 0] == board[1, 1] && board[1, 1] == board[2, 2])
{
if (board[0, 0] == _computer)
return VICTORY_VALUE;
else if (board[0, 0] == _opponent)
return -VICTORY_VALUE;
}
if (board[0, 2] == board[1, 1] && board[1, 1] == board[2, 0])
{
if (board[0, 2] == _computer)
return VICTORY_VALUE;
else if (board[0, 2] == _opponent)
return -VICTORY_VALUE;
}
return 0;
}
#endregion
private struct Move
{
public Int32 Row { get; set; }
public Int32 Col { get; set; }
public static Move Random(Int32 minRow, Int32 maxRow, Int32 minCol, Int32 maxCol)
{
Random random = new Random();
Int32 row = random.Next(minRow, maxRow);
Int32 col = random.Next(minCol, maxCol);
Move move = new Move()
{
Row = row,
Col = col
};
return move;
}
};
}
}Editor is loading...