import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:aesthetica_wallpaper/models/puzzle_game.dart'; import 'package:aesthetica_wallpaper/providers/simple_puzzle_provider.dart'; import 'package:aesthetica_wallpaper/screens/puzzle/puzzle_complete_screen.dart'; /// 简化版拼图游戏界面(使用颜色块) class SimplePuzzleGameScreen extends StatefulWidget { final GameDifficulty difficulty; final GameMode mode; const SimplePuzzleGameScreen({ super.key, required this.difficulty, required this.mode, }); @override State createState() => _SimplePuzzleGameScreenState(); } class _SimplePuzzleGameScreenState extends State { int? _selectedPieceIndex; late SimplePuzzleProvider _puzzleProvider; @override void initState() { super.initState(); _puzzleProvider = SimplePuzzleProvider(); // 创建游戏 WidgetsBinding.instance.addPostFrameCallback((_) { _puzzleProvider.createSimpleGame( difficulty: widget.difficulty, mode: widget.mode, ); }); } @override void dispose() { _puzzleProvider.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.purple.shade50, Colors.blue.shade50], ), ), child: SafeArea( child: ChangeNotifierProvider.value( value: _puzzleProvider, child: Consumer( builder: (context, provider, child) { final game = provider.currentGame; if (game == null) { return const Center(child: CircularProgressIndicator()); } // 游戏完成后跳转 if (game.isComplete) { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => PuzzleCompleteScreen(game: game), ), ); }); } return Column( children: [ // 顶部信息栏 _buildTopBar(game), // 游戏区域 Expanded( child: Center(child: _buildPuzzleGrid(game, provider)), ), // 底部工具栏 _buildBottomBar(game, provider), ], ); }, ), ), ), ), ); } Widget _buildTopBar(PuzzleGame game) { return Container( padding: const EdgeInsets.all(16), child: Row( children: [ // 返回按钮 IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context), ), const Spacer(), // 难度显示 Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.purple.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Text( '${game.difficulty.description} (测试版)', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.purple, ), ), ), const Spacer(), // 计时器 Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.blue.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Row( children: [ const Icon(Icons.timer, size: 16, color: Colors.blue), const SizedBox(width: 4), Text( _formatDuration(game.elapsedTime), style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.blue, ), ), ], ), ), const SizedBox(width: 8), // 步数 Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.orange.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Row( children: [ const Icon( Icons.directions_walk, size: 16, color: Colors.orange, ), const SizedBox(width: 4), Text( '${game.moves}', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.orange, ), ), ], ), ), ], ), ); } Widget _buildPuzzleGrid(PuzzleGame game, SimplePuzzleProvider provider) { final gridSize = game.gridSize; final screenWidth = MediaQuery.of(context).size.width; final puzzleSize = screenWidth * 0.9; final pieceSize = puzzleSize / gridSize; return Container( width: puzzleSize, height: puzzleSize, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.1), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: GridView.builder( physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: gridSize, ), itemCount: game.pieces.length, itemBuilder: (context, index) { return _buildPuzzlePiece(game, index, provider, pieceSize); }, ), ), ); } Widget _buildPuzzlePiece( PuzzleGame game, int index, SimplePuzzleProvider provider, double size, ) { final piece = game.pieces[index]; final isSelected = _selectedPieceIndex == index; final isCorrect = piece.isCorrect; final isEmpty = game.mode == GameMode.classic && game.emptyPosition == index; return GestureDetector( onTap: () => _onPieceTap(index, game, provider), child: Container( decoration: BoxDecoration( border: Border.all( color: isSelected ? Colors.blue : isCorrect ? Colors.green.withValues(alpha: 0.3) : Colors.grey.withValues(alpha: 0.3), width: isSelected ? 3 : 1, ), color: isEmpty ? Colors.grey.shade200 : null, ), child: isEmpty ? const Center( child: Text( '空', style: TextStyle(fontSize: 20, color: Colors.grey), ), ) : Stack( fit: StackFit.expand, children: [ // 使用简单的颜色块代替图片 Container( color: _getColorForPiece(piece.id), child: Center( child: Text( '${piece.id + 1}', style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ), // 正确位置指示器 if (isCorrect) Positioned( top: 4, right: 4, child: Container( padding: const EdgeInsets.all(2), decoration: const BoxDecoration( color: Colors.green, shape: BoxShape.circle, ), child: const Icon( Icons.check, color: Colors.white, size: 12, ), ), ), ], ), ), ); } Color _getColorForPiece(int id) { final colors = [ Colors.red, Colors.blue, Colors.green, Colors.orange, Colors.purple, Colors.pink, Colors.teal, Colors.amber, Colors.indigo, Colors.cyan, Colors.lime, Colors.brown, Colors.grey, Colors.deepOrange, Colors.lightBlue, Colors.lightGreen, Colors.yellow, Colors.deepPurple, Colors.blueGrey, Colors.redAccent, Colors.greenAccent, Colors.blueAccent, Colors.orangeAccent, Colors.purpleAccent, Colors.pinkAccent, Colors.tealAccent, Colors.amberAccent, Colors.indigoAccent, Colors.cyanAccent, Colors.limeAccent, Colors.black87, Colors.black54, Colors.black45, Colors.black38, Colors.black26, Colors.black12, ]; return colors[id % colors.length]; } void _onPieceTap(int index, PuzzleGame game, SimplePuzzleProvider provider) { if (game.mode == GameMode.classic) { // 滑动模式:直接移动 provider.movePiece(index); } else { // 交换模式:选择两个块 if (_selectedPieceIndex == null) { setState(() { _selectedPieceIndex = index; }); } else { provider.swapPieces(_selectedPieceIndex!, index); setState(() { _selectedPieceIndex = null; }); } } } Widget _buildBottomBar(PuzzleGame game, SimplePuzzleProvider provider) { return Container( padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // 重新开始 _buildToolButton( icon: Icons.refresh, label: '重新开始', color: Colors.orange, onPressed: () => provider.restartGame(), ), // 提示 _buildToolButton( icon: Icons.lightbulb, label: '提示', color: Colors.yellow.shade700, onPressed: () => provider.useHint(), ), // 返回 _buildToolButton( icon: Icons.home, label: '返回', color: Colors.purple, onPressed: () => Navigator.pop(context), ), ], ), ); } Widget _buildToolButton({ required IconData icon, required String label, required Color color, required VoidCallback onPressed, }) { return Column( mainAxisSize: MainAxisSize.min, children: [ Container( decoration: BoxDecoration( color: color.withValues(alpha: 0.2), shape: BoxShape.circle, ), child: IconButton( icon: Icon(icon, color: color), onPressed: onPressed, ), ), const SizedBox(height: 4), Text( label, style: TextStyle(fontSize: 12, color: Colors.grey.shade700), ), ], ); } String _formatDuration(Duration duration) { final minutes = duration.inMinutes.toString().padLeft(2, '0'); final seconds = (duration.inSeconds % 60).toString().padLeft(2, '0'); return '$minutes:$seconds'; } }