1. Level Editor 수정
연산 시간이 너무 오래 걸려서 검증이 제대로 안되고 있는 문제가 있어서
방법론을 바꿔서 구현하기로 하였다.
지금은 한번에 모든 오리를 다 본 후 성공 로직이 있는 경우의 수를 뽑고 있는데
이러니 너무 depth가 깊어져서 결국은
1. 한번에 모든 오리를 다 보지 않고
2. 오리 한마리씩 단계적으로 해결해서
3. 해결된 시점의 GameState를 새 root로 잡아서
4. 다시 다음 오리 해결을 반복
이런식으로 방법론을 구성하였다.
여기서 추가로 넣어주면 좋은 기능은
1. 해결된 오리, 파이프, 골은 Id 부여해줄 것 (인간이 직접 부여하는 불필요함 ↓)
public bool IsGameComplete()
{
// 모든 오리가 목적지에 도달했거나 제거되었는지 확인
return Ducks.Count == 0 || Ducks.All(d => d.IsCompleted);
}
지금은 모든 오리 다 없어졌을 때에만 성공하기 때문에 우선 이부분부터 고쳐주자
private static async Task<(List<List<WaterSlideSimulator.GameAction>> solutionPaths, int exploredStates)>
FindSolutionsOptimizedAsync(
WaterSlideSimulator simulator,
WaterSlideSimulator.GameState initialState,
int movableTileCount,
AdvancedValidationResult result,
CancellationToken cancellationToken,
IProgress<float> progress,
Func<WaterSlideSimulator.GameState, bool> isGoal // 추가
)
if (isGoal == null)
isGoal = s => s.IsGameComplete(); // 맨 윗줄 추가
var solutionPaths = new List<List<WaterSlideSimulator.GameAction>>();
...
// 초기 상태가 이미 완료 상태인지 먼저 체크
if (initialState.IsGameComplete())
{
solutionPaths.Add(new List<WaterSlideSimulator.GameAction>()); // 액션 없이 완료
return (solutionPaths, 1);
}
// 아래처럼 변경
// 초기 상태가 이미 목표를 만족하는지 체크
if (isGoal(initialState))
{
solutionPaths.Add(new List<WaterSlideSimulator.GameAction>());
return (solutionPaths, 1);
}
while (...)
{
...
// 기존: if (currentNode.State.IsGameComplete())
if (isGoal(currentNode.State))
{
solutionPaths.Add(currentNode.Path);
...
continue;
}
...
}
// 한 단계: 현재 상태에서 Ducks.Count 를 줄이는 경로를 찾고, 그 결과 상태를 반환
private static async Task<(bool success,
List<WaterSlideSimulator.GameAction> stepPath,
WaterSlideSimulator.GameState nextState,
int explored)>
SolveOneDuckStepAsync(
WaterSlideSimulator simulator,
WaterSlideSimulator.GameState rootState,
int movableTileCount,
AdvancedValidationResult result,
CancellationToken token,
IProgress<float> progress)
{
var startDuckCount = rootState.Ducks.Count;
// 이미 오리가 없으면 더 할 게 없음
if (startDuckCount == 0)
return (true, new List<WaterSlideSimulator.GameAction>(), rootState, 0);
// 이번 단계의 목표: "오리 수가 줄어든 상태"
Func<WaterSlideSimulator.GameState, bool> isGoal =
s => s.Ducks.Count < startDuckCount;
// 기존 검색 함수를, 우리가 넣은 isGoal 로 호출
var (paths, exploredStates) = await FindSolutionsOptimizedAsync(
simulator,
rootState,
movableTileCount,
result,
token,
progress,
isGoal);
if (paths == null || paths.Count == 0)
{
// 이 루트에서는 오리 수를 줄일 방법이 없음 = 막다른 길
return (false, null, rootState, exploredStates);
}
var stepPath = paths[0];
// stepPath 를 실제로 적용해서 다음 단계 루트 상태 만들기
var current = rootState;
foreach (var action in stepPath)
{
current = simulator.ApplyActionAndSimulate(current, action);
}
return (true, stepPath, current, exploredStates);
}
// 전체 게임: 오리가 0 마리가 될 때까지 SolveOneDuckStepAsync 를 반복
private static async Task<(List<List<WaterSlideSimulator.GameAction>> solutionPaths, int exploredStates)>
SolveAllDucksStepByStepAsync(
WaterSlideSimulator simulator,
WaterSlideSimulator.GameState initialState,
int movableTileCount,
AdvancedValidationResult result,
CancellationToken token,
IProgress<float> progress)
{
var currentState = initialState;
var fullPath = new List<WaterSlideSimulator.GameAction>();
var totalExplored = 0;
// 안전장치: 최대 단계 수
var maxSteps = initialState.Ducks.Count + 5;
int step = 0;
while (currentState.Ducks.Count > 0 && step < maxSteps)
{
step++;
var (ok, stepPath, nextState, explored) = await SolveOneDuckStepAsync(
simulator,
currentState,
movableTileCount,
result,
token,
progress);
totalExplored += explored;
if (!ok)
{
// 이 순서/루트로는 중간에 막다른 길 → 해답 없음
return (new List<List<WaterSlideSimulator.GameAction>>(), totalExplored);
}
fullPath.AddRange(stepPath);
currentState = nextState;
}
if (currentState.Ducks.Count == 0)
{
// 한 개의 전체 경로를 솔루션 리스트로 감싸서 반환
var list = new List<List<WaterSlideSimulator.GameAction>> { fullPath };
return (list, totalExplored);
}
else
{
return (new List<List<WaterSlideSimulator.GameAction>>(), totalExplored);
}
}


'Unity > 멋쟁이사자처럼 부트캠프' 카테고리의 다른 글
| [멋쟁이사자처럼 - 유니티 스튜디오 인턴십] 매핑 이상 레벨 (0) | 2025.12.12 |
|---|---|
| [멋쟁이사자처럼 - 유니티 스튜디오 인턴십] 레벨 매핑 작업 (40~50레벨) (0) | 2025.12.09 |
| [멋쟁이사자처럼 - 유니티 스튜디오 인턴십] Level Editor Vaildation 분석 (0) | 2025.12.03 |
| [천도컴퍼니] 플레이어가 사망했을 때 타 플레이어가 업어가는 로직 구현 (4) (7) | 2025.12.01 |
| [멋쟁이사자처럼 - 유니티 스튜디오 인턴십] 하이퍼캐주얼 게임 기획 및 로직 확인 (0) | 2025.11.28 |