using UnityEngine;
using System.Collections.Generic;
using System.Linq;
namespace AibisDream.MiniGame.Language
{
///
/// 分析模式网格生成器
/// 根据配置数据智能生成网格布局,确保唯一解
///
public class AnalysisModeGenerator
{
private AnalysisModeData config;
private System.Random random;
public AnalysisModeGenerator(AnalysisModeData config, int seed = -1)
{
this.config = config;
this.random = seed >= 0 ? new System.Random(seed) : new System.Random();
}
///
/// 生成完整的网格数据
///
public GridCell[,] GenerateGrid(int gridWidth, int gridHeight)
{
GridCell[,] grid = new GridCell[gridHeight, gridWidth];
// 第一步:放置答案词(在正确的解码器位置)
PlaceAnswerWords(grid, gridWidth, gridHeight);
// 第二步:放置诱饵词(相同情绪,但位置不匹配解码器)
PlaceDecoyWords(grid, gridWidth, gridHeight);
// 第三步:填充中性词
FillNeutralWords(grid, gridWidth, gridHeight);
// 第四步:验证唯一解
if (!ValidateUniqueSolution(grid, gridWidth, gridHeight))
{
Debug.LogWarning("[AnalysisModeGenerator] 生成的网格可能没有唯一解,建议调整配置");
}
return grid;
}
///
/// 放置答案词
///
private void PlaceAnswerWords(GridCell[,] grid, int gridWidth, int gridHeight)
{
Vector2Int decoderPos = config.correctDecoderPosition;
for (int i = 0; i < config.answerWords.Count; i++)
{
// 计算答案词的绝对位置 = 解码器位置 + 孔洞相对位置
Vector2Int holeOffset = config.holePositions[i];
int row = decoderPos.x + holeOffset.x;
int col = decoderPos.y + holeOffset.y;
// 确保位置在网格范围内
if (row < 0 || row >= gridHeight || col < 0 || col >= gridWidth)
{
Debug.LogError($"[AnalysisModeGenerator] 答案词位置({row}, {col})超出网格范围");
continue;
}
// 放置答案词
grid[row, col] = new GridCell
{
row = row,
col = col,
word = config.answerWords[i],
emotion = config.answerEmotion,
isTarget = true
};
}
}
///
/// 放置诱饵词(相同情绪,但不匹配解码器)
///
private void PlaceDecoyWords(GridCell[,] grid, int gridWidth, int gridHeight)
{
// 为每种情绪生成诱饵词
EmotionType[] emotions = { EmotionType.Joy, EmotionType.Sadness, EmotionType.Anger, EmotionType.Fear };
foreach (var emotion in emotions)
{
// 获取该情绪的诱饵词数量
int decoyCount = config.decoyCountPerEmotion;
// 如果是答案情绪,减去答案词数量
if (emotion == config.answerEmotion)
{
decoyCount = Mathf.Max(0, decoyCount - config.answerWords.Count);
}
// 获取随机词语(排除答案词)
List decoyWords = config.wordPool.GetRandomWords(
emotion,
decoyCount,
emotion == config.answerEmotion ? config.answerWords : null
);
// 放置诱饵词
PlaceWordsRandomly(grid, gridWidth, gridHeight, decoyWords, emotion, false);
}
}
///
/// 填充中性词
///
private void FillNeutralWords(GridCell[,] grid, int gridWidth, int gridHeight)
{
List neutralWords = new List(config.wordPool.neutralWords);
// 随机打乱
neutralWords = neutralWords.OrderBy(x => random.Next()).ToList();
int wordIndex = 0;
for (int row = 0; row < gridHeight; row++)
{
for (int col = 0; col < gridWidth; col++)
{
if (grid[row, col] == null)
{
// 如果词库用完了,重新开始
if (wordIndex >= neutralWords.Count)
{
wordIndex = 0;
}
grid[row, col] = new GridCell
{
row = row,
col = col,
word = neutralWords[wordIndex],
emotion = EmotionType.Neutral,
isTarget = false
};
wordIndex++;
}
}
}
}
///
/// 随机放置词语
///
private void PlaceWordsRandomly(GridCell[,] grid, int gridWidth, int gridHeight,
List words, EmotionType emotion, bool isTarget)
{
List availablePositions = new List();
// 收集所有可用位置
for (int row = 0; row < gridHeight; row++)
{
for (int col = 0; col < gridWidth; col++)
{
if (grid[row, col] == null)
{
availablePositions.Add(new Vector2Int(row, col));
}
}
}
// 随机打乱
availablePositions = availablePositions.OrderBy(x => random.Next()).ToList();
// 放置词语
for (int i = 0; i < words.Count && i < availablePositions.Count; i++)
{
Vector2Int pos = availablePositions[i];
grid[pos.x, pos.y] = new GridCell
{
row = pos.x,
col = pos.y,
word = words[i],
emotion = emotion,
isTarget = isTarget
};
}
}
///
/// 验证唯一解:检查是否只有一个位置和情绪组合能匹配所有答案词
///
private bool ValidateUniqueSolution(GridCell[,] grid, int gridWidth, int gridHeight)
{
int matchCount = 0;
Vector2Int correctPos = config.correctDecoderPosition;
// 遍历所有可能的解码器位置
for (int row = 0; row <= gridHeight - config.decoderHeight; row++)
{
for (int col = 0; col <= gridWidth - config.decoderWidth; col++)
{
// 遍历所有情绪
foreach (EmotionType emotion in System.Enum.GetValues(typeof(EmotionType)))
{
if (emotion == EmotionType.Neutral) continue;
// 检查是否所有孔洞位置都匹配该情绪
bool allMatch = true;
List matchedWords = new List();
foreach (var hole in config.holePositions)
{
int checkRow = row + hole.x;
int checkCol = col + hole.y;
if (checkRow >= gridHeight || checkCol >= gridWidth)
{
allMatch = false;
break;
}
GridCell cell = grid[checkRow, checkCol];
if (cell == null || cell.emotion != emotion)
{
allMatch = false;
break;
}
matchedWords.Add(cell.word);
}
// 如果所有孔洞都匹配
if (allMatch)
{
matchCount++;
// 检查是否是正确答案
bool isCorrectAnswer = (row == correctPos.x && col == correctPos.y &&
emotion == config.answerEmotion);
if (isCorrectAnswer)
{
// 验证词语是否完全匹配
bool wordsMatch = true;
for (int i = 0; i < config.answerWords.Count; i++)
{
if (matchedWords[i] != config.answerWords[i])
{
wordsMatch = false;
break;
}
}
if (!wordsMatch)
{
Debug.LogError("[AnalysisModeGenerator] 正确位置的词语不匹配答案!");
return false;
}
}
else
{
// 诱饵解
Debug.Log($"[AnalysisModeGenerator] 发现诱饵解: 位置({row},{col}), 情绪{emotion}, 词语[{string.Join(",", matchedWords)}]");
}
}
}
}
}
// 应该恰好有一个解
if (matchCount == 0)
{
Debug.LogError("[AnalysisModeGenerator] 没有找到任何解!");
return false;
}
else if (matchCount > 1)
{
Debug.LogWarning($"[AnalysisModeGenerator] 找到 {matchCount} 个可能的解(包括诱饵),这可能增加难度");
}
else
{
Debug.Log("[AnalysisModeGenerator] 验证通过:唯一解");
}
return true;
}
///
/// 生成笑话演出数据(可选)
/// 将网格数据转换为笑话段落,用于初始演出
///
public List GenerateJokePhrases(GridCell[,] grid, int gridWidth, int gridHeight)
{
// 如果配置中有笑话,直接使用
if (config.jokePhrases != null && config.jokePhrases.Count > 0)
{
return new List(config.jokePhrases);
}
// 否则从网格词语生成简单的笑话段落
List phrases = new List();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for (int row = 0; row < gridHeight; row++)
{
for (int col = 0; col < gridWidth; col += 10) // 每10个词组成一句
{
sb.Clear();
for (int i = 0; i < 10 && col + i < gridWidth; i++)
{
if (grid[row, col + i] != null)
{
sb.Append(grid[row, col + i].word);
}
}
if (sb.Length > 0)
{
phrases.Add(sb.ToString());
}
}
}
return phrases;
}
///
/// 生成解析目标配置(用于 AnalysisModeManager)
///
public AnalysisTarget GenerateAnalysisTarget()
{
AnalysisTarget target = new AnalysisTarget
{
name = config.levelName,
emotion = config.answerEmotion,
stripPosition = config.correctDecoderPosition,
isCorrectAnswer = true,
words = new List()
};
// 添加目标词
for (int i = 0; i < config.answerWords.Count; i++)
{
Vector2Int holeOffset = config.holePositions[i];
Vector2Int absolutePos = new Vector2Int(
config.correctDecoderPosition.x + holeOffset.x,
config.correctDecoderPosition.y + holeOffset.y
);
target.words.Add(new TargetWord
{
position = absolutePos,
word = config.answerWords[i]
});
}
return target;
}
}
}