From ce940a4f1c4ad2e83058e5a6168e394da8d95767 Mon Sep 17 00:00:00 2001 From: Sehyeon Date: Thu, 27 Mar 2025 16:13:46 +0900 Subject: [PATCH] =?UTF-8?q?DO-54=20[Feat]=20=EC=9E=A5=EB=AA=A9=20=EA=B1=B0?= =?UTF-8?q?=EC=A7=93=20=EA=B8=88=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Script/AI/MiniMaxAIController.cs | 2 +- .../Script/Renju/KSH_Renju/DoubleFourCheck.cs | 66 +++++++++++++++++-- .../Renju/RenjuForbiddenMoveDetector.cs | 32 ++++++--- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/Assets/Script/AI/MiniMaxAIController.cs b/Assets/Script/AI/MiniMaxAIController.cs index 5952707..062f181 100644 --- a/Assets/Script/AI/MiniMaxAIController.cs +++ b/Assets/Script/AI/MiniMaxAIController.cs @@ -360,7 +360,7 @@ public static class MiniMaxAIController var (count, _) = CountStones(board, row, col, dir, player, isSavedCache); // 자기 자신 포함하여 5개 이상일 시 true 반환 - if (count + 1 >= WIN_COUNT) + if (count + 1 == WIN_COUNT) return true; } diff --git a/Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs b/Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs index 499c28d..b9900f9 100644 --- a/Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs +++ b/Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using UnityEngine; // 오목 렌주룰 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) 여부를 검사합니다. // 쌍사이면 true, 아니면 false - public bool IsDoubleFour(Enums.PlayerType[,] board, int row, int col) + public bool FindDoubleLineFour(Enums.PlayerType[,] board, int row, int col) { // 임시로 돌 배치 board[row, col] = Black; @@ -45,7 +53,44 @@ public class DoubleFourCheck : ForbiddenDetectorBase // 원래 상태로 되돌림 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 검사 @@ -173,7 +218,20 @@ public class DoubleFourCheck : ForbiddenDetectorBase // 현재 위치 설정 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++) { int newRow = row + Directions[dir1, 0] * i; @@ -203,7 +261,7 @@ public class DoubleFourCheck : ForbiddenDetectorBase { linePattern[centerIndex - i] = White; // 범위 밖은 벽으로 처리하여 일관성 유지 } - } + }*/ return linePattern; } diff --git a/Assets/Script/Renju/RenjuForbiddenMoveDetector.cs b/Assets/Script/Renju/RenjuForbiddenMoveDetector.cs index 4810e48..7e74980 100644 --- a/Assets/Script/Renju/RenjuForbiddenMoveDetector.cs +++ b/Assets/Script/Renju/RenjuForbiddenMoveDetector.cs @@ -6,9 +6,9 @@ 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 @@ -33,7 +33,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase if (_overlineDetactor.IsOverline(board, row, col)) { forbiddenCount++; - // Debug.Log("장목 금수 좌표 X축 : " + row + ", Y축 : " + col); forbiddenMoves.Add(new Vector2Int(row, col)); continue; } @@ -42,7 +41,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase if (_doubleFourDetactor.IsDoubleFour(board, row, col)) { forbiddenCount++; - // Debug.Log("사사 금수 좌표 X축 : " + row + ", Y축 : " + col); forbiddenMoves.Add(new Vector2Int(row, col)); continue; } @@ -53,12 +51,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase if (_doubleThreeDetector.IsDoubleThree(board, 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; 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; } + List resultMoves = CheckHasFiveStones(board, forbiddenMoves); + + return resultMoves; + } + + // 금수 위치에서 5목이 가능할 경우 해당 위치는 금수 표기 X + private List CheckHasFiveStones(Enums.PlayerType[,] board, List 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; }