Files
LEA2/CheckersSpielBot/GameService.cs
T
abdelaziz bc4118704e logic
2026-03-30 07:49:37 +02:00

192 lines
6.2 KiB
C#

namespace CheckersSpielBot
{
public class GameService
{
// 0=Empty | 1=Red | 2=Blue | 3=RedKing | 4=BlueKing
public int[,] Board { get; private set; } = new int[8, 8];
public int ActivePlayer { get; private set; } = 1;
public bool IsChainJumpActive { get; private set; } = false;
public int ChainJumpRow { get; private set; } = -1;
public int ChainJumpCol { get; private set; } = -1;
public HashSet<(int, int)> MandatoryCapturePieces { get; private set; } = new();
private MoveGeneratorService _moveGenerator;
public GameService()
{
_moveGenerator = new MoveGeneratorService(Board);
}
// Setup
public void InitializeNewGame()
{
Board = new int[8, 8];
ActivePlayer = 1;
IsChainJumpActive = false;
ChainJumpRow = -1;
ChainJumpCol = -1;
_moveGenerator = new MoveGeneratorService(Board);
PlaceInitialPieces();
RefreshMandatoryCaptures();
}
private void PlaceInitialPieces()
{
for (int row = 0; row < 3; row++)
for (int col = 0; col < 8; col++)
if (BoardHelper.IsPlayableSquare(row, col))
Board[row, col] = 2; // Blue top
for (int row = 5; row < 8; row++)
for (int col = 0; col < 8; col++)
if (BoardHelper.IsPlayableSquare(row, col))
Board[row, col] = 1; // Red bottom
}
// Move generation
public List<Move> GetLegalMoves(int row, int col, bool capturesOnly) =>
_moveGenerator.GetLegalMoves(row, col, capturesOnly);
// Move execution
public MoveResult ExecuteMove(int originRow, int originCol, Move move)
{
int piece = Board[originRow, originCol];
Board[move.DestinationRow, move.DestinationCol] = piece;
Board[originRow, originCol] = 0;
if (move.IsCapture)
Board[move.CapturedPieceRow, move.CapturedPieceCol] = 0;
PromoteToKingIfEligible(move.DestinationRow, move.DestinationCol);
ResetChainJump();
// Chain jump
if (move.IsCapture)
{
var furtherJumps = GetLegalMoves(move.DestinationRow, move.DestinationCol,
capturesOnly: true);
if (furtherJumps.Count > 0)
{
IsChainJumpActive = true;
ChainJumpRow = move.DestinationRow;
ChainJumpCol = move.DestinationCol;
return MoveResult.ChainJumpRequired;
}
}
// Victory check
if (EvaluateVictoryCondition(out int victor))
return MoveResult.Victory(victor);
// Advance turn
ActivePlayer = ActivePlayer == 1 ? 2 : 1;
RefreshMandatoryCaptures();
return MoveResult.TurnAdvanced;
}
private void PromoteToKingIfEligible(int row, int col)
{
if (Board[row, col] == 1 && row == 0) Board[row, col] = 3;
if (Board[row, col] == 2 && row == 7) Board[row, col] = 4;
}
private void ResetChainJump()
{
IsChainJumpActive = false;
ChainJumpRow = -1;
ChainJumpCol = -1;
}
// Mandatory captures
public void RefreshMandatoryCaptures()
{
MandatoryCapturePieces = new HashSet<(int, int)>();
for (int r = 0; r < 8; r++)
for (int c = 0; c < 8; c++)
{
int p = Board[r, c];
if (BoardHelper.BelongsToPlayer(p, ActivePlayer) &&
GetLegalMoves(r, c, capturesOnly: true).Count > 0)
MandatoryCapturePieces.Add((r, c));
}
}
// Victory
private bool EvaluateVictoryCondition(out int victor)
{
victor = 0;
int opponent = ActivePlayer == 1 ? 2 : 1;
bool opponentHasPieces = false;
bool opponentCanMove = false;
for (int r = 0; r < 8; r++)
{
for (int c = 0; c < 8; c++)
{
if (!BoardHelper.BelongsToPlayer(Board[r, c], opponent)) continue;
opponentHasPieces = true;
if (GetLegalMoves(r, c, capturesOnly: false).Count > 0)
{
opponentCanMove = true;
break;
}
}
if (opponentCanMove) break;
}
if (!opponentHasPieces || !opponentCanMove)
{
victor = ActivePlayer;
return true;
}
return false;
}
public List<Move> GetAllLegalMovesForPlayer(int player)
{
var moveGen = new MoveGeneratorService(Board);
var captures = new List<Move>();
var normals = new List<Move>();
for (int r = 0; r < 8; r++)
{
for (int c = 0; c < 8; c++)
{
if (!BoardHelper.BelongsToPlayer(Board[r, c], player)) continue;
var jumps = moveGen.GetLegalMoves(r, c, capturesOnly: true);
if (jumps.Count > 0) { captures.AddRange(jumps); continue; }
normals.AddRange(moveGen.GetLegalMoves(r, c, capturesOnly: false));
}
}
return captures.Count > 0 ? captures : normals;
}
#region helpers
public bool BelongsToActivePlayer(int piece) =>
BoardHelper.BelongsToPlayer(piece, ActivePlayer);
public (int red, int blue) GetPieceCounts()
{
int red = 0, blue = 0;
for (int r = 0; r < 8; r++)
for (int c = 0; c < 8; c++)
{
int p = Board[r, c];
if (p == 1 || p == 3) red++;
else if (p == 2 || p == 4) blue++;
}
return (red, blue);
}
#endregion
}
}