chip-gameV3/Assets/Scripts/FieldModel.cs
2026-07-14 11:14:13 +03:00

222 lines
6.6 KiB
C#

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 getHeight(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 (getHeight(col) != -1) return false;
}
return true;
}
}