...
This commit is contained in:
parent
09665fa073
commit
3228e370c5
@ -32,10 +32,15 @@ class CardFlipController with ChangeNotifier {
|
|||||||
int _remainingTime = 0;
|
int _remainingTime = 0;
|
||||||
int get remainingTime => _remainingTime;
|
int get remainingTime => _remainingTime;
|
||||||
|
|
||||||
// [🔥 신규] 게임이 시작되었는지(타이머가 도는지) 여부
|
|
||||||
bool _isGameStarted = false;
|
bool _isGameStarted = false;
|
||||||
bool get isGameStarted => _isGameStarted;
|
bool get isGameStarted => _isGameStarted;
|
||||||
|
|
||||||
|
// [🔥 신규] 매칭된 쌍의 개수
|
||||||
|
int get matchedPairsCount => _cards.where((c) => c.isMatched).length ~/ 2;
|
||||||
|
|
||||||
|
// [🔥 신규] 총 쌍의 개수
|
||||||
|
int get totalPairsCount => _cards.length ~/ 2;
|
||||||
|
|
||||||
void setUserInfo(String userId, String? userName) {
|
void setUserInfo(String userId, String? userName) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.userName = userName;
|
this.userName = userName;
|
||||||
@ -49,21 +54,17 @@ class CardFlipController with ChangeNotifier {
|
|||||||
_isGameCompleted = false;
|
_isGameCompleted = false;
|
||||||
_isTimeOut = false;
|
_isTimeOut = false;
|
||||||
_isProcessing = false;
|
_isProcessing = false;
|
||||||
_isGameStarted = false; // 타이머 대기 상태
|
_isGameStarted = false;
|
||||||
_firstFlippedCard = null;
|
_firstFlippedCard = null;
|
||||||
|
|
||||||
_generateCards();
|
_generateCards();
|
||||||
// [🔥 수정] startNewGame에서는 타이머를 시작하지 않음 (가이드 확인 후 시작)
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void restartGame() {
|
void restartGame() {
|
||||||
startNewGame(difficulty);
|
startNewGame(difficulty);
|
||||||
// 재시작 시에는 가이드 없이 바로 시작하고 싶다면 여기서 startTimer 호출
|
|
||||||
// 하지만 일관성을 위해 UI에서 다시 가이드를 띄우도록 유도
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [🔥 수정] Public으로 변경 (UI에서 호출)
|
|
||||||
void startGameTimer() {
|
void startGameTimer() {
|
||||||
if (_isGameStarted) return;
|
if (_isGameStarted) return;
|
||||||
_isGameStarted = true;
|
_isGameStarted = true;
|
||||||
@ -83,38 +84,61 @@ class CardFlipController with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔽 [🔥 핵심] 카드 생성 로직 (타입별 분기)
|
|
||||||
void _generateCards() {
|
void _generateCards() {
|
||||||
final int totalCards = difficulty.totalCards;
|
final int totalCards = difficulty.totalCards;
|
||||||
final int pairsCount = totalCards ~/ 2;
|
final int pairsCount = totalCards ~/ 2;
|
||||||
List<CardItem> deck = [];
|
List<CardItem> deck = [];
|
||||||
|
final Random random = Random();
|
||||||
|
|
||||||
if (difficulty.contentType == CardContentType.calculation) {
|
if (difficulty.contentType == CardContentType.calculation) {
|
||||||
// 1. 연산 모드 (식 ↔ 답)
|
final Set<int> usedResults = {};
|
||||||
var entries = CardFlipDifficulties.calculationPairs.entries.toList()..shuffle();
|
|
||||||
for (int i = 0; i < pairsCount; i++) {
|
for (int i = 0; i < pairsCount; i++) {
|
||||||
var entry = entries[i % entries.length];
|
String equation;
|
||||||
String matchKey = "CALC_$i"; // 논리적 ID
|
String answer;
|
||||||
// 식 카드
|
int result;
|
||||||
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.key));
|
|
||||||
// 답 카드
|
while (true) {
|
||||||
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.value));
|
final int opType = random.nextInt(3);
|
||||||
|
int a, b;
|
||||||
|
if (opType == 0) { // +
|
||||||
|
a = random.nextInt(15) + 1;
|
||||||
|
b = random.nextInt(15) + 1;
|
||||||
|
result = a + b;
|
||||||
|
equation = "$a + $b";
|
||||||
|
} else if (opType == 1) { // -
|
||||||
|
a = random.nextInt(20) + 5;
|
||||||
|
b = random.nextInt(a - 1) + 1;
|
||||||
|
result = a - b;
|
||||||
|
equation = "$a - $b";
|
||||||
|
} else { // *
|
||||||
|
a = random.nextInt(9) + 2;
|
||||||
|
b = random.nextInt(5) + 2;
|
||||||
|
result = a * b;
|
||||||
|
equation = "$a x $b";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usedResults.contains(result)) {
|
||||||
|
usedResults.add(result);
|
||||||
|
answer = result.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String matchKey = "CALC_$i";
|
||||||
|
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: equation));
|
||||||
|
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: answer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (difficulty.contentType == CardContentType.pairWord) {
|
else if (difficulty.contentType == CardContentType.pairWord) {
|
||||||
// 2. 연상 모드 (A ↔ B)
|
|
||||||
var entries = CardFlipDifficulties.wordPairs.entries.toList()..shuffle();
|
var entries = CardFlipDifficulties.wordPairs.entries.toList()..shuffle();
|
||||||
for (int i = 0; i < pairsCount; i++) {
|
for (int i = 0; i < pairsCount; i++) {
|
||||||
var entry = entries[i % entries.length];
|
var entry = entries[i % entries.length];
|
||||||
String matchKey = "PAIR_$i";
|
String matchKey = "PAIR_$i";
|
||||||
// 단어 A
|
|
||||||
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.key));
|
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.key));
|
||||||
// 단어 B
|
|
||||||
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.value));
|
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 3. 동일 매칭 모드 (이모지, 아이콘, 숫자)
|
|
||||||
List<String> pool = List.of(CardFlipDifficulties.emojis)..shuffle();
|
List<String> pool = List.of(CardFlipDifficulties.emojis)..shuffle();
|
||||||
for (int i = 0; i < pairsCount; i++) {
|
for (int i = 0; i < pairsCount; i++) {
|
||||||
String content;
|
String content;
|
||||||
@ -128,16 +152,13 @@ class CardFlipController with ChangeNotifier {
|
|||||||
content = pool[i % pool.length];
|
content = pool[i % pool.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 똑같은 카드 2장
|
|
||||||
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: content));
|
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: content));
|
||||||
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: content));
|
deck.add(CardItem(id: 0, matchId: matchKey, displayContent: content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 전체 섞기 및 ID 부여
|
deck.shuffle(random);
|
||||||
deck.shuffle(Random());
|
|
||||||
for (int i = 0; i < deck.length; i++) {
|
for (int i = 0; i < deck.length; i++) {
|
||||||
// 기존 객체를 복사하며 고유 ID 부여
|
|
||||||
deck[i] = CardItem(
|
deck[i] = CardItem(
|
||||||
id: i,
|
id: i,
|
||||||
matchId: deck[i].matchId,
|
matchId: deck[i].matchId,
|
||||||
@ -147,9 +168,7 @@ class CardFlipController with ChangeNotifier {
|
|||||||
_cards = deck;
|
_cards = deck;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔽 [핵심] 카드 뒤집기 로직
|
|
||||||
void onCardTapped(CardItem card) {
|
void onCardTapped(CardItem card) {
|
||||||
// 게임이 시작되지 않았거나, 이미 완료되었거나, 처리 중이면 무시
|
|
||||||
if (!_isGameStarted || _isGameCompleted || _isProcessing || card.isFaceUp || card.isMatched) return;
|
if (!_isGameStarted || _isGameCompleted || _isProcessing || card.isFaceUp || card.isMatched) return;
|
||||||
|
|
||||||
card.isFaceUp = true;
|
card.isFaceUp = true;
|
||||||
@ -165,10 +184,8 @@ class CardFlipController with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔽 [🔥 수정] 매칭 로직: matchId로 비교
|
|
||||||
void _checkMatch(CardItem card1, CardItem card2) {
|
void _checkMatch(CardItem card1, CardItem card2) {
|
||||||
if (card1.matchId == card2.matchId) {
|
if (card1.matchId == card2.matchId) {
|
||||||
// 정답
|
|
||||||
card1.isMatched = true;
|
card1.isMatched = true;
|
||||||
card2.isMatched = true;
|
card2.isMatched = true;
|
||||||
_isProcessing = false;
|
_isProcessing = false;
|
||||||
@ -179,7 +196,6 @@ class CardFlipController with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} else {
|
} else {
|
||||||
// 오답
|
|
||||||
Future.delayed(const Duration(milliseconds: 800), () {
|
Future.delayed(const Duration(milliseconds: 800), () {
|
||||||
card1.isFaceUp = false;
|
card1.isFaceUp = false;
|
||||||
card2.isFaceUp = false;
|
card2.isFaceUp = false;
|
||||||
|
|||||||
@ -3,20 +3,18 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:service_api/service_api.dart';
|
import 'package:service_api/service_api.dart';
|
||||||
|
|
||||||
/// 카드에 들어갈 콘텐츠 타입
|
|
||||||
enum CardContentType {
|
enum CardContentType {
|
||||||
emoji, // 기존: 똑같은 이모지 (🐰 ↔ 🐰)
|
emoji, // 🐰 ↔ 🐰
|
||||||
icon, // 기존: 똑같은 아이콘 (⭐️ ↔ ⭐️)
|
icon, // ⭐️ ↔ ⭐️
|
||||||
number, // 기존: 똑같은 숫자 (1 ↔ 1)
|
number, // 1 ↔ 1
|
||||||
calculation, // [🔥 신규] 연산 (3+4 ↔ 7)
|
calculation, // 3+4 ↔ 7 (동적 생성)
|
||||||
pairWord, // [🔥 신규] 연상 단어 (토끼 ↔ 당근)
|
pairWord, // 토끼 ↔ 당근
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 개별 카드 상태 모델
|
|
||||||
class CardItem {
|
class CardItem {
|
||||||
final int id; // 카드의 고유 식별자 (GridView 인덱스와 무관, 셔플됨)
|
final int id;
|
||||||
final String matchId; // [🔥 신규] 매칭 판단용 ID (이게 같으면 정답)
|
final String matchId;
|
||||||
final String displayContent; // [🔥 신규] 화면에 보여질 내용
|
final String displayContent;
|
||||||
|
|
||||||
bool isFaceUp;
|
bool isFaceUp;
|
||||||
bool isMatched;
|
bool isMatched;
|
||||||
@ -51,7 +49,7 @@ class CardFlipDifficulty extends GameDifficulty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CardFlipDifficulties {
|
class CardFlipDifficulties {
|
||||||
// --- 콘텐츠 풀 ---
|
// 이모지 풀
|
||||||
static const List<String> emojis = [
|
static const List<String> emojis = [
|
||||||
"🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯",
|
"🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯",
|
||||||
"🦁", "🐮", "🐷", "🐸", "🐵", "🐔", "🐧", "🐦", "🐤", "🦆",
|
"🦁", "🐮", "🐷", "🐸", "🐵", "🐔", "🐧", "🐦", "🐤", "🦆",
|
||||||
@ -59,14 +57,9 @@ class CardFlipDifficulties {
|
|||||||
"⚽", "🏀", "🏈", "⚾", "🎾", "🏐", "🏉", "🎱", "🏓", "🏸"
|
"⚽", "🏀", "🏈", "⚾", "🎾", "🏐", "🏉", "🎱", "🏓", "🏸"
|
||||||
];
|
];
|
||||||
|
|
||||||
// [🔥 신규] 연산 문제 풀 (질문 : 정답)
|
// ❌ [삭제됨] calculationPairs (컨트롤러에서 동적 생성하므로 제거)
|
||||||
static const Map<String, String> calculationPairs = {
|
|
||||||
"2 + 3": "5", "5 + 5": "10", "7 - 2": "5", "3 x 3": "9", "10 - 4": "6",
|
|
||||||
"6 + 6": "12", "8 + 1": "9", "4 x 2": "8", "15 - 5": "10", "20 / 2": "10",
|
|
||||||
"1 + 1": "2", "9 - 3": "6", "2 x 5": "10", "8 / 2": "4", "3 + 7": "10"
|
|
||||||
};
|
|
||||||
|
|
||||||
// [🔥 신규] 연상 단어 풀 (A : B)
|
// 연상 단어 풀 (A : B)
|
||||||
static const Map<String, String> wordPairs = {
|
static const Map<String, String> wordPairs = {
|
||||||
"토끼": "당근", "원숭이": "바나나", "한국": "서울", "미국": "워싱턴",
|
"토끼": "당근", "원숭이": "바나나", "한국": "서울", "미국": "워싱턴",
|
||||||
"해": "달", "여름": "겨울", "남자": "여자", "학교": "학생",
|
"해": "달", "여름": "겨울", "남자": "여자", "학교": "학생",
|
||||||
@ -74,7 +67,7 @@ class CardFlipDifficulties {
|
|||||||
"봄": "꽃", "가을": "단풍", "숟가락": "젓가락"
|
"봄": "꽃", "가을": "단풍", "숟가락": "젓가락"
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- 난이도 목록 (15단계) ---
|
// 난이도 목록 (15단계)
|
||||||
static final List<CardFlipDifficulty> allDifficulties = [
|
static final List<CardFlipDifficulty> allDifficulties = [
|
||||||
// Phase 1: 입문 (동일 매칭)
|
// Phase 1: 입문 (동일 매칭)
|
||||||
const CardFlipDifficulty(levelIndex: 1, name: 'Lv. 1: 입문 (이모지 12)', contextId: 'FLIP_L1_EMOJI', rows: 4, cols: 3, timeLimitSeconds: 40, contentType: CardContentType.emoji),
|
const CardFlipDifficulty(levelIndex: 1, name: 'Lv. 1: 입문 (이모지 12)', contextId: 'FLIP_L1_EMOJI', rows: 4, cols: 3, timeLimitSeconds: 40, contentType: CardContentType.emoji),
|
||||||
@ -100,6 +93,8 @@ class CardFlipDifficulties {
|
|||||||
const CardFlipDifficulty(levelIndex: 13, name: 'Lv. 13: 갓모드 (30장)', contextId: 'FLIP_L13_6x5', rows: 6, cols: 5, timeLimitSeconds: 130, contentType: CardContentType.emoji),
|
const CardFlipDifficulty(levelIndex: 13, name: 'Lv. 13: 갓모드 (30장)', contextId: 'FLIP_L13_6x5', rows: 6, cols: 5, timeLimitSeconds: 130, contentType: CardContentType.emoji),
|
||||||
const CardFlipDifficulty(levelIndex: 14, name: 'Lv. 14: 타임어택 (연산)', contextId: 'FLIP_L14_6x5_CALC', rows: 6, cols: 5, timeLimitSeconds: 120, contentType: CardContentType.calculation),
|
const CardFlipDifficulty(levelIndex: 14, name: 'Lv. 14: 타임어택 (연산)', contextId: 'FLIP_L14_6x5_CALC', rows: 6, cols: 5, timeLimitSeconds: 120, contentType: CardContentType.calculation),
|
||||||
const CardFlipDifficulty(levelIndex: 15, name: 'Lv. 15: 엔드게임 (연상)', contextId: 'FLIP_L15_6x5_PAIR', rows: 6, cols: 5, timeLimitSeconds: 120, contentType: CardContentType.pairWord),
|
const CardFlipDifficulty(levelIndex: 15, name: 'Lv. 15: 엔드게임 (연상)', contextId: 'FLIP_L15_6x5_PAIR', rows: 6, cols: 5, timeLimitSeconds: 120, contentType: CardContentType.pairWord),
|
||||||
|
|
||||||
|
const CardFlipDifficulty(levelIndex: 16, name: 'Lv. 15: 헬 (연상)', contextId: 'FLIP_L16_6x6_PAIR', rows: 6, cols: 6, timeLimitSeconds: 120, contentType: CardContentType.pairWord),
|
||||||
];
|
];
|
||||||
|
|
||||||
static CardFlipDifficulty getLevel(int levelIndex) {
|
static CardFlipDifficulty getLevel(int levelIndex) {
|
||||||
|
|||||||
@ -17,7 +17,6 @@ class CardFlipGameScreen extends StatefulWidget {
|
|||||||
class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
||||||
bool _isDialogShowing = false;
|
bool _isDialogShowing = false;
|
||||||
|
|
||||||
// 아이콘 풀
|
|
||||||
static const List<IconData> _iconPool = [
|
static const List<IconData> _iconPool = [
|
||||||
Icons.home, Icons.favorite, Icons.star, Icons.person, Icons.settings,
|
Icons.home, Icons.favorite, Icons.star, Icons.person, Icons.settings,
|
||||||
Icons.lock, Icons.map, Icons.camera_alt, Icons.phone, Icons.music_note,
|
Icons.lock, Icons.map, Icons.camera_alt, Icons.phone, Icons.music_note,
|
||||||
@ -31,13 +30,11 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// [🔥 신규] 게임 시작 전 가이드 표시
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_showGameGuide();
|
_showGameGuide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔽 [🔥 신규] 게임 가이드 다이얼로그
|
|
||||||
void _showGameGuide() {
|
void _showGameGuide() {
|
||||||
final controller = context.read<CardFlipController>();
|
final controller = context.read<CardFlipController>();
|
||||||
final difficulty = controller.difficulty;
|
final difficulty = controller.difficulty;
|
||||||
@ -55,7 +52,7 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false, // 반드시 확인을 눌러야 함
|
barrierDismissible: false,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
|
title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
content: Text(message, style: const TextStyle(fontSize: 16), textAlign: TextAlign.center),
|
content: Text(message, style: const TextStyle(fontSize: 16), textAlign: TextAlign.center),
|
||||||
@ -63,7 +60,6 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
// [🔥 핵심] 가이드 닫으면 타이머 시작
|
|
||||||
controller.startGameTimer();
|
controller.startGameTimer();
|
||||||
},
|
},
|
||||||
child: const Text("시작하기"),
|
child: const Text("시작하기"),
|
||||||
@ -74,8 +70,17 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showGameCompletion(CardFlipController controller) async {
|
void _showGameCompletion(CardFlipController controller) async {
|
||||||
|
// [🔥 수정] 점수 포맷터: secondaryScore를 디코딩하여 표시
|
||||||
|
// (secondary = matched * 1000 + (999 - flips))
|
||||||
String formatScore(int primary, int? secondary) {
|
String formatScore(int primary, int? secondary) {
|
||||||
return '남은 시간: ${primary}초 (시도: $secondary회)';
|
if (secondary == null) return '${primary}초';
|
||||||
|
|
||||||
|
final int matched = secondary ~/ 1000;
|
||||||
|
final int flips = 999 - (secondary % 1000);
|
||||||
|
// (실패 횟수 = (총 뒤집기 - 정답매칭*2) / 2)
|
||||||
|
final int mistakes = (flips - (matched * 2)) ~/ 2;
|
||||||
|
|
||||||
|
return '시간: ${primary}초 (성공:$matched / 실수:$mistakes)';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveProgress(String playerName) async {
|
Future<void> saveProgress(String playerName) async {
|
||||||
@ -94,6 +99,10 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [🔥 수정] secondaryScore에 매칭 수와 클릭 수를 함께 인코딩 (정렬을 위해)
|
||||||
|
// (많은 매칭 + 적은 클릭일수록 높은 값이 되도록 설계)
|
||||||
|
final int encodedScore = (controller.matchedPairsCount * 1000) + (999 - controller.flipCount);
|
||||||
|
|
||||||
await Navigator.push(
|
await Navigator.push(
|
||||||
context,
|
context,
|
||||||
@ -103,7 +112,7 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
gameType: 'CARD_FLIP',
|
gameType: 'CARD_FLIP',
|
||||||
contextId: controller.difficulty.contextId,
|
contextId: controller.difficulty.contextId,
|
||||||
primaryScore: controller.remainingTime,
|
primaryScore: controller.remainingTime,
|
||||||
secondaryScore: controller.flipCount,
|
secondaryScore: encodedScore, // 👈 인코딩된 점수 전달
|
||||||
userId: controller.userId,
|
userId: controller.userId,
|
||||||
userName: controller.userName,
|
userName: controller.userName,
|
||||||
scoreFormatter: formatScore,
|
scoreFormatter: formatScore,
|
||||||
@ -149,10 +158,24 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
|
// 🔽 [🔥 수정] 상단 정보: 매칭 수 / 시도 횟수 표시
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(12.0),
|
||||||
child: Text("뒤집은 횟수: ${controller.flipCount}", style: TextStyle(fontSize: 16, color: theme.textTheme.bodyMedium?.color)),
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"찾은 짝: ${controller.matchedPairsCount} / ${controller.totalPairsCount}",
|
||||||
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: theme.primaryColor)
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"뒤집기: ${controller.flipCount}",
|
||||||
|
style: const TextStyle(fontSize: 16, color: Colors.grey)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@ -206,7 +229,6 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔽 [🔥 수정] displayContent 사용
|
|
||||||
Widget _buildCardContent(CardItem card) {
|
Widget _buildCardContent(CardItem card) {
|
||||||
if (card.displayContent.startsWith("ICON_")) {
|
if (card.displayContent.startsWith("ICON_")) {
|
||||||
final int iconIndex = int.tryParse(card.displayContent.split('_')[1]) ?? 0;
|
final int iconIndex = int.tryParse(card.displayContent.split('_')[1]) ?? 0;
|
||||||
@ -218,7 +240,7 @@ class _CardFlipGameScreenState extends State<CardFlipGameScreen> {
|
|||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
child: Text(
|
child: Text(
|
||||||
card.displayContent, // 👈 displayContent 표시
|
card.displayContent,
|
||||||
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
|
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user