import 'dart:math'; import 'board.dart'; import 'coordinate.dart'; import 'match_page.dart'; abstract class Cpu { final Color color; final Random _random = Random(DateTime.now().millisecond); Cpu(this.color); Color get otherPlayer => color == Color.red ? Color.yellow : Color.red; Future<int> chooseCol(Board board); } class DumbCpu extends Cpu { DumbCpu(super.player); @override Color get otherPlayer => color == Color.red ? Color.yellow : Color.red; @override Future<int> chooseCol(Board board) async { await Future.delayed(Duration(seconds: _random.nextInt(2))); int col = _random.nextInt(7); return col; } @override String toString() => 'DUMB CPU'; } class HarderCpu extends Cpu { HarderCpu(super.player); @override Future<int> chooseCol(Board board) async { final List<double?> scores = List.filled(7, 0.0); await Future.delayed(Duration(seconds: 1 + _random.nextInt(2))); return _compute(board, 0, 1, scores); } int _compute(Board board, int step, int deepness, List<double?> scores) { for (var i = 0; i < 7; ++i) { final boardCopy = board.clone(); final target = boardCopy.getColumnTarget(i); if (target == -1) { scores[i] = null; continue; } final coordinate = Coordinate(i, target); boardCopy.setBox(coordinate, color); if (boardCopy.checkWinner(coordinate, color)) { scores[i] = (scores[i] ?? 0) + deepness / (step + 1); continue; } for (var j = 0; j < 7; ++j) { final target = boardCopy.getColumnTarget(j); if (target == -1) { continue; } final coordinate = Coordinate(j, target); boardCopy.setBox(coordinate, otherPlayer); if (boardCopy.checkWinner(coordinate, otherPlayer)) { scores[i] = (scores[i] ?? 0) - deepness / (step + 1); continue; } if (step + 1 < deepness) { _compute(board, step + 1, deepness, scores); } } } return _getBestScoreIndex(scores); } int _getBestScoreIndex(List<double?> scores) { int bestScoreIndex = scores.indexWhere((s) => s != null); scores.asMap().forEach((index, score) { if (score != null && (score > (scores[bestScoreIndex] ?? 0) || (score == scores[bestScoreIndex] && _random.nextBool()))) { bestScoreIndex = index; } }); return bestScoreIndex; } @override String toString() => 'HARDER CPU'; } class HardestCpu extends HarderCpu { HardestCpu(super.player); @override Future<int> chooseCol(Board board) async { final List<double?> scores = List.filled(7, 0); await Future.delayed(Duration(seconds: 2 + _random.nextInt(2))); return _compute(board, 0, 4, scores); } @override String toString() => 'HARDEST CPU'; }