Select Git revision
cpu_level_page.dart
-
Benoît Harrault authoredBenoît Harrault authored
cpu.dart 2.79 KiB
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';
}