231 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
public enum CellState
{
Empty, Player1, Player2
}
public class FieldModel
{
//двумерный массив для поля
public CellState[,] FieldArray;
public int Height;
public int Width;
public int TargetLineLength = 4;
public FieldModel(int width, int height)
{
//0 индекс для строк, 1 индекс для столбцов
Width = width;
Height = height;
makeEmptyField(width, height);
}
public void makeEmptyField(int width, int height)
{
FieldArray = new CellState[height, width];
Array.Clear(FieldArray, 0, FieldArray.Length);
}
public CheckResult Check(CellState lastPlayer)
{
HashSet<(int row, int col)> WinningIndexes = new();
var rowsResult = checkAllRows(lastPlayer);
var colsResult = checkAllColumns(lastPlayer);
var diagonalsResult = checkAllDiagonals(lastPlayer);
bool hasWin = rowsResult.hasWin ||
colsResult.hasWin ||
diagonalsResult.hasWin;
if (hasWin)
{
WinningIndexes.UnionWith(rowsResult.winningIndexes);
WinningIndexes.UnionWith(colsResult.winningIndexes);
WinningIndexes.UnionWith(diagonalsResult.winningIndexes);
return new CheckResult(end: true,
isDraw: false,
WinningIndexes);
}
else if (checkDraw())
{
return new CheckResult(end: true,
isDraw: true,
WinningIndexes);
}
else
{
return new CheckResult(end: false,
isDraw: false,
WinningIndexes);
}
}
private (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(CellState targetCellState)
{
var winningCells = new HashSet<(int row, int col)>();
for (int row = 0; row < Height; row++)
{
int start = -1;
for (int col = 0; col <= Width; col++) // теперь проходим до Width включительно
{
// Проверяем, не вышли ли за границы массива
bool isMatch = col < Width && FieldArray[row, col] == targetCellState;
if (isMatch && start == -1)
start = col;
if ((!isMatch || col == Width) && start != -1)
{
int length = col - start;
if (length >= TargetLineLength)
{
for (int c = start; c < col; c++)
winningCells.Add((row, c));
}
start = -1;
}
}
}
return (winningCells.Count > 0, winningCells);
}
private (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllColumns(CellState targetCellState)
{
var winningCells = new HashSet<(int row, int col)>();
for (int col = 0; col < Width; col++)
{
int start = -1;
for (int row = 0; row <= Height; row++)
{
bool isMatch = row < Height && FieldArray[row, col] == targetCellState;
if (isMatch && start == -1)
start = row;
if ((!isMatch || row == Height) && start != -1)
{
int length = row - start;
if (length >= TargetLineLength)
{
for (int r = start; r < row; r++)
winningCells.Add((r, col));
}
start = -1;
}
}
}
return (winningCells.Count > 0, winningCells);
}
private (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllDiagonals(CellState targetCellState)
{
var winningCells = new HashSet<(int row, int col)>();
// Проверка главных диагоналей
for (int row = 0; row < Height; row++)
{
CheckDiagonalStartingAt(row, 0, 1, 1, targetCellState, winningCells);
}
for (int col = 1; col < Width; col++)
{
CheckDiagonalStartingAt(0, col, 1, 1, targetCellState, winningCells);
}
// Проверка побочных диагоналей
for (int row = 0; row < Height; row++)
{
CheckDiagonalStartingAt(row, Width - 1, 1, -1, targetCellState, winningCells);
}
for (int col = Width - 2; col >= 0; col--)
{
CheckDiagonalStartingAt(0, col, 1, -1, targetCellState, winningCells);
}
return (winningCells.Count > 0, winningCells);
}
private void CheckDiagonalStartingAt(int startRow, int startCol, int rowStep, int colStep,
CellState targetCellState, HashSet<(int, int)> winningCells)
{
int rows = Height;
int cols = Width;
int currentRow = startRow;
int currentCol = startCol;
int sequenceLength = 0;
int sequenceStartRow = startRow;
int sequenceStartCol = startCol;
while (currentRow >= 0 && currentRow < rows &&
currentCol >= 0 && currentCol < cols)
{
bool isMatch = FieldArray[currentRow, currentCol] == targetCellState;
if (isMatch)
{
sequenceLength++;
if (sequenceLength >= TargetLineLength)
{
// Добавляем ВСЕ ячейки из текущей последовательности
for (int i = 0; i < sequenceLength; i++)
{
int r = sequenceStartRow + i * rowStep;
int c = sequenceStartCol + i * colStep;
winningCells.Add((r, c));
}
}
}
else
{
sequenceLength = 0;
sequenceStartRow = currentRow + rowStep;
sequenceStartCol = currentCol + colStep;
}
currentRow += rowStep;
currentCol += colStep;
}
}
public int GetColumnHeight(int colIndex)
{
for (int row = Height - 1; row >= 0; row--)
{
if (FieldArray[row, colIndex] == CellState.Empty)
{
return row;
}
}
return -1;//если не нашли, то больше добавить нельзя
}
public bool checkDraw()
{
for (int col = 0; col < Width; col++)
{
if (GetColumnHeight(col) != -1) return false;
}
return true;
}
public List<int> CollectNonFullCols()
{
var positions = new List<int>();
for (int i = 0; i < Width; i++)
if (GetColumnHeight(i) != -1)
positions.Add(i);
return positions;
}
}