import 'dart:math'; import 'package:flutter/material.dart'; import 'package:aesthetica_wallpaper/models/drag_puzzle_game.dart'; import 'package:aesthetica_wallpaper/screens/puzzle/drag_puzzle_screen.dart'; /// 拖拽式拼图菜单页面 class DragPuzzleMenuScreen extends StatefulWidget { const DragPuzzleMenuScreen({super.key}); @override State createState() => _DragPuzzleMenuScreenState(); } class _DragPuzzleMenuScreenState extends State { DragPuzzleDifficulty _selectedDifficulty = DragPuzzleDifficulty.beginner; String? _selectedImagePath; List _availableImages = []; final Random _random = Random(); // 所有可用的图片列表(按类别组织) static const Map> _allImages = { 'nature': [ 'assets/images/nature/nature1.png', 'assets/images/nature/nature2.png', 'assets/images/nature/nature3.png', 'assets/images/nature/nature4.png', 'assets/images/nature/nature5.png', 'assets/images/nature/nature6.png', 'assets/images/nature/nature7.png', 'assets/images/nature/nature8.png', 'assets/images/nature/nature9.png', ], 'abstract': [ 'assets/images/abstract/abstract1.png', 'assets/images/abstract/abstract2.png', 'assets/images/abstract/abstract3.png', 'assets/images/abstract/abstract4.png', 'assets/images/abstract/abstract5.png', 'assets/images/abstract/abstract6.png', 'assets/images/abstract/abstract7.png', 'assets/images/abstract/abstract8.png', 'assets/images/abstract/abstract9.png', 'assets/images/abstract/abstract10.png', 'assets/images/abstract/abstract11.png', 'assets/images/abstract/abstract12.png', 'assets/images/abstract/abstract13.png', 'assets/images/abstract/abstract14.png', 'assets/images/abstract/abstract15.png', ], 'architecture': [ 'assets/images/architecture/architecture1.png', 'assets/images/architecture/architecture2.png', 'assets/images/architecture/architecture3.png', 'assets/images/architecture/architecture4.png', 'assets/images/architecture/architecture5.png', 'assets/images/architecture/architecture6.png', 'assets/images/architecture/architecture7.png', 'assets/images/architecture/architecture8.png', 'assets/images/architecture/architecture9.png', 'assets/images/architecture/architecture10.png', ], 'animals': [ 'assets/images/animals/animals1.png', 'assets/images/animals/animals2.png', 'assets/images/animals/animals3.png', 'assets/images/animals/animals4.png', 'assets/images/animals/animals5.png', 'assets/images/animals/animals6.png', 'assets/images/animals/animals7.png', ], 'food': [ 'assets/images/food/food1.png', 'assets/images/food/food2.png', 'assets/images/food/food3.png', 'assets/images/food/food4.png', 'assets/images/food/food5.png', 'assets/images/food/food6.png', 'assets/images/food/food7.png', 'assets/images/food/food8.png', 'assets/images/food/food9.png', 'assets/images/food/food10.png', 'assets/images/food/food11.png', 'assets/images/food/food12.png', 'assets/images/food/food13.png', ], 'travel': [ 'assets/images/travel/travel1.png', 'assets/images/travel/travel2.png', 'assets/images/travel/travel3.png', 'assets/images/travel/travel4.png', 'assets/images/travel/travel5.png', 'assets/images/travel/travel6.png', 'assets/images/travel/travel7.png', 'assets/images/travel/travel8.png', 'assets/images/travel/travel9.png', ], }; @override void initState() { super.initState(); _loadAvailableImages(); } void _loadAvailableImages() { // 从所有类别中随机选择3张图片 final allImagesList = []; _allImages.forEach((category, images) { allImagesList.addAll(images); }); // 打乱列表并选择前3张 allImagesList.shuffle(_random); _availableImages = allImagesList.take(3).toList(); if (_availableImages.isNotEmpty) { _selectedImagePath = _availableImages.first; } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Colors.purple.shade400, Colors.blue.shade400], ), ), child: SafeArea( child: Column( children: [ // 顶部栏 _buildAppBar(), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 标题 _buildTitle(), const SizedBox(height: 40), // 游戏说明 _buildGameDescription(), const SizedBox(height: 30), // 难度选择 _buildDifficultySelection(), const SizedBox(height: 30), // 图片选择 _buildImageSelection(), const SizedBox(height: 40), // 开始游戏按钮 _buildStartButton(), ], ), ), ), ], ), ), ), ); } Widget _buildAppBar() { return Padding( padding: const EdgeInsets.all(16), child: Row( children: [ IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () => Navigator.pop(context), ), const Spacer(), IconButton( icon: const Icon(Icons.help_outline, color: Colors.white), onPressed: () => _showHelpDialog(), ), ], ), ); } Widget _buildTitle() { return Column( children: [ const Icon(Icons.view_module, size: 80, color: Colors.white), const SizedBox(height: 16), const Text( 'Drag Puzzle', style: TextStyle( fontSize: 36, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 8), Text( 'Drag pieces to the correct position', style: TextStyle( fontSize: 16, color: Colors.white.withValues(alpha: 0.9), ), ), ], ); } Widget _buildGameDescription() { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row( children: [ Icon(Icons.info_outline, color: Colors.white), SizedBox(width: 8), Text( 'Game Rules', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), const SizedBox(height: 12), _buildRuleItem('1. Image will be split into puzzle pieces'), _buildRuleItem('2. Pieces are randomly arranged at the bottom'), _buildRuleItem('3. Drag pieces to the correct position above'), _buildRuleItem('4. Correctly placed pieces show green checkmark'), _buildRuleItem('5. Complete all pieces to win'), ], ), ); } Widget _buildRuleItem(String text) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( children: [ const SizedBox(width: 16), const Icon(Icons.check_circle_outline, color: Colors.white, size: 16), const SizedBox(width: 8), Expanded( child: Text( text, style: TextStyle( color: Colors.white.withValues(alpha: 0.9), fontSize: 14, ), ), ), ], ), ); } Widget _buildDifficultySelection() { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Select Difficulty', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 16), Wrap( spacing: 8, runSpacing: 8, children: DragPuzzleDifficulty.values.map((difficulty) { return _buildDifficultyChip(difficulty); }).toList(), ), ], ), ); } Widget _buildDifficultyChip(DragPuzzleDifficulty difficulty) { final isSelected = _selectedDifficulty == difficulty; return InkWell( onTap: () { setState(() { _selectedDifficulty = difficulty; }); }, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), decoration: BoxDecoration( color: isSelected ? Colors.white : Colors.white.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( difficulty.label, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: isSelected ? Colors.purple : Colors.white, ), ), const SizedBox(height: 2), Text( difficulty.description, style: TextStyle( fontSize: 11, color: isSelected ? Colors.purple.withValues(alpha: 0.7) : Colors.white.withValues(alpha: 0.7), ), ), const SizedBox(height: 2), Text( '${difficulty.totalPieces} pieces', style: TextStyle( fontSize: 10, color: isSelected ? Colors.purple.withValues(alpha: 0.6) : Colors.white.withValues(alpha: 0.6), ), ), ], ), ), ); } Widget _buildImageSelection() { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Select Image', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), TextButton.icon( onPressed: () { setState(() { _loadAvailableImages(); }); }, icon: const Icon(Icons.refresh, color: Colors.white, size: 18), label: const Text( 'Refresh', style: TextStyle(color: Colors.white, fontSize: 14), ), style: TextButton.styleFrom( backgroundColor: Colors.white.withValues(alpha: 0.2), padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), ), ), ], ), const SizedBox(height: 16), SizedBox( height: 100, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: _availableImages.length, itemBuilder: (context, index) { final imagePath = _availableImages[index]; final isSelected = _selectedImagePath == imagePath; return GestureDetector( onTap: () { setState(() { _selectedImagePath = imagePath; }); }, child: Container( width: 80, margin: const EdgeInsets.only(right: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? Colors.white : Colors.transparent, width: 3, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Image.asset(imagePath, fit: BoxFit.cover), ), ), ); }, ), ), ], ), ); } Widget _buildStartButton() { return ElevatedButton( onPressed: _selectedImagePath != null ? _startGame : null, style: ElevatedButton.styleFrom( backgroundColor: Colors.white, foregroundColor: Colors.purple, padding: const EdgeInsets.symmetric(vertical: 20), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), elevation: 8, ), child: const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.play_arrow, size: 32), SizedBox(width: 8), Text( 'Start Puzzle', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), ], ), ); } void _startGame() { if (_selectedImagePath == null) return; Navigator.push( context, MaterialPageRoute( builder: (context) => DragPuzzleScreen( imagePath: _selectedImagePath!, difficulty: _selectedDifficulty, ), ), ); } void _showHelpDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Game Help'), content: const Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('🎯 Goal: Drag all pieces to correct positions'), SizedBox(height: 8), Text('👆 Control: Long press and drag pieces to target'), SizedBox(height: 8), Text('✅ Hint: Correct pieces show green checkmark'), SizedBox(height: 8), Text('🔄 Reset: Tap placed pieces to move back'), SizedBox(height: 8), Text('⭐ Rating: Based on time and moves'), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Got it'), ), ], ), ); } }