flutter_sudoku/lib/screens/home_screen.dart
2025-11-10 18:02:01 +09:00

175 lines
7.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:sudoku_app/models/sudoku_game_dto.dart';
import 'package:sudoku_app/models/sudoku_theme.dart';
import 'package:sudoku_app/screens/game_screen.dart';
import 'package:sudoku_app/screens/ranking_screen.dart';
import 'package:sudoku_app/services/puzzle_service.dart';
import 'package:sudoku_app/services/identity_service.dart'; // 👈 ID 서비스 임포트
import 'package:sudoku_app/widgets/ad_banner_widget.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// 8단계 난이도
double _difficultyLevel = 4.0; // 1.0 ~ 8.0 (기본값 Level 4: 중급 9x9)
final List<String> levelLabels = [
"입문 (4x4)", "초급 (4x4)",
"쉬움 (9x9)", "중급 (9x9)", "어려움 (9x9)",
"전문가 (16x16)", "마스터 (16x16)", "지옥 (16x16)"
];
late String _selectedThemeName;
bool isLoading = false;
final PuzzleService _puzzleService = PuzzleService();
final IdentityService _identityService = IdentityService(); // 👈 ID 서비스 초기화
@override
void initState() {
super.initState();
_selectedThemeName = AppThemes.random; // 기본 테마 '랜덤'
}
Future<void> _startGame() async {
setState(() { isLoading = true; });
try {
// 1. 난이도 값(String) 전달
final String difficulty = _difficultyLevel.round().toString();
// 2. 서버에서 게임 데이터 가져오기
final SudokuGameDto gameData = await _puzzleService.startGame(difficulty);
// 3. 로컬에서 앱-고유 ID와 저장된 이름 가져오기
final String userId = await _identityService.getOrCreateUserId();
final String? userName = await _identityService.getSavedUserName();
if (mounted) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GameScreen(
gameData: gameData,
themeName: _selectedThemeName,
userId: userId, // 👈 ID 전달
userName: userName, // 👈 이름 전달
),
),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('게임 로딩 실패: $e')),
);
}
} finally {
if (mounted) {
setState(() { isLoading = false; });
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('스도쿠 게임')),
body: LayoutBuilder( // 비율 기반 레이아웃
builder: (context, constraints) {
// 너비/높이 비율 변수 (0.6 = 너비가 높이의 60%를 넘지 않도록 함)
const double maxContentRatio = 0.6;
final double constrainedWidth = constraints.maxHeight * maxContentRatio;
return Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: constrainedWidth),
child: Column(
children: [
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 1. 난이도 선택 (8단계)
const Text("난이도", style: TextStyle(fontSize: 18)),
Text(
levelLabels[_difficultyLevel.round() - 1],
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.blue),
),
Slider(
value: _difficultyLevel,
min: 1.0, max: 8.0, divisions: 7, // 8단계
label: levelLabels[_difficultyLevel.round() - 1],
onChanged: (newValue) => setState(() { _difficultyLevel = newValue; }),
),
const SizedBox(height: 20),
// 2. 테마 선택 (String 기반)
const Text("테마", style: TextStyle(fontSize: 18)),
DropdownButton<String>(
value: _selectedThemeName,
items: AppThemes.selectableThemeNames.map((themeName) {
return DropdownMenuItem<String>(
value: themeName,
child: Text(themeName, style: const TextStyle(fontSize: 20)),
);
}).toList(),
onChanged: (themeName) {
if (themeName != null) {
setState(() { _selectedThemeName = themeName; });
}
},
),
const SizedBox(height: 30),
if (isLoading)
const CircularProgressIndicator()
else
ElevatedButton(
onPressed: _startGame,
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 15)),
child: const Text('게임 시작', style: TextStyle(fontSize: 18)),
),
const SizedBox(height: 10),
// "랭킹 보기" 버튼
TextButton(
onPressed: () {
// 현재 슬라이더의 난이도 이름(String)을 가져옴
final String currentDifficultyName = levelLabels[_difficultyLevel.round() - 1];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RankingScreen(
initialDifficultyName: currentDifficultyName,
),
),
);
},
child: const Text('랭킹 보기'),
),
],
),
),
),
),
const AdBannerWidget(),
],
),
),
);
},
),
);
}
}