....
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
// packages/feature_game_finddiff/lib/controllers/finddiff_controller.dart
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/finddiff_models.dart';
|
||||
import '../utils/hangul_utils.dart';
|
||||
|
||||
class FindDiffController with ChangeNotifier {
|
||||
late FindDiffDifficulty difficulty;
|
||||
@@ -13,34 +12,35 @@ class FindDiffController with ChangeNotifier {
|
||||
List<FindDiffItem> _items = [];
|
||||
List<FindDiffItem> get items => _items;
|
||||
|
||||
// 게임 상태
|
||||
int _currentRound = 0;
|
||||
int get currentRound => _currentRound;
|
||||
|
||||
int _score = 0;
|
||||
int get score => _score;
|
||||
|
||||
int _incorrectCount = 0;
|
||||
int _incorrectCount = 0;
|
||||
int get incorrectCount => _incorrectCount;
|
||||
|
||||
bool _isGameCompleted = false;
|
||||
bool get isGameCompleted => _isGameCompleted;
|
||||
|
||||
// 타이머
|
||||
Timer? _timer;
|
||||
int _remainingTime = 0;
|
||||
int get remainingTime => _remainingTime;
|
||||
int _secondsElapsed = 0;
|
||||
int get secondsElapsed => _secondsElapsed;
|
||||
|
||||
// [🔥 신규] 게임 시작 여부 (가이드 확인 후 true)
|
||||
bool _isGameStarted = false;
|
||||
bool get isGameStarted => _isGameStarted;
|
||||
|
||||
// [🔥 신규] 피드백 상태
|
||||
bool _showFeedback = false;
|
||||
bool get showFeedback => _showFeedback;
|
||||
bool _isLastAnswerCorrect = false;
|
||||
bool get isLastAnswerCorrect => _isLastAnswerCorrect;
|
||||
|
||||
FindDiffType _currentRoundType = FindDiffType.color;
|
||||
FindDiffType get currentRoundType => _currentRoundType;
|
||||
|
||||
final Random _random = Random();
|
||||
|
||||
void setUserInfo(String userId, String? userName) {
|
||||
@@ -54,11 +54,11 @@ class FindDiffController with ChangeNotifier {
|
||||
_incorrectCount = 0;
|
||||
_currentRound = 1;
|
||||
_isGameCompleted = false;
|
||||
_isGameStarted = false; // 대기 상태
|
||||
_secondsElapsed = 0;
|
||||
_isGameStarted = false;
|
||||
_showFeedback = false;
|
||||
|
||||
_generateLevel();
|
||||
// [🔥 수정] 여기서 타이머를 시작하지 않음
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ class FindDiffController with ChangeNotifier {
|
||||
startNewGame(difficulty);
|
||||
}
|
||||
|
||||
// [🔥 신규] UI에서 호출할 타이머 시작 함수
|
||||
void startGameTimer() {
|
||||
if (_isGameStarted) return;
|
||||
_isGameStarted = true;
|
||||
@@ -79,53 +78,126 @@ class FindDiffController with ChangeNotifier {
|
||||
final int totalItems = difficulty.totalItems;
|
||||
final int targetIndex = _random.nextInt(totalItems);
|
||||
|
||||
// 1. 기본 속성 결정
|
||||
IconData baseIcon = Icons.circle;
|
||||
// 1. 문제 유형 결정
|
||||
if (difficulty.diffType == FindDiffType.mix) {
|
||||
const List<FindDiffType> types = [
|
||||
FindDiffType.color, FindDiffType.icon, FindDiffType.rotate,
|
||||
FindDiffType.category, FindDiffType.word
|
||||
];
|
||||
_currentRoundType = types[_random.nextInt(types.length)];
|
||||
} else {
|
||||
_currentRoundType = difficulty.diffType;
|
||||
}
|
||||
|
||||
// 2. 기본 속성 준비
|
||||
IconData? baseIcon;
|
||||
String? baseText;
|
||||
String? targetText;
|
||||
Color baseColor = Colors.blue;
|
||||
double baseAngle = 0.0;
|
||||
|
||||
// [🔥 핵심] 유형별 아이콘/데이터 소스 분리
|
||||
if (_currentRoundType == FindDiffType.category) {
|
||||
// 카테고리 (나중에 루프에서 결정)
|
||||
|
||||
} else if (_currentRoundType == FindDiffType.word) {
|
||||
// 단어 & 오타
|
||||
final String originalWord = FindDiffDifficulties.baseWords[
|
||||
_random.nextInt(FindDiffDifficulties.baseWords.length)
|
||||
];
|
||||
final String modifiedWord = HangulUtils.generateSimilarWord(originalWord);
|
||||
if (_random.nextBool()) {
|
||||
baseText = originalWord;
|
||||
targetText = modifiedWord;
|
||||
} else {
|
||||
baseText = modifiedWord;
|
||||
targetText = originalWord;
|
||||
}
|
||||
baseColor = Colors.black87;
|
||||
|
||||
// 난이도별 속성 설정
|
||||
if (difficulty.diffType == FindDiffType.icon) {
|
||||
} else if (_currentRoundType == FindDiffType.icon) {
|
||||
// 모양 찾기
|
||||
final pair = FindDiffDifficulties.iconPairs[_random.nextInt(FindDiffDifficulties.iconPairs.length)];
|
||||
baseIcon = pair[0];
|
||||
baseIcon = pair[0];
|
||||
baseColor = Colors.black87;
|
||||
|
||||
} else if (_currentRoundType == FindDiffType.rotate) {
|
||||
// [🔥 수정] 회전 모드: rotateIcons에서 선택 (원, 네모 등 제외)
|
||||
baseIcon = FindDiffDifficulties.rotateIcons[_random.nextInt(FindDiffDifficulties.rotateIcons.length)];
|
||||
baseColor = Color.fromARGB(255, _random.nextInt(200), _random.nextInt(200), _random.nextInt(200));
|
||||
|
||||
} else {
|
||||
baseIcon = FindDiffDifficulties.basicIcons[_random.nextInt(FindDiffDifficulties.basicIcons.length)];
|
||||
// 색상 모드: colorIcons에서 선택
|
||||
baseIcon = FindDiffDifficulties.colorIcons[_random.nextInt(FindDiffDifficulties.colorIcons.length)];
|
||||
baseColor = Color.fromARGB(255, _random.nextInt(200), _random.nextInt(200), _random.nextInt(200));
|
||||
}
|
||||
|
||||
// 2. 아이템 생성
|
||||
// 카테고리 모드용 리스트 준비
|
||||
List<String> baseCatList = [];
|
||||
List<String> targetCatList = [];
|
||||
if (_currentRoundType == FindDiffType.category) {
|
||||
final keys = FindDiffDifficulties.emojiCategories.keys.toList();
|
||||
String baseKey = keys[_random.nextInt(keys.length)];
|
||||
String targetKey;
|
||||
do { targetKey = keys[_random.nextInt(keys.length)]; } while (baseKey == targetKey);
|
||||
baseCatList = FindDiffDifficulties.emojiCategories[baseKey]!;
|
||||
targetCatList = FindDiffDifficulties.emojiCategories[targetKey]!;
|
||||
}
|
||||
|
||||
// 3. 아이템 배치
|
||||
for (int i = 0; i < totalItems; i++) {
|
||||
bool isTarget = (i == targetIndex);
|
||||
|
||||
IconData icon = baseIcon;
|
||||
IconData? icon = baseIcon;
|
||||
String? textContent = baseText;
|
||||
Color color = baseColor;
|
||||
double angle = baseAngle;
|
||||
|
||||
if (isTarget) {
|
||||
// 정답 아이템 변형
|
||||
switch (difficulty.diffType) {
|
||||
case FindDiffType.color:
|
||||
int offset = (difficulty.levelIndex >= 4) ? 30 : 60;
|
||||
color = Color.fromARGB(
|
||||
255,
|
||||
(baseColor.red + offset) % 255,
|
||||
(baseColor.green + offset) % 255,
|
||||
(baseColor.blue + offset) % 255,
|
||||
);
|
||||
break;
|
||||
case FindDiffType.icon:
|
||||
final pair = FindDiffDifficulties.iconPairs.firstWhere((p) => p.contains(baseIcon));
|
||||
icon = (baseIcon == pair[0]) ? pair[1] : pair[0];
|
||||
break;
|
||||
case FindDiffType.rotate:
|
||||
angle = 0.5; // 약 30도 회전
|
||||
break;
|
||||
}
|
||||
switch (_currentRoundType) {
|
||||
case FindDiffType.color:
|
||||
if (isTarget) {
|
||||
// 난이도가 높거나 믹스 모드일 경우 색상 차이를 미세하게
|
||||
int offset = (difficulty.levelIndex >= 5) ? 30 : 60;
|
||||
color = Color.fromARGB(255, (baseColor.red + offset) % 255, (baseColor.green + offset) % 255, (baseColor.blue + offset) % 255);
|
||||
}
|
||||
break;
|
||||
|
||||
case FindDiffType.icon:
|
||||
if (isTarget) {
|
||||
final pair = FindDiffDifficulties.iconPairs.firstWhere((p) => p.contains(baseIcon));
|
||||
icon = (baseIcon == pair[0]) ? pair[1] : pair[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case FindDiffType.rotate:
|
||||
if (isTarget) angle = 0.5; // 약 30도 회전
|
||||
break;
|
||||
|
||||
case FindDiffType.category:
|
||||
if (isTarget) {
|
||||
textContent = targetCatList[_random.nextInt(targetCatList.length)];
|
||||
} else {
|
||||
textContent = baseCatList[_random.nextInt(baseCatList.length)];
|
||||
}
|
||||
color = Colors.black;
|
||||
break;
|
||||
|
||||
case FindDiffType.word:
|
||||
if (isTarget) {
|
||||
textContent = targetText;
|
||||
} else {
|
||||
textContent = baseText;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_items.add(FindDiffItem(
|
||||
id: i,
|
||||
icon: icon,
|
||||
textContent: textContent,
|
||||
color: color,
|
||||
angle: angle,
|
||||
isTarget: isTarget,
|
||||
@@ -135,13 +207,13 @@ class FindDiffController with ChangeNotifier {
|
||||
_remainingTime = difficulty.timeLimitSeconds;
|
||||
}
|
||||
|
||||
// ... (나머지 메서드 동일) ...
|
||||
void _startTimer() {
|
||||
_timer?.cancel();
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
_secondsElapsed++;
|
||||
_remainingTime--;
|
||||
|
||||
if (_remainingTime <= 0) {
|
||||
// 시간 초과: 오답 처리 및 다음 문제
|
||||
_handleAnswer(false);
|
||||
}
|
||||
notifyListeners();
|
||||
@@ -150,12 +222,11 @@ class FindDiffController with ChangeNotifier {
|
||||
|
||||
void onItemTapped(FindDiffItem item) {
|
||||
if (!_isGameStarted || _isGameCompleted || _showFeedback) return;
|
||||
|
||||
_handleAnswer(item.isTarget);
|
||||
}
|
||||
|
||||
void _handleAnswer(bool isCorrect) {
|
||||
_timer?.cancel(); // 잠시 멈춤
|
||||
_timer?.cancel();
|
||||
_showFeedback = true;
|
||||
_isLastAnswerCorrect = isCorrect;
|
||||
|
||||
@@ -164,18 +235,15 @@ class FindDiffController with ChangeNotifier {
|
||||
} else {
|
||||
_incorrectCount++;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
|
||||
// 피드백 후 다음 라운드
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
if (_score >= 10) { // [목표] 10문제 맞추면 클리어
|
||||
if (_score >= 10) {
|
||||
_isGameCompleted = true;
|
||||
} else {
|
||||
_currentRound++;
|
||||
_showFeedback = false;
|
||||
_generateLevel();
|
||||
_startTimer(); // 타이머 재개
|
||||
_startTimer();
|
||||
}
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user