Degullmok-client/Assets/Script/Renju/RenjuForbiddenMoveDetector.cs
2025-03-26 16:44:02 +09:00

210 lines
6.7 KiB
C#

using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
{
// 렌주 룰 금수 감지기 생성
/*private RenjuOverlineDetector _overlineDetactor = new();
private RenjuDoubleFourDetector _doubleFourDetactor = new();
private RenjuDoubleThreeDetector _doubleThreeDetector = new();*/
// 임시 테스트
private RenjuOverlineDetector _overlineDetactor = new();
private DoubleFourCheck _doubleFourDetactor = new(); // DoubleFourCheck
private DoubleThreeCheck _doubleThreeDetector = new(); // DoubleThreeCheck
/// <summary>
/// 렌주 룰로 금수 리스트를 반환하는 함수
/// </summary>
/// <param name="board">현재 보드의 상태</param>
/// <returns>금수 좌표를 담은 리스트</returns>
public List<Vector2Int> RenjuForbiddenMove(Enums.PlayerType[,] board)
{
var forbiddenCount = 0;
List<Vector2Int> forbiddenMoves = new();
List<Vector2Int> tempForbiddenMoves = new();
for (int row = 0; row < BoardSize; row++)
{
for (int col = 0; col < BoardSize; col++)
{
// ** 비어 있지 않으면 검사할 필요 없음 **
if (!IsEmptyPosition(board, row, col)) continue;
// 장목 검사
if (_overlineDetactor.IsOverline(board, row, col))
{
forbiddenCount++;
Debug.Log("장목 금수 좌표 X축 : " + row + ", Y축 : " + col);
forbiddenMoves.Add(new Vector2Int(row, col));
continue;
}
// 4-4 검사
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
{
forbiddenCount++;
Debug.Log("사사 금수 좌표 X축 : " + row + ", Y축 : " + col);
forbiddenMoves.Add(new Vector2Int(row, col));
continue;
}
if(forbiddenCount > 0) continue;
// 3-3 검사
if (_doubleThreeDetector.IsDoubleThree(board, row, col))
{
tempForbiddenMoves.Add(new Vector2Int(row, col));
/*if (HasWinningPotential(board, row, col))
{
tempForbiddenMoves.Add(new Vector2Int(row, col));
}*/
// if (!SimulateDoubleFour(tempBoard))
// {
// Debug.Log("삼삼 금수 좌표 X축 : " + row + ", Y축 : " + col);
// forbiddenMoves.Add(new Vector2Int(row, col));
// }
}
}
}
foreach (var pos in tempForbiddenMoves)
{
board[pos.x, pos.y] = Black;
if (!SimulateDoubleFour(board) && !SimulateOverline(board))
{
Debug.Log("X: "+pos.x + "Y: "+ pos.y);
forbiddenMoves.Add(new Vector2Int(pos.x, pos.y));
}
board[pos.x, pos.y] = Space;
}
return forbiddenMoves;
}
private bool HasWinningPotential(Enums.PlayerType[,] board, int row, int col)
{
// 모든 방향에 대해 5개 연속 돌을 만들 수 있는지 확인
for (int dirPair = 0; dirPair < 4; dirPair++)
{
int dir1 = DirectionPairs[dirPair, 0];
int dir2 = DirectionPairs[dirPair, 1];
if (CanFormFiveInDirection(board, row, col, dir1, dir2))
{
return true;
}
}
return false;
}
private bool CanFormFiveInDirection(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
{
// 해당 방향으로 5개 연속 돌을 놓을 가능성 확인
// 현재 위치에 흑돌 임시 배치
board[row, col] = Black;
// 양방향으로 연속된 돌 또는 빈 공간 개수 세기
int length = 1; // 현재 위치 포함
// dir1 방향 확인
for (int i = 1; i < 5; i++)
{
int newRow = row + Directions[dir1, 0] * i;
int newCol = col + Directions[dir1, 1] * i;
if (!IsInBounds(newRow, newCol) || board[newRow, newCol] == White)
{
break;
}
length++;
}
// dir2 방향 확인
for (int i = 1; i < 5; i++)
{
int newRow = row + Directions[dir2, 0] * i;
int newCol = col + Directions[dir2, 1] * i;
if (!IsInBounds(newRow, newCol) || board[newRow, newCol] == White)
{
break;
}
length++;
}
// 원래 상태로 복원
board[row, col] = Space;
// 5개 이상 연속 가능하면 승리 가능성 있음
return length >= 5;
}
private bool SimulateDoubleFour(Enums.PlayerType[,] board)
{
for (int row = 0; row < BoardSize; row++)
{
for (int col = 0; col < BoardSize; col++)
{
if (board[row, col] != Space)
continue;
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
return true;
}
}
return false;
}
private bool SimulateOverline(Enums.PlayerType[,] board)
{
for (int row = 0; row < BoardSize; row++)
{
for (int col = 0; col < BoardSize; col++)
{
if (board[row, col] != Space)
continue;
if (_overlineDetactor.IsOverline(board, row, col))
{
return true;
}
}
}
return false;
}
/// <summary>
/// 보드 상태를 시각적으로 출력하는 디버깅 함수
/// </summary>
/// <param name="board">현재 보드 상태</param>
/// <returns>보드의 시각적 표현 문자열</returns>
private string DebugBoard(Enums.PlayerType[,] board)
{
StringBuilder sb = new StringBuilder();
for (int row = 0; row < BoardSize; row++)
{
for (int col = 0; col < BoardSize; col++)
{
sb.Append(board[row, col] switch
{
Enums.PlayerType.None => "□",
Enums.PlayerType.PlayerA => "●",
Enums.PlayerType.PlayerB => "○",
_ => "?"
});
}
sb.AppendLine(); // 줄바꿈 추가
}
return sb.ToString();
}
}