DO-31 Feat: 쌍삼 로직 추가
- 쌍삼 감지기 추가 - 통합 클래스에서 임시 보드 복제하여 전달
This commit is contained in:
parent
3d6b9255b3
commit
ffdd4e9aa8
@ -2,6 +2,7 @@
|
||||
{
|
||||
private protected Enums.PlayerType Black = Enums.PlayerType.PlayerA;
|
||||
private protected Enums.PlayerType Space = Enums.PlayerType.None;
|
||||
private protected Enums.PlayerType White = Enums.PlayerType.PlayerB;
|
||||
|
||||
// 8방향을 나타내는 델타 배열 (가로, 세로, 대각선 방향)
|
||||
private protected readonly int[,] Directions = new int[8, 2]
|
||||
|
@ -16,11 +16,278 @@ public class RenjuDoubleThreeDetector: ForbiddenDetectorBase
|
||||
board[row, col] = Black;
|
||||
|
||||
// 쌍삼 검사
|
||||
// bool isThreeThree = CheckThreeThree(board, row, col);
|
||||
bool isDoubleThree = CheckDoubleThree(board, row, col);
|
||||
|
||||
// 원래 상태로 되돌림
|
||||
board[row, col] = Space;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 쌍삼(3-3) 여부를 검사합니다.
|
||||
/// </summary>
|
||||
private bool CheckDoubleThree(Enums.PlayerType[,] board, int row, int col)
|
||||
{
|
||||
int openThreeCount = 0;
|
||||
|
||||
// 4개의 방향 쌍에 대해 검사 (대각선 및 직선 포함)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int dir1 = DirectionPairs[i, 0];
|
||||
int dir2 = DirectionPairs[i, 1];
|
||||
|
||||
// 해당 방향에서 열린 3의 개수 계산
|
||||
if (CheckOpenThreeInDirection(board, row, col, dir1, dir2))
|
||||
{
|
||||
openThreeCount++;
|
||||
|
||||
// 이미 열린 3이 2개 이상 발견되면 쌍삼으로 판정
|
||||
if (openThreeCount >= 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 방향에서 열린 3이 형성되는지 확인합니다.
|
||||
/// </summary>
|
||||
private bool CheckOpenThreeInDirection(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
|
||||
{
|
||||
// 각 방향으로 최대 5칸까지의 범위를 검사 (현재 위치 포함 총 11칸)
|
||||
Enums.PlayerType[] linePattern = new Enums.PlayerType[11];
|
||||
int centerIndex = 5; // 중앙 인덱스 (현재 위치)
|
||||
|
||||
// 현재 위치 설정
|
||||
linePattern[centerIndex] = Black;
|
||||
|
||||
// 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))
|
||||
{
|
||||
linePattern[centerIndex + i] = board[newRow, newCol];
|
||||
}
|
||||
else
|
||||
{
|
||||
linePattern[centerIndex + i] = White; // 범위 밖은 막힌 것으로 처리
|
||||
}
|
||||
}
|
||||
|
||||
// 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))
|
||||
{
|
||||
linePattern[centerIndex - i] = board[newRow, newCol];
|
||||
}
|
||||
else
|
||||
{
|
||||
linePattern[centerIndex - i] = White; // 범위 밖은 막힌 것으로 처리
|
||||
}
|
||||
}
|
||||
|
||||
// 열린 3 패턴 확인
|
||||
return CheckForOpenThree(linePattern, centerIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 라인 패턴에서 열린 3 패턴을 확인합니다.
|
||||
/// </summary>
|
||||
private bool CheckForOpenThree(Enums.PlayerType[] linePattern, int centerIndex)
|
||||
{
|
||||
// 연속된 열린 3 확인
|
||||
if (CheckConsecutiveOpenThree(linePattern, centerIndex))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 한 칸 떨어진 열린 3 확인
|
||||
if (CheckGappedOpenThree(linePattern, centerIndex))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 연속된 열린 3 패턴을 확인합니다.
|
||||
/// </summary>
|
||||
private bool CheckConsecutiveOpenThree(Enums.PlayerType[] linePattern, int centerIndex)
|
||||
{
|
||||
// 연속된 3개의 돌 패턴
|
||||
// 시작 인덱스를 조정하여 센터가 패턴 내에 있는지 확인
|
||||
for (int start = centerIndex - 2; start <= centerIndex; start++)
|
||||
{
|
||||
// 범위 체크
|
||||
if (start < 0 || start + 2 >= linePattern.Length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3개의 연속된 돌 확인
|
||||
bool isConsecutiveThree = true;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (linePattern[start + i] != Black)
|
||||
{
|
||||
isConsecutiveThree = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isConsecutiveThree)
|
||||
{
|
||||
// 양쪽이 모두 열려있는지 확인
|
||||
bool isLeftOpen = (start - 1 >= 0) && (linePattern[start - 1] == Space);
|
||||
bool isRightOpen = (start + 3 < linePattern.Length) && (linePattern[start + 3] == Space);
|
||||
|
||||
// 양쪽이 모두 열려있으면 열린 3
|
||||
if (isLeftOpen && isRightOpen)
|
||||
{
|
||||
// 추가 검증: 더 확장해서 열려있는지 확인
|
||||
bool isExtendedLeftOpen = IsExtendedOpen(linePattern, start - 1, -1);
|
||||
bool isExtendedRightOpen = IsExtendedOpen(linePattern, start + 3, 1);
|
||||
|
||||
if (isExtendedLeftOpen && isExtendedRightOpen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 한 칸 떨어진 열린 3 패턴을 확인합니다.
|
||||
/// </summary>
|
||||
private bool CheckGappedOpenThree(Enums.PlayerType[] linePattern, int centerIndex)
|
||||
{
|
||||
// 한 칸 떨어진 패턴 확인
|
||||
// 패턴 1: ●●○● (centerIndex가 어느 위치든 가능)
|
||||
// 패턴 2: ●○●● (centerIndex가 어느 위치든 가능)
|
||||
|
||||
// 윈도우 크기 4로 슬라이딩하면서 검사
|
||||
for (int start = Mathf.Max(0, centerIndex - 3); start <= Mathf.Min(linePattern.Length - 4, centerIndex); start++)
|
||||
{
|
||||
// 패턴 내에 돌과 빈칸 개수 확인
|
||||
int stoneCount = 0;
|
||||
int gapCount = 0;
|
||||
int gapPosition = -1;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (linePattern[start + i] == Black)
|
||||
{
|
||||
stoneCount++;
|
||||
}
|
||||
else if (linePattern[start + i] == Space)
|
||||
{
|
||||
gapCount++;
|
||||
gapPosition = start + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 상대 돌이나 벽이 있으면 패턴이 깨짐
|
||||
stoneCount = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3개의 돌과 1개의 빈칸으로 구성된 패턴
|
||||
if (stoneCount == 3 && gapCount == 1)
|
||||
{
|
||||
// 빈칸에 돌을 놓았을 때 열린 4가 되는지 확인
|
||||
if (CheckIfCreatesOpenFour(linePattern, gapPosition))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 빈칸에 돌을 놓았을 때 열린 4가 되는지 확인합니다.
|
||||
/// </summary>
|
||||
private bool CheckIfCreatesOpenFour(Enums.PlayerType[] linePattern, int position)
|
||||
{
|
||||
// 시뮬레이션: 빈칸에 돌을 놓아봄
|
||||
Enums.PlayerType[] testPattern = new Enums.PlayerType[linePattern.Length];
|
||||
System.Array.Copy(linePattern, testPattern, linePattern.Length);
|
||||
testPattern[position] = Black;
|
||||
|
||||
// 놓은 위치를 포함해 연속된 4가 있는지 확인
|
||||
for (int start = Mathf.Max(0, position - 3); start <= position; start++)
|
||||
{
|
||||
// 범위 체크
|
||||
if (start + 3 >= testPattern.Length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4개의 연속된 돌 확인
|
||||
bool isConsecutiveFour = true;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (testPattern[start + i] != Black)
|
||||
{
|
||||
isConsecutiveFour = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isConsecutiveFour)
|
||||
{
|
||||
// 양쪽이 모두 열려있는지 확인 (열린 4)
|
||||
bool isLeftOpen = (start - 1 >= 0) && (testPattern[start - 1] == Space);
|
||||
bool isRightOpen = (start + 4 < testPattern.Length) && (testPattern[start + 4] == Space);
|
||||
|
||||
if (isLeftOpen && isRightOpen)
|
||||
{
|
||||
return true; // 열린 4가 됨
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 방향으로 추가로 열려있는지 확인합니다.
|
||||
/// </summary>
|
||||
private bool IsExtendedOpen(Enums.PlayerType[] linePattern, int startPos, int direction)
|
||||
{
|
||||
// 한 칸 더 확장해서 확인
|
||||
int nextPos = startPos + direction;
|
||||
if (nextPos >= 0 && nextPos < linePattern.Length)
|
||||
{
|
||||
// 다음 칸이 상대 돌이나 벽이면 확장 불가
|
||||
if (linePattern[nextPos] == White)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 범위를 벗어나면 확장 불가
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -15,6 +15,6 @@ public class RenjuForbiddenMoveDetector
|
||||
public List<Vector2Int> RenjuForbiddenMove(Enums.PlayerType[,] board)
|
||||
{
|
||||
var tempBoard = (Enums.PlayerType[,])board.Clone();
|
||||
return _ruleChecker.GetForbiddenMoves(board);
|
||||
return _ruleChecker.GetForbiddenMoves(tempBoard);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user