Wednesday, January 6, 2010

Checkers code

Click here to download the source code for checkers game mentioned in my previous post. It was developed in Visual C#.NET 2005.

The heuristic function is used to get the best possible move for computer at each of its turns. It works as follows:
- For each of the computer's pieces, there are 2 diagonally forward moves available if its a non-king piece and 2 diagonally forward moves and 2 diagonally backward moves are available if its a king piece.
- For each of these available moves, the diagonal distance to the nearest human piece is calculated using the function "EvaluateMove()".
- The diagonal distance value and coordinates of the move with the greatest diagonal distance is stored for the piece which is currently its best move.
- The previous steps are repeated for each of the computer's pieces.
- Finally, the best move of all the pieces are compared and the move with the highest distance is chosen by computer.

Here is the code that carry out these tasks:

public PlayerMove GetBestMove (Player pl)
{
int distance = 0;
int x = pl.X_Coordinate;
int y = pl.Y_Coordinate;
int []x_pos = new int[4];
int []y_pos = new int[4];
bool CanJump, MoveAvailable, HasAtleastOneMove = false;
int DiagDist = 0,MinDist = -10;

PlayerMove move = new PlayerMove();
move.player = pl;

x_pos[0] = x + 1; y_pos[0] = y + 1;
MoveAvailable = CheckMoveAvailability(x_pos [0], y_pos[0]);
CanJump = IsJumpAvailable(x_pos[0], y_pos[0], x_pos[0] + 1, y_pos[0] + 1, pl);

if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos [0] + 1;
move.New_Y_Coordinate = y_pos[0] + 1;
move.CapturedMove = true;
return move ;
}

DiagDist = EvaluateMove(x_pos[0],y_pos[0],x,y);
MinDist = DiagDist;
move.New_X_Coordinate = x_pos [0];
move.New_Y_Coordinate = y_pos[0];
move.Heuristic = MinDist;
move.CapturedMove = false;

}

x_pos[1] = x - 1; y_pos[1] = y + 1;
MoveAvailable = CheckMoveAvailability(x_pos[1], y_pos[1]);
CanJump = IsJumpAvailable(x_pos[1], y_pos[1], x_pos[1] - 1, y_pos[1] + 1, pl);
if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos[1] - 1;
move.New_Y_Coordinate = y_pos[1] + 1;
move.CapturedMove = true;
return move;
}

DiagDist = EvaluateMove(x_pos[1],y_pos[1],x,y);

if (MinDist < DiagDist) // Use of Heuristics
{
MinDist = DiagDist;
move.New_X_Coordinate = x_pos[1];
move.Heuristic = MinDist;
move.New_Y_Coordinate = y_pos[1];
move.CapturedMove = false;
}

}

if (pl.IsKing)
{
x_pos[2] = x + 1; y_pos[2] = y - 1;
MoveAvailable = CheckMoveAvailability(x_pos[2], y_pos[2]);
CanJump = IsJumpAvailable(x_pos[2], y_pos[2], x_pos[2] + 1, y_pos[2] - 1, pl);
if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos[2] + 1;
move.New_Y_Coordinate = y_pos[2] - 1;
move.CapturedMove = true;
return move;
}

DiagDist = EvaluateMove(x_pos[2], y_pos[2], x, y);

if (MinDist < DiagDist)
{
MinDist = DiagDist;
move.New_X_Coordinate = x_pos[2];
move.New_Y_Coordinate = y_pos[2];
move.Heuristic = MinDist;
move.CapturedMove = false;
}

}

x_pos[3] = x - 1; y_pos[3] = y - 1;
MoveAvailable = CheckMoveAvailability(x_pos[3], y_pos[3]);
CanJump = IsJumpAvailable(x_pos[3], y_pos[3], x_pos[3] - 1, y_pos[3] - 1, pl);

if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos[3] - 1;
move.New_Y_Coordinate = y_pos[3] - 1;
move.CapturedMove = true;
return move;
}

DiagDist = EvaluateMove(x_pos[3], y_pos[3], x, y);

if (MinDist < DiagDist)
{
MinDist = DiagDist;
move.New_X_Coordinate = x_pos[3];
move.Heuristic = MinDist;
move.New_Y_Coordinate = y_pos[3];
move.CapturedMove = false;
}

}
}
if (HasAtleastOneMove)
return move;
else
return null;

}


private int EvaluateMove(int x, int y, int Current_X, int Current_Y)
{
int MinDistToOpponent = 0, temp = 0, distance = 0,temp_x, temp_y;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x + 1 == Current_X && temp_y + 1 == Current_Y)
{
temp = -1;
break;
}

if ((temp_x > 8) || (temp_y > 8))
{
distance = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
distance = temp;
break;
}

else
{
temp = temp + 1;
temp_x = temp_x + 1;
temp_y = temp_y + 1;
}
}

temp = 0;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x - 1 == Current_X && temp_y + 1 == Current_Y)
{
temp = -1;
break;
}


if ((temp_x < 1) || (temp_y > 8)) // No opponents in this path
{
temp = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
break;
}

else
{
temp = temp + 1;
temp_x = temp_x - 1;
temp_y = temp_y + 1;
}
}

if (distance > temp && temp != -1)
distance = temp;

temp = 0;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x + 1 == Current_X && temp_y - 1 == Current_Y)
{
temp = -1;
break;
}

if ((temp_x > 8 ) || (temp_y < 1)) // No opponents in this path
{
temp = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
break;
}

else
{
temp = temp + 1;
temp_x = temp_x + 1;
temp_y = temp_y - 1;
}
}

if (distance > temp && temp != -1)
distance = temp;

temp = 0;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x - 1 == Current_X && temp_y - 1 == Current_Y)
{
temp = -1;
break;
}

if ((temp_x < 1) || (temp_y < 1)) // No opponents in this path
{
temp = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
break;
}

else
{
temp = temp + 1;
temp_x = temp_x - 1;
temp_y = temp_y - 1;
}
}

if (distance > temp && temp != -1)
distance = temp;

return distance;
}

No comments:

Post a Comment