163 lines
4.1 KiB
Dart
163 lines
4.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:aesthetica_wallpaper/models/puzzle_game_interface.dart';
|
|
|
|
/// 拖拽式拼图块数据模型
|
|
class DragPuzzlePiece {
|
|
final int id; // 唯一标识
|
|
final int correctRow; // 正确的行位置
|
|
final int correctCol; // 正确的列位置
|
|
final ImageProvider image; // 图片块
|
|
bool isPlaced; // 是否已放置到正确位置
|
|
int? currentRow; // 当前行位置(如果已放置)
|
|
int? currentCol; // 当前列位置(如果已放置)
|
|
|
|
DragPuzzlePiece({
|
|
required this.id,
|
|
required this.correctRow,
|
|
required this.correctCol,
|
|
required this.image,
|
|
this.isPlaced = false,
|
|
this.currentRow,
|
|
this.currentCol,
|
|
});
|
|
|
|
bool get isCorrectlyPlaced =>
|
|
isPlaced && currentRow == correctRow && currentCol == correctCol;
|
|
|
|
DragPuzzlePiece copyWith({
|
|
int? id,
|
|
int? correctRow,
|
|
int? correctCol,
|
|
ImageProvider? image,
|
|
bool? isPlaced,
|
|
int? currentRow,
|
|
int? currentCol,
|
|
}) {
|
|
return DragPuzzlePiece(
|
|
id: id ?? this.id,
|
|
correctRow: correctRow ?? this.correctRow,
|
|
correctCol: correctCol ?? this.correctCol,
|
|
image: image ?? this.image,
|
|
isPlaced: isPlaced ?? this.isPlaced,
|
|
currentRow: currentRow ?? this.currentRow,
|
|
currentCol: currentCol ?? this.currentCol,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 拖拽式拼图游戏状态
|
|
class DragPuzzleGame implements IPuzzleGame {
|
|
final List<DragPuzzlePiece> pieces; // 所有拼图块
|
|
final int gridRows; // 网格行数
|
|
final int gridCols; // 网格列数
|
|
final Duration elapsedTime; // 已用时间
|
|
final int moves; // 移动次数
|
|
final bool isComplete; // 是否完成
|
|
final String imagePath; // 原图路径
|
|
|
|
DragPuzzleGame({
|
|
required this.pieces,
|
|
required this.gridRows,
|
|
required this.gridCols,
|
|
this.elapsedTime = Duration.zero,
|
|
this.moves = 0,
|
|
this.isComplete = false,
|
|
required this.imagePath,
|
|
});
|
|
|
|
/// 获取未放置的拼图块
|
|
List<DragPuzzlePiece> get unplacedPieces =>
|
|
pieces.where((piece) => !piece.isPlaced).toList();
|
|
|
|
/// 获取已放置的拼图块
|
|
List<DragPuzzlePiece> get placedPieces =>
|
|
pieces.where((piece) => piece.isPlaced).toList();
|
|
|
|
/// 检查游戏是否完成
|
|
bool checkComplete() {
|
|
return pieces.every((piece) => piece.isCorrectlyPlaced);
|
|
}
|
|
|
|
/// 获取指定位置的拼图块
|
|
DragPuzzlePiece? getPieceAt(int row, int col) {
|
|
try {
|
|
return pieces.firstWhere(
|
|
(piece) =>
|
|
piece.isPlaced &&
|
|
piece.currentRow == row &&
|
|
piece.currentCol == col,
|
|
);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@override
|
|
String get difficultyLabel {
|
|
return '${gridRows}x$gridCols';
|
|
}
|
|
|
|
/// 获取星级评分
|
|
@override
|
|
int getStarRating() {
|
|
if (!isComplete) return 0;
|
|
|
|
final totalPieces = gridRows * gridCols;
|
|
final optimalMoves = totalPieces; // 理想情况下每个块只移动一次
|
|
final optimalTime = Duration(minutes: totalPieces ~/ 4); // 理想时间
|
|
|
|
int stars = 1;
|
|
if (moves <= optimalMoves && elapsedTime <= optimalTime) {
|
|
stars = 3;
|
|
} else if (moves <= optimalMoves * 1.5 ||
|
|
elapsedTime <= optimalTime * 1.5) {
|
|
stars = 2;
|
|
}
|
|
|
|
return stars;
|
|
}
|
|
|
|
DragPuzzleGame copyWith({
|
|
List<DragPuzzlePiece>? pieces,
|
|
int? gridRows,
|
|
int? gridCols,
|
|
Duration? elapsedTime,
|
|
int? moves,
|
|
bool? isComplete,
|
|
String? imagePath,
|
|
}) {
|
|
return DragPuzzleGame(
|
|
pieces: pieces ?? this.pieces,
|
|
gridRows: gridRows ?? this.gridRows,
|
|
gridCols: gridCols ?? this.gridCols,
|
|
elapsedTime: elapsedTime ?? this.elapsedTime,
|
|
moves: moves ?? this.moves,
|
|
isComplete: isComplete ?? this.isComplete,
|
|
imagePath: imagePath ?? this.imagePath,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 拖拽式拼图难度
|
|
enum DragPuzzleDifficulty {
|
|
beginner(2, 2, 'Beginner', '2x2'),
|
|
easy(3, 2, 'Easy', '3x2'),
|
|
medium(4, 3, 'Medium', '4x3'),
|
|
hard(5, 4, 'Hard', '5x4'),
|
|
expert(6, 5, 'Expert', '6x5');
|
|
|
|
final int rows;
|
|
final int cols;
|
|
final String label;
|
|
final String description;
|
|
|
|
const DragPuzzleDifficulty(
|
|
this.rows,
|
|
this.cols,
|
|
this.label,
|
|
this.description,
|
|
);
|
|
|
|
int get totalPieces => rows * cols;
|
|
}
|