DO-73 MERGE
This commit is contained in:
commit
4a541ee9e1
@ -1104,7 +1104,7 @@ MonoBehaviour:
|
|||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_text: "18\uAE09"
|
m_text: "1\uAE09"
|
||||||
m_isRightToLeft: 0
|
m_isRightToLeft: 0
|
||||||
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
@ -1457,7 +1457,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 0
|
m_IsActive: 1
|
||||||
--- !u!224 &405965270916774547
|
--- !u!224 &405965270916774547
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -1527,6 +1527,7 @@ GameObject:
|
|||||||
- component: {fileID: 3789896065191799873}
|
- component: {fileID: 3789896065191799873}
|
||||||
- component: {fileID: 1899561816919013120}
|
- component: {fileID: 1899561816919013120}
|
||||||
- component: {fileID: 713532354933724924}
|
- component: {fileID: 713532354933724924}
|
||||||
|
- component: {fileID: 6976376814499149807}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Start Button
|
m_Name: Start Button
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -1648,6 +1649,19 @@ MonoBehaviour:
|
|||||||
m_StringArgument:
|
m_StringArgument:
|
||||||
m_BoolArgument: 0
|
m_BoolArgument: 0
|
||||||
m_CallState: 2
|
m_CallState: 2
|
||||||
|
--- !u!114 &6976376814499149807
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4808074897885991391}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 4330206548604932b038a7007dacf94b, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
enableOneTimeClick: 1
|
||||||
--- !u!1 &4880640143325961548
|
--- !u!1 &4880640143325961548
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -1713,7 +1727,7 @@ MonoBehaviour:
|
|||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_text: "\uBC15\uD638\uB7AD"
|
m_text: ksh
|
||||||
m_isRightToLeft: 0
|
m_isRightToLeft: 0
|
||||||
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
@ -1799,7 +1813,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!224 &8172929902404983356
|
--- !u!224 &8172929902404983356
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -1958,6 +1972,7 @@ MonoBehaviour:
|
|||||||
- {fileID: 4381601883819518242}
|
- {fileID: 4381601883819518242}
|
||||||
- {fileID: 6837262359343561592}
|
- {fileID: 6837262359343561592}
|
||||||
rankingButton: {fileID: 202560210887412943}
|
rankingButton: {fileID: 202560210887412943}
|
||||||
|
gameStartButton: {fileID: 713532354933724924}
|
||||||
--- !u!1 &9186617826613474881
|
--- !u!1 &9186617826613474881
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ public class MainPanelController : MonoBehaviour
|
|||||||
[SerializeField] private Button signOutButton;
|
[SerializeField] private Button signOutButton;
|
||||||
[SerializeField] private GameObject[] profileImages;
|
[SerializeField] private GameObject[] profileImages;
|
||||||
[SerializeField] private Button rankingButton;
|
[SerializeField] private Button rankingButton;
|
||||||
|
[SerializeField] private Button gameStartButton;
|
||||||
|
|
||||||
private int _selectedImageIndex;
|
private int _selectedImageIndex;
|
||||||
|
|
||||||
@ -22,6 +23,8 @@ public class MainPanelController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
signOutButton.onClick.AddListener(OnSignOutClick);
|
signOutButton.onClick.AddListener(OnSignOutClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gameStartButton.GetComponent<SingleInteractableButtonHandler>().ResetButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateUserInfo()
|
public void UpdateUserInfo()
|
||||||
|
3
Assets/Script/Renju/KSH_Renju.meta
Normal file
3
Assets/Script/Renju/KSH_Renju.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 787a283493d7435ea606170d7442790a
|
||||||
|
timeCreated: 1742967205
|
268
Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs
Normal file
268
Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// 오목 렌주룰 4-4 금수 판정.
|
||||||
|
public class DoubleFourCheck : ForbiddenDetectorBase
|
||||||
|
{
|
||||||
|
// 열린 4 패턴 정보를 저장하는 구조체
|
||||||
|
private struct OpenFourInfo
|
||||||
|
{
|
||||||
|
public int direction; // 방향 인덱스
|
||||||
|
public List<Vector2Int> emptyPositions; // 빈 좌표들 (5를 만들 수 있는 위치)
|
||||||
|
|
||||||
|
public OpenFourInfo(int dir)
|
||||||
|
{
|
||||||
|
direction = dir;
|
||||||
|
emptyPositions = new List<Vector2Int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-4 금수를 체크합니다.
|
||||||
|
public bool IsDoubleFour(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
return FindDoubleLineFour(board, row, col) || // 각각 두개의 라인에서 쌍사를 형성하는 경우
|
||||||
|
FindSingleLineDoubleFour(board, row, col); // 일직선으로 쌍사가 만들어지는 특수 패턴
|
||||||
|
}
|
||||||
|
|
||||||
|
// 쌍사(4-4) 여부를 검사합니다.
|
||||||
|
// <returns>쌍사이면 true, 아니면 false</returns>
|
||||||
|
public bool FindDoubleLineFour(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
// 임시로 돌 배치
|
||||||
|
board[row, col] = Black;
|
||||||
|
|
||||||
|
List<int> openFourDirections = new List<int>();
|
||||||
|
|
||||||
|
// 4개의 방향 검사
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int dir1 = DirectionPairs[i, 0];
|
||||||
|
int dir2 = DirectionPairs[i, 1];
|
||||||
|
|
||||||
|
// 이 방향에서 실제 열린 4가 있는지 확인
|
||||||
|
if (HasRealOpenFour(board, row, col, dir1, dir2))
|
||||||
|
{
|
||||||
|
if (HasRealOpenFour(board, row, col, dir1, dir2))
|
||||||
|
{
|
||||||
|
openFourDirections.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 원래 상태로 되돌림
|
||||||
|
board[row, col] = Space;
|
||||||
|
|
||||||
|
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 검사
|
||||||
|
private bool HasRealOpenFour(Enums.PlayerType[,] board, int row, int col,
|
||||||
|
int dir1, int dir2)
|
||||||
|
{
|
||||||
|
// 패턴 추출
|
||||||
|
Enums.PlayerType[] linePattern = ExtractLinePattern(board, row, col, dir1, dir2);
|
||||||
|
int centerIndex = 5; // 중앙 인덱스 (현재 위치)
|
||||||
|
|
||||||
|
// 연속된 4개 돌 패턴 검사 (●●●●)
|
||||||
|
for (int start = centerIndex - 3; start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
if (start < 0 || start + 3 >= linePattern.Length) continue;
|
||||||
|
|
||||||
|
// 4개의 연속된 돌 확인
|
||||||
|
bool isFour = true;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] != Black)
|
||||||
|
{
|
||||||
|
isFour = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFour)
|
||||||
|
{
|
||||||
|
// 양쪽이 모두 열려있는지 확인
|
||||||
|
bool isLeftOpen = IsOpen(linePattern, start - 1);
|
||||||
|
bool isRightOpen = IsOpen(linePattern, start + 4);
|
||||||
|
|
||||||
|
// 적어도 한쪽이 열려있으면 (한쪽이라도 5를 만들 수 있으면) 열린 4
|
||||||
|
if ((isLeftOpen || isRightOpen) && CanFormFive(linePattern, start))
|
||||||
|
{
|
||||||
|
return true; // 실제 열린 4 발견
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 한 칸 떨어진 패턴 검사 (●●●○● 또는 ●○●●● 등)
|
||||||
|
for (int start = Math.Max(0, centerIndex - 4); start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
if (start + 4 >= linePattern.Length) continue;
|
||||||
|
|
||||||
|
// 5칸 내에 4개 돌과 1개 빈칸이 있는지 확인
|
||||||
|
int stoneCount = 0;
|
||||||
|
int emptyCount = 0;
|
||||||
|
int emptyPos = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] == Black) stoneCount++;
|
||||||
|
else if (linePattern[start + i] == Space)
|
||||||
|
{
|
||||||
|
emptyCount++;
|
||||||
|
emptyPos = start + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4개 돌 + 1개 빈칸 패턴이면
|
||||||
|
if (stoneCount == 4 && emptyCount == 1)
|
||||||
|
{
|
||||||
|
// 5개 돌을 만들 수 있는지 확인
|
||||||
|
if (CanFormFive(linePattern, start))
|
||||||
|
{
|
||||||
|
return true; // 실제 열린 4 발견
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // 열린 4 없음
|
||||||
|
}
|
||||||
|
|
||||||
|
// 해당 위치가 실제로 열려 있는지 확인 (백돌이나 벽으로 막히지 않은지)
|
||||||
|
private bool IsOpen(Enums.PlayerType[] pattern, int position)
|
||||||
|
{
|
||||||
|
// 범위 체크
|
||||||
|
if (position < 0 || position >= pattern.Length)
|
||||||
|
{
|
||||||
|
return false; // 벽으로 막힘
|
||||||
|
}
|
||||||
|
|
||||||
|
// 빈 공간인지 확인
|
||||||
|
return pattern[position] == Space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이 패턴으로 5개 돌을 만들 수 있는지 확인
|
||||||
|
private bool CanFormFive(Enums.PlayerType[] pattern, int startPos)
|
||||||
|
{
|
||||||
|
// 모든 가능한 5칸 슬라이딩 윈도우 확인
|
||||||
|
for (int slide = -4; slide <= 0; slide++)
|
||||||
|
{
|
||||||
|
bool possible = true;
|
||||||
|
|
||||||
|
// 5개 윈도우 내에 상대 돌이나 벽이 없는지 확인
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
int pos = startPos + slide + i;
|
||||||
|
|
||||||
|
if (pos < 0 || pos >= pattern.Length || pattern[pos] == White)
|
||||||
|
{
|
||||||
|
possible = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (possible)
|
||||||
|
{
|
||||||
|
return true; // 5개 연속 가능
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // 어떤 위치에서도 5개 연속 불가능
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 라인 패턴을 추출합니다.
|
||||||
|
/// </summary>
|
||||||
|
private Enums.PlayerType[] ExtractLinePattern(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
Enums.PlayerType[] linePattern = new Enums.PlayerType[11];
|
||||||
|
int centerIndex = 5; // 중앙 인덱스 (현재 위치)
|
||||||
|
|
||||||
|
// 현재 위치 설정
|
||||||
|
linePattern[centerIndex] = Black;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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; // 범위 밖은 벽으로 처리하여 일관성 유지
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return linePattern;
|
||||||
|
}
|
||||||
|
}
|
3
Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs.meta
Normal file
3
Assets/Script/Renju/KSH_Renju/DoubleFourCheck.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a0f3f36424a845a3bfa973db9ee6c627
|
||||||
|
timeCreated: 1742967613
|
207
Assets/Script/Renju/KSH_Renju/DoubleThreeCheck.cs
Normal file
207
Assets/Script/Renju/KSH_Renju/DoubleThreeCheck.cs
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// 오목 렌주룰 3-3 금수 판정. 3-3 둘다 열린 상황만 금수로 판정합니다.
|
||||||
|
public class DoubleThreeCheck : ForbiddenDetectorBase
|
||||||
|
{
|
||||||
|
// 열린 3 패턴 정보를 저장하는 구조체
|
||||||
|
private struct OpenThreeInfo
|
||||||
|
{
|
||||||
|
public int direction; // 방향 인덱스
|
||||||
|
public List<Vector2Int> emptyPositions; // 빈 좌표들 (4를 만들 수 있는 위치)
|
||||||
|
|
||||||
|
public OpenThreeInfo(int dir)
|
||||||
|
{
|
||||||
|
direction = dir;
|
||||||
|
emptyPositions = new List<Vector2Int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 쌍삼(3-3) 여부를 검사합니다.
|
||||||
|
// <returns>쌍삼이면 true, 아니면 false</returns>
|
||||||
|
public bool IsDoubleThree(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
// 임시로 돌 배치
|
||||||
|
board[row, col] = Black;
|
||||||
|
|
||||||
|
List<int> openThreeDirections = new List<int>(); // 열린 3 저장용
|
||||||
|
|
||||||
|
// 4개의 방향 검사
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int dir1 = DirectionPairs[i, 0];
|
||||||
|
int dir2 = DirectionPairs[i, 1];
|
||||||
|
|
||||||
|
// 이 방향에서 실제 열린 3이 있는지 확인
|
||||||
|
if (HasRealOpenThree(board, row, col, dir1, dir2))
|
||||||
|
{
|
||||||
|
openThreeDirections.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 원래 상태로 되돌림
|
||||||
|
board[row, col] = Space;
|
||||||
|
|
||||||
|
return openThreeDirections.Count >= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 특정 방향에 대해 열린 3 검사
|
||||||
|
private bool HasRealOpenThree(Enums.PlayerType[,] board, int row, int col,
|
||||||
|
int dir1, int dir2)
|
||||||
|
{
|
||||||
|
// 패턴 추출
|
||||||
|
Enums.PlayerType[] linePattern = ExtractLinePattern(board, row, col, dir1, dir2);
|
||||||
|
int centerIndex = 5; // 중앙 인덱스 (현재 위치)
|
||||||
|
|
||||||
|
// 연속된 3개 돌 패턴 검사 (●●●)
|
||||||
|
for (int start = centerIndex - 2; start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
if (start < 0 || start + 2 >= linePattern.Length) continue;
|
||||||
|
|
||||||
|
// 3개의 연속된 돌 확인
|
||||||
|
bool isThree = true;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] != Black)
|
||||||
|
{
|
||||||
|
isThree = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isThree)
|
||||||
|
{
|
||||||
|
// 양쪽이 모두 열려있는지 확인 (진짜 열린 3)
|
||||||
|
bool isLeftOpen = IsOpen(linePattern, start - 1);
|
||||||
|
bool isRightOpen = IsOpen(linePattern, start + 3);
|
||||||
|
|
||||||
|
// 양쪽이 모두 열려있고 5개 돌을 만들 수 있는지 확인
|
||||||
|
if (isLeftOpen && isRightOpen && CanFormFive(linePattern, start))
|
||||||
|
{
|
||||||
|
return true; // 실제 열린 3 발견
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 한 칸 떨어진 패턴 검사 (●●○● 또는 ●○●● 등)
|
||||||
|
for (int start = Math.Max(0, centerIndex - 3); start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
if (start + 3 >= linePattern.Length) continue;
|
||||||
|
|
||||||
|
// 4칸 내에 3개 돌과 1개 빈칸이 있는지 확인
|
||||||
|
int stoneCount = 0;
|
||||||
|
int emptyCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] == Black) stoneCount++;
|
||||||
|
else if (linePattern[start + i] == Space) emptyCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3개 돌 + 1개 빈칸 패턴이면
|
||||||
|
if (stoneCount == 3 && emptyCount == 1)
|
||||||
|
{
|
||||||
|
// 양쪽이 모두 열려있는지 확인
|
||||||
|
bool isLeftOpen = start > 0 && linePattern[start - 1] == Space;
|
||||||
|
bool isRightOpen = start + 4 < linePattern.Length && linePattern[start + 4] == Space;
|
||||||
|
|
||||||
|
// 양쪽이 모두 열려있고 5개 돌을 만들 수 있는지 확인
|
||||||
|
if (isLeftOpen && isRightOpen && CanFormFive(linePattern, start))
|
||||||
|
{
|
||||||
|
return true; // 실제 열린 3 발견
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // 열린 3 없음
|
||||||
|
}
|
||||||
|
|
||||||
|
// 추가: 해당 위치가 실제로 열려 있는지 확인 (백돌이나 벽으로 막히지 않은지)
|
||||||
|
private bool IsOpen(Enums.PlayerType[] pattern, int position)
|
||||||
|
{
|
||||||
|
// 범위 체크
|
||||||
|
if (position < 0 || position >= pattern.Length)
|
||||||
|
{
|
||||||
|
return false; // 벽으로 막힘
|
||||||
|
}
|
||||||
|
|
||||||
|
// 빈 공간인지 확인
|
||||||
|
return pattern[position] == Space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 추가: 이 패턴으로 5개 돌을 만들 수 있는지 확인
|
||||||
|
private bool CanFormFive(Enums.PlayerType[] pattern, int startPos)
|
||||||
|
{
|
||||||
|
// 모든 가능한 5칸 슬라이딩 윈도우 확인
|
||||||
|
for (int slide = -4; slide <= 0; slide++)
|
||||||
|
{
|
||||||
|
bool possible = true;
|
||||||
|
|
||||||
|
// 5개 윈도우 내에 상대 돌이나 벽이 없는지 확인
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
int pos = startPos + slide + i;
|
||||||
|
|
||||||
|
if (pos < 0 || pos >= pattern.Length || pattern[pos] == White)
|
||||||
|
{
|
||||||
|
possible = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (possible)
|
||||||
|
{
|
||||||
|
return true; // 5개 연속 가능
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // 어떤 위치에서도 5개 연속 불가능
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 라인 패턴을 추출합니다.
|
||||||
|
/// </summary>
|
||||||
|
private Enums.PlayerType[] ExtractLinePattern(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
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; // 범위 밖은 벽으로 처리하여 일관성 유지
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return linePattern;
|
||||||
|
}
|
||||||
|
}
|
3
Assets/Script/Renju/KSH_Renju/DoubleThreeCheck.cs.meta
Normal file
3
Assets/Script/Renju/KSH_Renju/DoubleThreeCheck.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b85e35d8df4b40f0826732775c528c83
|
||||||
|
timeCreated: 1742967219
|
@ -6,9 +6,11 @@ using UnityEngine;
|
|||||||
public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
|
public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
|
||||||
{
|
{
|
||||||
// 렌주 룰 금수 감지기 생성
|
// 렌주 룰 금수 감지기 생성
|
||||||
|
/*private RenjuDoubleFourDetector _doubleFourDetactor = new();
|
||||||
|
private RenjuDoubleThreeDetector _doubleThreeDetector = new();*/
|
||||||
private RenjuOverlineDetector _overlineDetactor = new();
|
private RenjuOverlineDetector _overlineDetactor = new();
|
||||||
private RenjuDoubleFourDetector _doubleFourDetactor = new();
|
private DoubleFourCheck _doubleFourDetactor = new(); // DoubleFourCheck
|
||||||
private RenjuDoubleThreeDetector _doubleThreeDetector = new();
|
private DoubleThreeCheck _doubleThreeDetector = new(); // DoubleThreeCheck
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 렌주 룰로 금수 리스트를 반환하는 함수
|
/// 렌주 룰로 금수 리스트를 반환하는 함수
|
||||||
@ -31,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;
|
||||||
}
|
}
|
||||||
@ -40,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;
|
||||||
}
|
}
|
||||||
@ -51,11 +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));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,21 +60,44 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private bool SimulateDoubleFour(Enums.PlayerType[,] board)
|
private bool SimulateDoubleFour(Enums.PlayerType[,] board)
|
||||||
{
|
{
|
||||||
for (int row = 0; row < BoardSize; row++)
|
for (int row = 0; row < BoardSize; row++)
|
||||||
{
|
{
|
||||||
for (int col = 0; col < BoardSize; col++)
|
for (int col = 0; col < BoardSize; col++)
|
||||||
{
|
{
|
||||||
|
if (board[row, col] != Space) // 보드 초기화 방지용
|
||||||
|
continue;
|
||||||
|
|
||||||
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
|
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -93,6 +111,9 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
|
|||||||
{
|
{
|
||||||
for (int col = 0; col < BoardSize; col++)
|
for (int col = 0; col < BoardSize; col++)
|
||||||
{
|
{
|
||||||
|
if (board[row, col] != Space) // 보드 초기화 방지용
|
||||||
|
continue;
|
||||||
|
|
||||||
if (_overlineDetactor.IsOverline(board, row, col))
|
if (_overlineDetactor.IsOverline(board, row, col))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -101,7 +122,7 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 보드 상태를 시각적으로 출력하는 디버깅 함수
|
/// 보드 상태를 시각적으로 출력하는 디버깅 함수
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -127,6 +148,6 @@ public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ public class ReplayManager : Singleton<ReplayManager>
|
|||||||
public void RecordStonePlaced(Enums.StoneType stoneType,int row, int col)
|
public void RecordStonePlaced(Enums.StoneType stoneType,int row, int col)
|
||||||
{
|
{
|
||||||
string stoneColor = stoneType.ToString();
|
string stoneColor = stoneType.ToString();
|
||||||
|
if (_recordingReplayData == null) return;
|
||||||
_recordingReplayData.moves.Add(new Move(stoneColor, row, col));
|
_recordingReplayData.moves.Add(new Move(stoneColor, row, col));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user