DO-54 [Feat] 장목 거짓 금수 추가

This commit is contained in:
Sehyeon 2025-03-27 16:13:46 +09:00
parent 62d4d70eea
commit ce940a4f1c
3 changed files with 85 additions and 15 deletions

View File

@ -360,7 +360,7 @@ public static class MiniMaxAIController
var (count, _) = CountStones(board, row, col, dir, player, isSavedCache); var (count, _) = CountStones(board, row, col, dir, player, isSavedCache);
// 자기 자신 포함하여 5개 이상일 시 true 반환 // 자기 자신 포함하여 5개 이상일 시 true 반환
if (count + 1 >= WIN_COUNT) if (count + 1 == WIN_COUNT)
return true; return true;
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using UnityEngine; using UnityEngine;
// 오목 렌주룰 4-4 금수 판정. // 오목 렌주룰 4-4 금수 판정.
@ -18,9 +19,16 @@ public class DoubleFourCheck : ForbiddenDetectorBase
} }
} }
// 4-4 금수를 체크합니다.
public bool IsDoubleFour(Enums.PlayerType[,] board, int row, int col)
{
return FindDoubleLineFour(board, row, col) || // 각각 두개의 라인에서 쌍사를 형성하는 경우
FindSingleLineDoubleFour(board, row, col); // 일직선으로 쌍사가 만들어지는 특수 패턴
}
// 쌍사(4-4) 여부를 검사합니다. // 쌍사(4-4) 여부를 검사합니다.
// <returns>쌍사이면 true, 아니면 false</returns> // <returns>쌍사이면 true, 아니면 false</returns>
public bool IsDoubleFour(Enums.PlayerType[,] board, int row, int col) public bool FindDoubleLineFour(Enums.PlayerType[,] board, int row, int col)
{ {
// 임시로 돌 배치 // 임시로 돌 배치
board[row, col] = Black; board[row, col] = Black;
@ -45,9 +53,46 @@ public class DoubleFourCheck : ForbiddenDetectorBase
// 원래 상태로 되돌림 // 원래 상태로 되돌림
board[row, col] = Space; board[row, col] = Space;
return openFourDirections.Count >= 2; return openFourDirections.Count >= 2;
} }
private bool FindSingleLineDoubleFour(Enums.PlayerType[,] board, int row, int col)
{
for (int i = 0; i < 4; i++)
{
int dir1 = DirectionPairs[i, 0];
int dir2 = DirectionPairs[i, 1];
// 각 방향 라인 패턴
Enums.PlayerType[] linePattern = ExtractLinePattern(board, row, col, dir1, dir2);
// 패턴을 문자열로 변환
StringBuilder temp = new StringBuilder();
foreach (var cell in linePattern)
{
temp.Append(cell switch
{
Enums.PlayerType.None => "□",
Enums.PlayerType.PlayerA => "●",
Enums.PlayerType.PlayerB => "○",
_ => "?"
});
}
string patternStr = temp.ToString();
// 한줄로 발생하는 쌍사 패턴 검사
if (patternStr.Contains("●●□●●□●●") || patternStr.Contains("●□●●●□●"))
{
Debug.Log("patternStr: " + patternStr);
return true;
}
}
return false;
}
// 특정 방향에 대해 열린 4 검사 // 특정 방향에 대해 열린 4 검사
private bool HasRealOpenFour(Enums.PlayerType[,] board, int row, int col, private bool HasRealOpenFour(Enums.PlayerType[,] board, int row, int col,
int dir1, int dir2) int dir1, int dir2)
@ -173,7 +218,20 @@ public class DoubleFourCheck : ForbiddenDetectorBase
// 현재 위치 설정 // 현재 위치 설정
linePattern[centerIndex] = Black; linePattern[centerIndex] = Black;
// dir1 방향으로 패턴 채우기 for (int i = 1; i <= 5; i++)
{
for (int j = 0; j < 2; j++) // dir1과 dir2를 한 번에 처리
{
int direction = (j == 0) ? dir1 : dir2;
int newRow = row + Directions[direction, 0] * i;
int newCol = col + Directions[direction, 1] * i;
int index = (j == 0) ? centerIndex + i : centerIndex - i;
linePattern[index] = IsInBounds(newRow, newCol) ? board[newRow, newCol] : White;
}
}
/*// dir1 방향으로 패턴 채우기
for (int i = 1; i <= 5; i++) for (int i = 1; i <= 5; i++)
{ {
int newRow = row + Directions[dir1, 0] * i; int newRow = row + Directions[dir1, 0] * i;
@ -203,7 +261,7 @@ public class DoubleFourCheck : ForbiddenDetectorBase
{ {
linePattern[centerIndex - i] = White; // 범위 밖은 벽으로 처리하여 일관성 유지 linePattern[centerIndex - i] = White; // 범위 밖은 벽으로 처리하여 일관성 유지
} }
} }*/
return linePattern; return linePattern;
} }

