This commit is contained in:
lunaticbum 2025-11-19 17:34:52 +09:00
parent 3228e370c5
commit 64f3fb8adf
2 changed files with 105 additions and 42 deletions

View File

@ -35,10 +35,7 @@ class CardFlipController with ChangeNotifier {
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 matchedPairsCount => _cards.where((c) => c.isMatched).length ~/ 2;
// [🔥 ]
int get totalPairsCount => _cards.length ~/ 2; int get totalPairsCount => _cards.length ~/ 2;
void setUserInfo(String userId, String? userName) { void setUserInfo(String userId, String? userName) {
@ -91,32 +88,56 @@ class CardFlipController with ChangeNotifier {
final Random random = Random(); final Random random = Random();
if (difficulty.contentType == CardContentType.calculation) { if (difficulty.contentType == CardContentType.calculation) {
// [🔥 ]
final Set<int> usedResults = {}; final Set<int> usedResults = {};
// 4 ( 릿 /)
final bool isLevel4 = difficulty.levelIndex == 4;
for (int i = 0; i < pairsCount; i++) { for (int i = 0; i < pairsCount; i++) {
String equation; String equation;
String answer; String answer;
int result; int result;
while (true) { while (true) {
final int opType = random.nextInt(3); // Lv 4: 0(), 1() / : 0, 1, 2()
final int opType = isLevel4 ? random.nextInt(2) : random.nextInt(3);
int a, b; int a, b;
if (opType == 0) { // +
if (opType == 0) { // (+)
if (isLevel4) {
// 릿 (1~9)
a = random.nextInt(9) + 1;
b = random.nextInt(9) + 1;
} else {
// 릿 (1~15)
a = random.nextInt(15) + 1; a = random.nextInt(15) + 1;
b = random.nextInt(15) + 1; b = random.nextInt(15) + 1;
}
result = a + b; result = a + b;
equation = "$a + $b"; equation = "$a + $b";
} else if (opType == 1) { // -
} else if (opType == 1) { // (-)
if (isLevel4) {
// 릿
a = random.nextInt(9) + 2; // 2~10
b = random.nextInt(a - 1) + 1;
} else {
a = random.nextInt(20) + 5; a = random.nextInt(20) + 5;
b = random.nextInt(a - 1) + 1; b = random.nextInt(a - 1) + 1;
}
result = a - b; result = a - b;
equation = "$a - $b"; equation = "$a - $b";
} else { // *
} else { // (*)
// Lv 4
a = random.nextInt(9) + 2; a = random.nextInt(9) + 2;
b = random.nextInt(5) + 2; b = random.nextInt(5) + 2;
result = a * b; result = a * b;
equation = "$a x $b"; equation = "$a x $b";
} }
//
if (!usedResults.contains(result)) { if (!usedResults.contains(result)) {
usedResults.add(result); usedResults.add(result);
answer = result.toString(); answer = result.toString();
@ -130,6 +151,7 @@ class CardFlipController with ChangeNotifier {
} }
} }
else if (difficulty.contentType == CardContentType.pairWord) { else if (difficulty.contentType == CardContentType.pairWord) {
//
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];
@ -139,6 +161,7 @@ class CardFlipController with ChangeNotifier {
} }
} }
else { else {
//
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;

View File

@ -7,7 +7,7 @@ enum CardContentType {
emoji, // 🐰 🐰 emoji, // 🐰 🐰
icon, // icon, //
number, // 1 1 number, // 1 1
calculation, // 3+4 7 ( ) calculation, // 3+4 7
pairWord, // pairWord, //
} }
@ -49,7 +49,7 @@ class CardFlipDifficulty extends GameDifficulty {
} }
class CardFlipDifficulties { class CardFlipDifficulties {
// // --- ---
static const List<String> emojis = [ static const List<String> emojis = [
"🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯", "🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯",
"🦁", "🐮", "🐷", "🐸", "🐵", "🐔", "🐧", "🐦", "🐤", "🦆", "🦁", "🐮", "🐷", "🐸", "🐵", "🐔", "🐧", "🐦", "🐤", "🦆",
@ -57,44 +57,84 @@ class CardFlipDifficulties {
"", "🏀", "🏈", "", "🎾", "🏐", "🏉", "🎱", "🏓", "🏸" "", "🏀", "🏈", "", "🎾", "🏐", "🏉", "🎱", "🏓", "🏸"
]; ];
// [] calculationPairs ( ) // ( 80+)
// (A : B)
static const Map<String, String> wordPairs = { static const Map<String, String> wordPairs = {
"토끼": "당근", "원숭이": "바나나", "한국": "서울", "미국": "워싱턴", "토끼": "당근", "원숭이": "바나나", "다람쥐": "도토리", "고양이": "생선",
"": "", "여름": "겨울", "남자": "여자", "학교": "학생", "": "뼈다귀", "": "여물", "": "달걀", "": "",
"병원": "의사", "바늘": "", "우산": "", "책상": "의자", "거미": "거미줄", "개구리": "올챙이", "팬더": "대나무", "호랑이": "가죽",
"": "", "가을": "단풍", "숟가락": "젓가락" "누에": "뽕잎", "": "양털", "펭귄": "남극", "사자": "초원",
"바늘": "", "망치": "", "": "화살", "자물쇠": "열쇠",
"숟가락": "젓가락", "책상": "의자", "신발": "양말", "장갑": "목도리",
"지우개": "연필", "칠판": "분필", "": "물감", "도장": "인주",
"냄비": "뚜껑", "샴푸": "린스", "치약": "칫솔", "비누": "수건",
"배게": "이불", "항아리": "뚜껑", "안경": "안경집", "핸드폰": "충전기",
"": "", "하늘": "구름", "": "우산", "": "눈사람",
"": "", "여름": "부채", "가을": "단풍", "겨울": "",
"바다": "파도", "": "나무", "사막": "선인장", "": "",
"번개": "천둥", "무지개": "비온뒤", "화산": "용암", "지진": "진동",
"": "", "": "우유", "삼겹살": "상추", "짜장면": "단무지",
"치킨": "", "떡볶이": "오뎅", "피자": "콜라", "": "초장",
"감자": "고구마", "소금": "설탕", "간장": "고추장", "된장": "쌈장",
"남자": "여자", "부모": "자식", "할아버지": "할머니", "": "동생",
"선생님": "학생", "의사": "환자", "경찰": "도둑", "가수": "마이크",
"화가": "그림", "요리사": "주방", "어부": "낚시대", "군인": "",
"": "왕비", "왕자": "공주", "신랑": "신부", "주인": "손님",
"한국": "서울", "미국": "워싱턴", "프랑스": "파리", "영국": "런던",
"일본": "도쿄", "중국": "베이징", "학교": "교실", "병원": "주사기",
"은행": "", "우체국": "편지", "극장": "영화", "도서관": "",
"공항": "비행기", "항구": "", "": "기차", "정류장": "버스",
"시계": "시간", "달력": "날짜", "거울": "얼굴", "": "머리카락",
"가방": "", "모자": "머리", "안경": "", "마스크": "",
}; };
// (15) // [🔥 ] 21 (6x6 )
static final List<CardFlipDifficulty> allDifficulties = [ static final List<CardFlipDifficulty> allDifficulties = [
// Phase 1: ( ) // --- Phase 1: (6~8) ---
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: 입문 (숫자 6장)', contextId: 'FLIP_L1_2x3_NUM', rows: 3, cols: 2, timeLimitSeconds: 30, contentType: CardContentType.number),
const CardFlipDifficulty(levelIndex: 2, name: 'Lv. 2: 초급 (아이콘 12)', contextId: 'FLIP_L2_ICON', rows: 4, cols: 3, timeLimitSeconds: 30, contentType: CardContentType.icon), const CardFlipDifficulty(levelIndex: 2, name: 'Lv. 2: 입문 (이모지 6장)', contextId: 'FLIP_L2_2x3_EMOJI', rows: 3, cols: 2, timeLimitSeconds: 25, contentType: CardContentType.emoji),
const CardFlipDifficulty(levelIndex: 3, name: 'Lv. 3: 기초 (숫자 16)', contextId: 'FLIP_L3_NUM', rows: 4, cols: 4, timeLimitSeconds: 50, contentType: CardContentType.number), const CardFlipDifficulty(levelIndex: 3, name: 'Lv. 3: 기초 (숫자 8장)', contextId: 'FLIP_L3_2x4_NUM', rows: 4, cols: 2, timeLimitSeconds: 40, contentType: CardContentType.number),
const CardFlipDifficulty(levelIndex: 4, name: 'Lv. 4: 기초 (이모지 8장)', contextId: 'FLIP_L4_2x4_EMOJI', rows: 4, cols: 2, timeLimitSeconds: 35, contentType: CardContentType.emoji),
// Phase 2: / ( + ) // --- Phase 2: (12) ---
const CardFlipDifficulty(levelIndex: 4, name: 'Lv. 4: 연산 (덧셈/뺄셈)', contextId: 'FLIP_L4_CALC', rows: 4, cols: 4, timeLimitSeconds: 60, contentType: CardContentType.calculation), const CardFlipDifficulty(levelIndex: 5, name: 'Lv. 5: 초급 (이모지 12장)', contextId: 'FLIP_L5_3x4_EMOJI', rows: 4, cols: 3, timeLimitSeconds: 50, contentType: CardContentType.emoji),
const CardFlipDifficulty(levelIndex: 5, name: 'Lv. 5: 연상 (짝꿍 단어)', contextId: 'FLIP_L5_PAIR', rows: 4, cols: 4, timeLimitSeconds: 60, contentType: CardContentType.pairWord), const CardFlipDifficulty(levelIndex: 6, name: 'Lv. 6: 초급 (아이콘 12장)', contextId: 'FLIP_L6_3x4_ICON', rows: 4, cols: 3, timeLimitSeconds: 45, contentType: CardContentType.icon),
const CardFlipDifficulty(levelIndex: 6, name: 'Lv. 6: 도전 (이모지 20)', contextId: 'FLIP_L6_EMOJI_20', rows: 5, cols: 4, timeLimitSeconds: 70, contentType: CardContentType.emoji), const CardFlipDifficulty(levelIndex: 7, name: 'Lv. 7: 초급 (연산 12장)', contextId: 'FLIP_L7_3x4_CALC', rows: 4, cols: 3, timeLimitSeconds: 60, contentType: CardContentType.calculation),
const CardFlipDifficulty(levelIndex: 8, name: 'Lv. 8: 초급 (단어 12장)', contextId: 'FLIP_L8_3x4_PAIR', rows: 4, cols: 3, timeLimitSeconds: 60, contentType: CardContentType.pairWord),
// Phase 3: (/) // --- Phase 3: (16) ---
const CardFlipDifficulty(levelIndex: 7, name: 'Lv. 7: 상급 (연산 20)', contextId: 'FLIP_L7_CALC_20', rows: 5, cols: 4, timeLimitSeconds: 90, contentType: CardContentType.calculation), const CardFlipDifficulty(levelIndex: 9, name: 'Lv. 9: 중급 (숫자 16장)', contextId: 'FLIP_L9_4x4_NUM', rows: 4, cols: 4, timeLimitSeconds: 70, contentType: CardContentType.number),
const CardFlipDifficulty(levelIndex: 8, name: 'Lv. 8: 전문가 (연상 20)', contextId: 'FLIP_L8_PAIR_20', rows: 5, cols: 4, timeLimitSeconds: 90, contentType: CardContentType.pairWord), const CardFlipDifficulty(levelIndex: 10, name: 'Lv. 10: 중급 (아이콘 16장)', contextId: 'FLIP_L10_4x4_ICON', rows: 4, cols: 4, timeLimitSeconds: 65, contentType: CardContentType.icon),
const CardFlipDifficulty(levelIndex: 9, name: 'Lv. 9: 엘리트 (아이콘 24)', contextId: 'FLIP_L9_ICON_24', rows: 6, cols: 4, timeLimitSeconds: 100, contentType: CardContentType.icon), const CardFlipDifficulty(levelIndex: 11, name: 'Lv. 11: 중급 (연산 16장)', contextId: 'FLIP_L11_4x4_CALC', rows: 4, cols: 4, timeLimitSeconds: 90, contentType: CardContentType.calculation),
const CardFlipDifficulty(levelIndex: 12, name: 'Lv. 12: 중급 (단어 16장)', contextId: 'FLIP_L12_4x4_PAIR', rows: 4, cols: 4, timeLimitSeconds: 90, contentType: CardContentType.pairWord),
// Phase 4: ( ) // --- Phase 4: (20~24) ---
const CardFlipDifficulty(levelIndex: 10, name: 'Lv. 10: 마스터 (24장)', contextId: 'FLIP_L10_6x4', rows: 6, cols: 4, timeLimitSeconds: 100, contentType: CardContentType.emoji), const CardFlipDifficulty(levelIndex: 13, name: 'Lv. 13: 상급 (이모지 20장)', contextId: 'FLIP_L13_5x4_EMOJI', rows: 5, cols: 4, timeLimitSeconds: 100, contentType: CardContentType.emoji),
const CardFlipDifficulty(levelIndex: 11, name: 'Lv. 11: 그랜드마스터', contextId: 'FLIP_L11_6x4_CALC', rows: 6, cols: 4, timeLimitSeconds: 110, contentType: CardContentType.calculation), const CardFlipDifficulty(levelIndex: 14, name: 'Lv. 14: 상급 (연산 20장)', contextId: 'FLIP_L14_5x4_CALC', rows: 5, cols: 4, timeLimitSeconds: 120, contentType: CardContentType.calculation),
const CardFlipDifficulty(levelIndex: 12, name: 'Lv. 12: 레전드', contextId: 'FLIP_L12_6x4_PAIR', rows: 6, cols: 4, timeLimitSeconds: 110, contentType: CardContentType.pairWord), const CardFlipDifficulty(levelIndex: 15, name: 'Lv. 15: 전문가 (아이콘 24장)', contextId: 'FLIP_L15_6x4_ICON', rows: 6, cols: 4, timeLimitSeconds: 120, contentType: CardContentType.icon),
const CardFlipDifficulty(levelIndex: 16, name: 'Lv. 16: 전문가 (단어 24장)', contextId: 'FLIP_L16_6x4_PAIR', rows: 6, cols: 4, timeLimitSeconds: 150, contentType: CardContentType.pairWord),
// Phase 5: // --- Phase 5: (30) ---
const CardFlipDifficulty(levelIndex: 13, name: 'Lv. 13: 갓모드 (30장)', contextId: 'FLIP_L13_6x5', rows: 6, cols: 5, timeLimitSeconds: 130, contentType: CardContentType.emoji), const CardFlipDifficulty(levelIndex: 17, name: 'Lv. 17: 마스터 (숫자 30장)', contextId: 'FLIP_L17_6x5_NUM', rows: 6, cols: 5, timeLimitSeconds: 150, contentType: CardContentType.number),
const CardFlipDifficulty(levelIndex: 14, name: 'Lv. 14: 타임어택 (연산)', contextId: 'FLIP_L14_6x5_CALC', rows: 6, cols: 5, timeLimitSeconds: 120, contentType: CardContentType.calculation), const CardFlipDifficulty(levelIndex: 18, name: 'Lv. 18: 마스터 (연산 30장)', contextId: 'FLIP_L18_6x5_CALC', rows: 6, cols: 5, timeLimitSeconds: 180, 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: 19, name: 'Lv. 19: 레전드 (단어 30장)', contextId: 'FLIP_L19_6x5_PAIR', rows: 6, cols: 5, timeLimitSeconds: 180, contentType: CardContentType.pairWord),
const CardFlipDifficulty(levelIndex: 20, name: 'Lv. 20: 갓모드 (이모지 30장)', contextId: 'FLIP_L20_6x5_EMOJI', rows: 6, cols: 5, timeLimitSeconds: 120, contentType: CardContentType.emoji),
const CardFlipDifficulty(levelIndex: 16, name: 'Lv. 15: 헬 (연상)', contextId: 'FLIP_L16_6x6_PAIR', rows: 6, cols: 6, timeLimitSeconds: 120, contentType: CardContentType.pairWord), // --- [🔥 ] Phase 6: (6x6 = 36) ---
const CardFlipDifficulty(
levelIndex: 21,
name: 'Lv. 21: 헬모드 (36장)',
contextId: 'FLIP_L21_6x6_HELL',
rows: 6,
cols: 6,
timeLimitSeconds: 240,
contentType: CardContentType.pairWord
),
]; ];
static CardFlipDifficulty getLevel(int levelIndex) { static CardFlipDifficulty getLevel(int levelIndex) {