152 lines
3.7 KiB
C#
152 lines
3.7 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace API.Models.Game;
|
|
|
|
public readonly struct Coordinates
|
|
{
|
|
public int X { get; init; }
|
|
public int Y { get; init; }
|
|
}
|
|
|
|
public enum DropResult
|
|
{
|
|
OutOfGameField,
|
|
NotAllowedPlayer,
|
|
ColumnFull,
|
|
InvalidFieldValue,
|
|
Placed
|
|
}
|
|
|
|
public enum FieldState
|
|
{
|
|
OutOfGameField,
|
|
Empty,
|
|
OccupiedRed,
|
|
OccupiedYellow,
|
|
InvalidFieldValue
|
|
}
|
|
|
|
public class GameField(Coordinates gFs)
|
|
{
|
|
public Coordinates GFs = gFs;
|
|
public int[,] CurrentField { get; } = new int[gFs.Y, gFs.X];
|
|
public int[,] BackupField { get; } = new int[gFs.Y, gFs.X];
|
|
|
|
public DropResult Drop(int column, int player)
|
|
{
|
|
if (column < 0 || column >= CurrentField.GetLength(1))
|
|
return DropResult.OutOfGameField;
|
|
|
|
if (player != 1 && player != 2)
|
|
return DropResult.NotAllowedPlayer;
|
|
|
|
int rows = CurrentField.GetLength(0);
|
|
|
|
for (int y = rows - 1; y >= 0; y--)
|
|
{
|
|
int currentValue = CurrentField[y, column];
|
|
|
|
if (currentValue == 0)
|
|
{
|
|
CreateSave();
|
|
CurrentField[y, column] = player;
|
|
return DropResult.Placed;
|
|
}
|
|
|
|
if (currentValue != 1 && currentValue != 2)
|
|
return DropResult.InvalidFieldValue;
|
|
}
|
|
|
|
return DropResult.ColumnFull;
|
|
}
|
|
|
|
public FieldState CheckField(Coordinates coordinates)
|
|
{
|
|
if (coordinates.X < 0 || coordinates.X >= CurrentField.GetLength(1) ||
|
|
coordinates.Y < 0 || coordinates.Y >= CurrentField.GetLength(0))
|
|
return FieldState.OutOfGameField;
|
|
|
|
var currentValue = CurrentField[coordinates.Y, coordinates.X];
|
|
|
|
return currentValue switch
|
|
{
|
|
0 => FieldState.Empty,
|
|
1 => FieldState.OccupiedRed,
|
|
2 => FieldState.OccupiedYellow,
|
|
_ => FieldState.InvalidFieldValue
|
|
};
|
|
}
|
|
|
|
public bool IsFull()
|
|
{
|
|
int rows = CurrentField.GetLength(0);
|
|
int cols = CurrentField.GetLength(1);
|
|
for (int y = 0; y < rows; y++)
|
|
{
|
|
for (int x = 0; x < cols; x++)
|
|
{
|
|
if (CurrentField[y, x] == 0)
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private int CountInDirection(int startX, int startY, int dx, int dy, int player)
|
|
{
|
|
var count = 0;
|
|
var x = startX;
|
|
var y = startY;
|
|
|
|
while (
|
|
x >= 0 && x < CurrentField.GetLength(1) &&
|
|
y >= 0 && y < CurrentField.GetLength(0) &&
|
|
CurrentField[y, x] == player)
|
|
{
|
|
count++;
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
private bool CheckLine(int startX, int startY, int dx, int dy, int player)
|
|
{
|
|
int count = CountInDirection(startX + dx, startY + dy, dx, dy, player);
|
|
count += CountInDirection(startX - dx, startY - dy, -dx, -dy, player);
|
|
return count + 1 >= 4;
|
|
}
|
|
|
|
public int CheckForWin()
|
|
{
|
|
int rows = CurrentField.GetLength(0);
|
|
int cols = CurrentField.GetLength(1);
|
|
|
|
(int dx, int dy)[] directions = [(1, 0), (0, 1), (1, 1), (-1, 1)];
|
|
|
|
for (int y = 0; y < rows; y++)
|
|
{
|
|
for (int x = 0; x < cols; x++)
|
|
{
|
|
int player = CurrentField[y, x];
|
|
|
|
if (player != 1 && player != 2) continue;
|
|
|
|
foreach (var (dx, dy) in directions)
|
|
{
|
|
if (CheckLine(x, y, dx, dy, player))
|
|
return player;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private void CreateSave()
|
|
{
|
|
Array.Copy(CurrentField, BackupField, CurrentField.Length);
|
|
}
|
|
}
|