View File

@ -6,9 +6,9 @@ using UnityEngine;
public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
{ {
// 렌주 룰 금수 감지기 생성 // 렌주 룰 금수 감지기 생성
private RenjuOverlineDetector _overlineDetactor = new();
/*private RenjuDoubleFourDetector _doubleFourDetactor = new(); /*private RenjuDoubleFourDetector _doubleFourDetactor = new();
private RenjuDoubleThreeDetector _doubleThreeDetector = new();*/ private RenjuDoubleThreeDetector _doubleThreeDetector = new();*/
private RenjuOverlineDetector _overlineDetactor = new();
private DoubleFourCheck _doubleFourDetactor = new(); // DoubleFourCheck private DoubleFourCheck _doubleFourDetactor = new(); // DoubleFourCheck
private DoubleThreeCheck _doubleThreeDetector = new(); // DoubleThreeCheck private DoubleThreeCheck _doubleThreeDetector = new(); // DoubleThreeCheck
@ -33,7 +33,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
if (_overlineDetactor.IsOverline(board, row, col)) if (_overlineDetactor.IsOverline(board, row, col))
{ {
forbiddenCount++; forbiddenCount++;
// Debug.Log("장목 금수 좌표 X축 : " + row + ", Y축 : " + col);
forbiddenMoves.Add(new Vector2Int(row, col)); forbiddenMoves.Add(new Vector2Int(row, col));
continue; continue;
} }
@ -42,7 +41,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
if (_doubleFourDetactor.IsDoubleFour(board, row, col)) if (_doubleFourDetactor.IsDoubleFour(board, row, col))
{ {
forbiddenCount++; forbiddenCount++;
// Debug.Log("사사 금수 좌표 X축 : " + row + ", Y축 : " + col);
forbiddenMoves.Add(new Vector2Int(row, col)); forbiddenMoves.Add(new Vector2Int(row, col));
continue; continue;
} }
@ -53,12 +51,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
if (_doubleThreeDetector.IsDoubleThree(board, row, col)) if (_doubleThreeDetector.IsDoubleThree(board, row, col))
{ {
tempForbiddenMoves.Add(new Vector2Int(row, col)); tempForbiddenMoves.Add(new Vector2Int(row, col));
// if (!SimulateDoubleFour(tempBoard))
// {
// Debug.Log("삼삼 금수 좌표 X축 : " + row + ", Y축 : " + col);
// forbiddenMoves.Add(new Vector2Int(row, col));
// }
} }
} }
} }
@ -68,12 +60,32 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
board[pos.x, pos.y] = Black; board[pos.x, pos.y] = Black;
if (!SimulateDoubleFour(board) && !SimulateOverline(board)) if (!SimulateDoubleFour(board) && !SimulateOverline(board))
{ {
// Debug.Log("X: "+pos.x + "Y: "+ pos.y);
forbiddenMoves.Add(new Vector2Int(pos.x, pos.y)); forbiddenMoves.Add(new Vector2Int(pos.x, pos.y));
} }
board[pos.x, pos.y] = Space; board[pos.x, pos.y] = Space;
} }
List<Vector2Int> resultMoves = CheckHasFiveStones(board, forbiddenMoves);
return resultMoves;
}
// 금수 위치에서 5목이 가능할 경우 해당 위치는 금수 표기 X
private List<Vector2Int> CheckHasFiveStones(Enums.PlayerType[,] board, List<Vector2Int> forbiddenMoves)
{
// 리스트를 수정하는 동안 오류를 방지하기 위해 뒤에서부터 반복
for (int i = forbiddenMoves.Count - 1; i >= 0; i--)
{
int row = forbiddenMoves[i].x;
int col = forbiddenMoves[i].y;
// 해당 위치에서 승리(5목)이 가능하면 금수 표기 X
if (OmokAI.Instance.CheckGameWin(Enums.PlayerType.PlayerA, board, row, col))
{
forbiddenMoves.RemoveAt(i);
}
}
return forbiddenMoves; return forbiddenMoves;
} }