169 lines
4.0 KiB
Dart
169 lines
4.0 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:aesthetica_wallpaper/models/puzzle_game_interface.dart';
|
||
|
||
/// 拼图块数据模型
|
||
class PuzzlePiece {
|
||
final int id; // 唯一标识
|
||
final int correctPosition; // 正确位置
|
||
int currentPosition; // 当前位置
|
||
final ImageProvider image; // 图片块
|
||
|
||
PuzzlePiece({
|
||
required this.id,
|
||
required this.correctPosition,
|
||
required this.currentPosition,
|
||
required this.image,
|
||
});
|
||
|
||
bool get isCorrect => currentPosition == correctPosition;
|
||
|
||
PuzzlePiece copyWith({
|
||
int? id,
|
||
int? correctPosition,
|
||
int? currentPosition,
|
||
ImageProvider? image,
|
||
}) {
|
||
return PuzzlePiece(
|
||
id: id ?? this.id,
|
||
correctPosition: correctPosition ?? this.correctPosition,
|
||
currentPosition: currentPosition ?? this.currentPosition,
|
||
image: image ?? this.image,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 游戏模式
|
||
enum GameMode {
|
||
classic, // 经典模式(滑动)
|
||
challenge, // 挑战模式(限时)
|
||
casual, // 休闲模式(无限制)
|
||
}
|
||
|
||
/// 游戏难度
|
||
enum GameDifficulty {
|
||
easy(3, '简单', '3x3'),
|
||
medium(4, '中等', '4x4'),
|
||
hard(5, '困难', '5x5'),
|
||
expert(6, '专家', '6x6');
|
||
|
||
final int gridSize;
|
||
final String label;
|
||
final String description;
|
||
|
||
const GameDifficulty(this.gridSize, this.label, this.description);
|
||
}
|
||
|
||
/// 拼图游戏状态
|
||
class PuzzleGame implements IPuzzleGame {
|
||
List<PuzzlePiece> pieces;
|
||
int moves;
|
||
Duration elapsedTime;
|
||
GameDifficulty difficulty;
|
||
GameMode mode;
|
||
bool isComplete;
|
||
int? emptyPosition; // 空格位置(仅滑动模式)
|
||
|
||
PuzzleGame({
|
||
required this.pieces,
|
||
this.moves = 0,
|
||
this.elapsedTime = Duration.zero,
|
||
required this.difficulty,
|
||
this.mode = GameMode.classic,
|
||
this.isComplete = false,
|
||
this.emptyPosition,
|
||
});
|
||
|
||
int get gridSize => difficulty.gridSize;
|
||
int get totalPieces => gridSize * gridSize;
|
||
|
||
@override
|
||
String get difficultyLabel => difficulty.label;
|
||
|
||
/// 检查游戏是否完成
|
||
bool checkComplete() {
|
||
return pieces.every((piece) => piece.isCorrect);
|
||
}
|
||
|
||
/// 获取星级评分(1-3星)
|
||
@override
|
||
int getStarRating() {
|
||
if (!isComplete) return 0;
|
||
|
||
final optimalMoves = totalPieces * 2; // 理想步数
|
||
final optimalTime = Duration(minutes: difficulty.gridSize); // 理想时间
|
||
|
||
int stars = 1;
|
||
if (moves <= optimalMoves && elapsedTime <= optimalTime) {
|
||
stars = 3;
|
||
} else if (moves <= optimalMoves * 1.5 ||
|
||
elapsedTime <= optimalTime * 1.5) {
|
||
stars = 2;
|
||
}
|
||
|
||
return stars;
|
||
}
|
||
|
||
PuzzleGame copyWith({
|
||
List<PuzzlePiece>? pieces,
|
||
int? moves,
|
||
Duration? elapsedTime,
|
||
GameDifficulty? difficulty,
|
||
GameMode? mode,
|
||
bool? isComplete,
|
||
int? emptyPosition,
|
||
}) {
|
||
return PuzzleGame(
|
||
pieces: pieces ?? this.pieces,
|
||
moves: moves ?? this.moves,
|
||
elapsedTime: elapsedTime ?? this.elapsedTime,
|
||
difficulty: difficulty ?? this.difficulty,
|
||
mode: mode ?? this.mode,
|
||
isComplete: isComplete ?? this.isComplete,
|
||
emptyPosition: emptyPosition ?? this.emptyPosition,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 游戏记录
|
||
class GameRecord {
|
||
final String imageId;
|
||
final GameDifficulty difficulty;
|
||
final Duration time;
|
||
final int moves;
|
||
final int stars;
|
||
final DateTime completedAt;
|
||
|
||
GameRecord({
|
||
required this.imageId,
|
||
required this.difficulty,
|
||
required this.time,
|
||
required this.moves,
|
||
required this.stars,
|
||
required this.completedAt,
|
||
});
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'imageId': imageId,
|
||
'difficulty': difficulty.name,
|
||
'time': time.inSeconds,
|
||
'moves': moves,
|
||
'stars': stars,
|
||
'completedAt': completedAt.toIso8601String(),
|
||
};
|
||
}
|
||
|
||
factory GameRecord.fromJson(Map<String, dynamic> json) {
|
||
return GameRecord(
|
||
imageId: json['imageId'],
|
||
difficulty: GameDifficulty.values.firstWhere(
|
||
(d) => d.name == json['difficulty'],
|
||
),
|
||
time: Duration(seconds: json['time']),
|
||
moves: json['moves'],
|
||
stars: json['stars'],
|
||
completedAt: DateTime.parse(json['completedAt']),
|
||
);
|
||
}
|
||
}
|