import 'dart:math'; import 'package:flutter/material.dart'; class StampData extends ChangeNotifier { final List stamps = []; void push(Stamp stamp) { stamps.add(stamp); notifyListeners(); } void removeLast() { stamps.removeLast(); notifyListeners(); } void activeLast({Color color = Colors.blue}) { stamps.last.color = color; notifyListeners(); } void clear() { stamps.clear(); notifyListeners(); } void animateAt(int index, double radius) { stamps[index].radius = radius; stamps[index].rePath(); notifyListeners(); } GameState checkWin(double length){ bool redWin = _checkWinByColor(length,Colors.red); if(redWin) return GameState.redWin; bool blueWin = _checkWinByColor(length,Colors.blue); if(blueWin) return GameState.blueWin; return GameState.doing; } bool _checkWinByColor(double length,Color color) { List red = stamps .where((element) => element.color == color) .map((e) => e.center) .toList(); List> redPoints = red .map>((e) => Point(e.dx ~/ length, e.dy ~/ length)) .toList(); return _checkWinInline(redPoints, 3); } bool _checkWinInline(List> points, int max) { if (points.length < max) return false; for (int i = 0; i < points.length; i++) { int x = points[i].x; int y = points[i].y; if (_check(x, y, points, CheckModel.horizontal,max)) { return true; } else if (_check(x, y, points, CheckModel.vertical,max)) { return true; } else if (_check(x, y, points, CheckModel.leftDiagonal,max)) { return true; } else if (_check(x, y, points, CheckModel.rightDiagonal,max)) { return true; } } return false; } bool _check(int x, int y, List points, CheckModel checkModel,int max) { int count = 1; Point checkPoint; for (int i = 1; i < max; i++) { switch (checkModel) { case CheckModel.horizontal: checkPoint = Point(x - i, y); break; case CheckModel.vertical: checkPoint = Point(x, y - i); break; case CheckModel.leftDiagonal: checkPoint = Point(x - i, y + i);break; case CheckModel.rightDiagonal: checkPoint = Point(x + i, y + i); break; } if (points.contains(checkPoint)) {count++;} else {break;} } if (count == max) return true; return false; } } enum CheckModel { horizontal, // 横向判断 vertical, // 竖向判断 leftDiagonal, // 左斜判断 rightDiagonal // 右斜判断 } enum GameState{ doing, // 进行中 redWin, // 红胜 blueWin // 蓝胜 } class Stamp { Color color; Offset center; double radius; Stamp({this.color = Colors.blue, this.center = Offset.zero, this.radius = 20}); Path? _path; Path get path { if (_path == null) { _path = Path(); double r = radius; double rad = 30 / 180 * pi; _path!..moveTo(center.dx, center.dy); _path!.relativeMoveTo(r * cos(rad), -r * sin(rad)); _path!.relativeLineTo(-2 * r * cos(rad), 0); _path!.relativeLineTo(r * cos(rad), r + r * sin(rad)); _path!.relativeLineTo(r * cos(rad), -(r + r * sin(rad))); _path!..moveTo(center.dx, center.dy); _path!.relativeMoveTo(0, -r); _path!.relativeLineTo(-r * cos(rad), r + r * sin(rad)); _path!.relativeLineTo(2 * r * cos(rad), 0); _path!.relativeLineTo(-r * cos(rad), -(r + r * sin(rad))); return _path!; } else { return _path!; } } set path(Path path) { _path = path; } void rePath() { _path = null; _path = path; } }