DO-4 [Style] 공유되는 변수 정리
This commit is contained in:
parent
b382e82059
commit
3eb595b143
12
Assets/Script/AI/AIConstants.cs
Normal file
12
Assets/Script/AI/AIConstants.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// AI에서만 사용하는 상수 모음
|
||||
public class AIConstants
|
||||
{
|
||||
// 방향 상수
|
||||
public static readonly int[][] Directions = new int[][]
|
||||
{
|
||||
new int[] {1, 0}, // 수직
|
||||
new int[] {0, 1}, // 수평
|
||||
new int[] {1, 1}, // 대각선 ↘ ↖
|
||||
new int[] {1, -1} // 대각선 ↙ ↗
|
||||
};
|
||||
}
|
3
Assets/Script/AI/AIConstants.cs.meta
Normal file
3
Assets/Script/AI/AIConstants.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de0993e48b9548668a73768a38c11b6d
|
||||
timeCreated: 1742362879
|
@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public static class AIEvaluator
|
||||
{
|
||||
// 패턴 가중치 상수
|
||||
public static class PatternScore
|
||||
public struct PatternScore
|
||||
{
|
||||
// AI 패턴 점수
|
||||
public const float FIVE_IN_A_ROW = 100000f;
|
||||
@ -31,14 +32,7 @@ public static class AIEvaluator
|
||||
public const float EDGE_WEIGHT = 0.8f;
|
||||
}
|
||||
|
||||
// 방향 상수 -> public으로 빼기
|
||||
private static readonly int[][] Directions = new int[][]
|
||||
{
|
||||
new int[] {1, 0}, // 수직
|
||||
new int[] {0, 1}, // 수평
|
||||
new int[] {1, 1}, // 대각선 ↘ ↖
|
||||
new int[] {1, -1} // 대각선 ↙ ↗
|
||||
};
|
||||
private static readonly int[][] Directions = AIConstants.Directions;
|
||||
|
||||
// 보드 전체 상태 평가
|
||||
public static float EvaluateBoard(Enums.PlayerType[,] board, Enums.PlayerType aiPlayer)
|
||||
@ -102,7 +96,7 @@ public static class AIEvaluator
|
||||
// 위치 가중치 적용
|
||||
patternScore *= positionWeight;
|
||||
|
||||
// 최종 점수 적용 (플레이어는 음수)
|
||||
// 최종 점수 (플레이어는 음수)
|
||||
score += playerScore * patternScore;
|
||||
}
|
||||
}
|
||||
@ -310,19 +304,24 @@ public static class AIEvaluator
|
||||
return fourThreeCount;
|
||||
}
|
||||
|
||||
// 이동 평가 함수 (EvaluateMove 대체)
|
||||
// 이동 평가 함수
|
||||
public static float EvaluateMove(Enums.PlayerType[,] board, int row, int col, Enums.PlayerType AIPlayer)
|
||||
{
|
||||
float score = 0;
|
||||
Enums.PlayerType opponentPlayer = (AIPlayer == Enums.PlayerType.PlayerA) ?
|
||||
Enums.PlayerType.PlayerB : Enums.PlayerType.PlayerA;
|
||||
|
||||
// 복합 패턴 감지를 위한 위치 저장 리스트
|
||||
List<(int[] dir, int count, int openEnds)> aiPatterns = new List<(int[], int, int)>();
|
||||
List<(int[] dir, int count, int openEnds)> opponentPatterns = new List<(int[], int, int)>();
|
||||
|
||||
// AI 관점에서 평가
|
||||
board[row, col] = AIPlayer;
|
||||
|
||||
foreach (var dir in Directions)
|
||||
{
|
||||
var (count, openEnds) = MiniMaxAIController.CountStones(board, row, col, dir, AIPlayer, false);
|
||||
aiPatterns.Add((dir, count, openEnds));
|
||||
|
||||
if (count >= 4)
|
||||
{
|
||||
@ -347,12 +346,16 @@ public static class AIEvaluator
|
||||
}
|
||||
}
|
||||
|
||||
// AI 복합 패턴 점수 계산 (새로 추가)
|
||||
score += EvaluateComplexMovePatterns(aiPatterns, true);
|
||||
|
||||
// 상대 관점에서 평가 (방어 가치)
|
||||
board[row, col] = opponentPlayer;
|
||||
|
||||
foreach (var dir in Directions)
|
||||
{
|
||||
var (count, openEnds) = MiniMaxAIController.CountStones(board, row, col, dir, opponentPlayer, false);
|
||||
opponentPatterns.Add((dir, count, openEnds));
|
||||
|
||||
// 상대 패턴 차단에 대한 가치 (약간 낮은 가중치)
|
||||
if (count >= 4)
|
||||
@ -378,6 +381,8 @@ public static class AIEvaluator
|
||||
}
|
||||
}
|
||||
|
||||
score += EvaluateComplexMovePatterns(opponentPatterns, false);
|
||||
|
||||
// 원래 상태로 복원
|
||||
board[row, col] = Enums.PlayerType.None;
|
||||
|
||||
@ -391,4 +396,57 @@ public static class AIEvaluator
|
||||
|
||||
return score * centerBonus;
|
||||
}
|
||||
|
||||
// 복합 패턴 평가를 위한 새로운 함수
|
||||
private static float EvaluateComplexMovePatterns(List<(int[] dir, int count, int openEnds)> patterns, bool isAI)
|
||||
{
|
||||
float score = 0;
|
||||
|
||||
// 열린 3 패턴 및 4 패턴 찾기
|
||||
var openThrees = patterns.Where(p => p.count == 3 && p.openEnds == 2).ToList();
|
||||
var fours = patterns.Where(p => p.count == 4 && p.openEnds >= 1).ToList();
|
||||
|
||||
// 3-3 패턴 감지
|
||||
if (openThrees.Count >= 2)
|
||||
{
|
||||
for (int i = 0; i < openThrees.Count; i++)
|
||||
{
|
||||
for (int j = i + 1; j < openThrees.Count; j++)
|
||||
{
|
||||
if (!AreParallelDirections(openThrees[i].dir, openThrees[j].dir))
|
||||
{
|
||||
float threeThreeScore = PatternScore.DOUBLE_THREE / 4; // 복합 패턴 가중치
|
||||
score += isAI ? threeThreeScore : threeThreeScore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4-4 패턴 감지
|
||||
if (fours.Count >= 2)
|
||||
{
|
||||
for (int i = 0; i < fours.Count; i++)
|
||||
{
|
||||
for (int j = i + 1; j < fours.Count; j++)
|
||||
{
|
||||
if (!AreParallelDirections(fours[i].dir, fours[j].dir))
|
||||
{
|
||||
float fourFourScore = PatternScore.DOUBLE_FOUR / 4;
|
||||
score += isAI ? fourFourScore : fourFourScore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4-3 패턴 감지
|
||||
if (fours.Count > 0 && openThrees.Count > 0)
|
||||
{
|
||||
float fourThreeScore = PatternScore.FOUR_THREE / 4;
|
||||
score += isAI ? fourThreeScore : fourThreeScore;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,14 @@ public static class MiniMaxAIController
|
||||
private const int SEARCH_DEPTH = 3; // 탐색 깊이 제한 (3 = 빠른 응답, 4 = 좀 더 강한 AI 그러나 느린)
|
||||
private const int WIN_COUNT = 5;
|
||||
|
||||
private static int[][] _directions = new int[][]
|
||||
{
|
||||
new int[] {1, 0}, // 수직
|
||||
new int[] {0, 1}, // 수평
|
||||
new int[] {1, 1}, // 대각선 ↘ ↖
|
||||
new int[] {1, -1} // 대각선 ↙ ↗
|
||||
};
|
||||
private static int[][] _directions = AIConstants.Directions;
|
||||
|
||||
private static int _playerLevel = 1; // 급수 설정
|
||||
private static float _mistakeMove;
|
||||
|
||||
private static Enums.PlayerType _AIPlayerType = Enums.PlayerType.PlayerB;
|
||||
|
||||
private static System.Random _random = new System.Random();
|
||||
private static System.Random _random = new System.Random(); // 랜덤 실수용 Random 함수
|
||||
|
||||
// 중복 계산을 방지하기 위한 캐싱 데이터. 위치 기반 (그리드 기반 해시맵)
|
||||
private static Dictionary<(int row, int col), Dictionary<(int dirX, int dirY), (int count, int openEnds)>>
|
||||
@ -36,7 +31,7 @@ public static class MiniMaxAIController
|
||||
public static void SetLevel(int level)
|
||||
{
|
||||
_playerLevel = level;
|
||||
|
||||
// 레벨에 따른 실수률? 설정
|
||||
_mistakeMove = GetMistakeProbability(_playerLevel);
|
||||
}
|
||||
|
||||
@ -158,7 +153,10 @@ public static class MiniMaxAIController
|
||||
|
||||
// score가 높은 순으로 정렬 -> 더 좋은 수 먼저 계산하도록 함
|
||||
validMoves.Sort((a, b) => b.Item3.CompareTo(a.Item3));
|
||||
return validMoves;
|
||||
|
||||
// 상위 10-15개만 고려. 일단 15개
|
||||
return validMoves.Take(15).ToList();
|
||||
// return validMoves;
|
||||
}
|
||||
|
||||
private static bool HasNearbyStones(Enums.PlayerType[,] board, int row, int col, int distance = 3)
|
||||
@ -274,11 +272,13 @@ public static class MiniMaxAIController
|
||||
#endregion
|
||||
|
||||
// 최근에 둔 돌 위치 기반으로 게임 승리를 판별하는 함수
|
||||
public static bool CheckGameWin(Enums.PlayerType player, Enums.PlayerType[,] board, int row, int col)
|
||||
// !!!!!!MinimaxAIController 밖의 cs파일은 호출 시 맨 마지막을 false로 지정해야 합니다.!!!!!!
|
||||
public static bool CheckGameWin(Enums.PlayerType player, Enums.PlayerType[,] board,
|
||||
int row, int col, bool isSavedCache = true)
|
||||
{
|
||||
foreach (var dir in _directions)
|
||||
{
|
||||
var (count, _) = CountStones(board, row, col, dir, player);
|
||||
var (count, _) = CountStones(board, row, col, dir, player, isSavedCache);
|
||||
|
||||
// 자기 자신 포함하여 5개 이상일 시 true 반환
|
||||
if (count + 1 >= WIN_COUNT)
|
||||
|
@ -261,7 +261,7 @@ public class GameLogic : MonoBehaviour
|
||||
ReplayManager.Instance.RecordStonePlaced(Enums.StoneType.Black, row, col); //기보 데이터 저장
|
||||
break;
|
||||
case Enums.PlayerType.PlayerB:
|
||||
/*
|
||||
|
||||
// AI 테스트 시작
|
||||
OmokAI.Instance.StartBestMoveSearch(_board, (bestMove) =>
|
||||
{
|
||||
@ -277,14 +277,15 @@ public class GameLogic : MonoBehaviour
|
||||
}
|
||||
});
|
||||
// AI 테스트 끝
|
||||
*/
|
||||
|
||||
/*
|
||||
stoneController.SetStoneType(Enums.StoneType.White, row, col);
|
||||
stoneController.SetStoneState(Enums.StoneState.LastPositioned, row, col);
|
||||
_board[row, col] = Enums.PlayerType.PlayerB;
|
||||
LastNSelectedSetting(row, col);
|
||||
|
||||
ReplayManager.Instance.RecordStonePlaced(Enums.StoneType.White, row, col);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user