DYHBLNX63S326PH2KNHIBBQ27L2LXRHUVU3SNL3KRITV5RZNWA5AC
}
}
enum TicTacToePlayer { X, O }
final Set<int> winningTicTacToeScores = {7, 56, 448, 73, 146, 292, 273, 84};
class TicTacToeGame implements GameState<int?, TicTacToePlayer> {
List<TicTacToePlayer?>? board = [];
TicTacToePlayer? currentPlayer;
TicTacToePlayer? winner;
Map<TicTacToePlayer, int> scores = {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0,
};
TicTacToeGame(
{this.board, required this.scores, this.currentPlayer, this.winner});
static GameState<int?, TicTacToePlayer> newGame() {
return TicTacToeGame(
board:
List.from([null, null, null, null, null, null, null, null, null]),
currentPlayer: TicTacToePlayer.O,
scores: {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0,
});
}
@override
GameState<int?, TicTacToePlayer>? determine(
GameState<int?, TicTacToePlayer>? initialState) {
return initialState;
}
@override
List<int?> getMoves() {
if (winner == null) {
return board!
.asMap()
.map((index, player) =>
player == null ? MapEntry(index, null) : MapEntry(null, null))
.keys
.where((index) => index != null)
.toList();
}
return [];
@override
TicTacToeGame cloneAndApplyMove(int? move) {
if (move == null) {
return this;
}
var newScores = new Map<TicTacToePlayer, int>.from(scores);
if (board![move] != null) {
throw InvalidMove();
}
TicTacToePlayer newCurrentPlayer = currentPlayer == TicTacToePlayer.O
? TicTacToePlayer.X
: TicTacToePlayer.O;
TicTacToePlayer? newWinner;
List<TicTacToePlayer?> newBoard = List.from(board!);
newBoard[move] = currentPlayer;
Map<TicTacToePlayer, int> scoreByPlayer = {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0
};
newBoard.asMap().forEach((index, player) {
if (player != null) {
int addScore = pow(2.0, index.toDouble()).toInt();
scoreByPlayer.update(player, (score) => score + addScore,
ifAbsent: () => addScore);
}
});
for (var player in scoreByPlayer.keys) {
if (winningTicTacToeScores.contains(scoreByPlayer[player])) {
newWinner = player;
newScores[player] = 1;
}
}
return TicTacToeGame(
board: newBoard,
winner: newWinner,
scores: newScores,
currentPlayer: newCurrentPlayer);
}
import 'package:dartmcts/dartmcts.dart';
enum TicTacToePlayer { X, O }
final List<List<int>> checks = [
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 4, 8],
[6, 4, 2]
];
class TicTacToeGame implements GameState<int?, TicTacToePlayer> {
List<TicTacToePlayer?> board = [];
TicTacToePlayer? currentPlayer;
TicTacToePlayer? winner;
Map<TicTacToePlayer, int> scores = {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0,
};
TicTacToeGame(
{required this.board,
required this.scores,
this.currentPlayer,
this.winner});
static GameState<int?, TicTacToePlayer> newGame() {
return TicTacToeGame(
board:
List.from([null, null, null, null, null, null, null, null, null]),
currentPlayer: TicTacToePlayer.X,
scores: {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0,
});
}
@override
GameState<int?, TicTacToePlayer>? determine(
GameState<int?, TicTacToePlayer>? initialState) {
return initialState;
}
@override
List<int?> getMoves() {
if (winner == null) {
return board
.asMap()
.map((index, player) =>
player == null ? MapEntry(index, null) : MapEntry(null, null))
.keys
.where((index) => index != null)
.toList();
}
return [];
}
@override
TicTacToeGame cloneAndApplyMove(int? move) {
if (move == null) {
return this;
}
var newScores = new Map<TicTacToePlayer, int>.from(scores);
if (board[move] != null) {
throw InvalidMove();
}
TicTacToePlayer newCurrentPlayer = currentPlayer == TicTacToePlayer.O
? TicTacToePlayer.X
: TicTacToePlayer.O;
TicTacToePlayer? newWinner;
List<TicTacToePlayer?> newBoard = List.from(board);
newBoard[move] = currentPlayer;
for (var check in checks) {
if (newBoard[check[0]] != null &&
newBoard[check[0]] == newBoard[check[1]] &&
newBoard[check[1]] == newBoard[check[2]]) {
newWinner = newBoard[check[0]];
newScores[newBoard[check[0]]!] = 1;
}
}
return TicTacToeGame(
board: newBoard,
winner: newWinner,
scores: newScores,
currentPlayer: newCurrentPlayer);
}
String formatBoard() {
String formattedBoard = "";
int count = 0;
for (var cell in board) {
if (count % 3 == 0) {
formattedBoard += "\n";
}
switch (cell) {
case TicTacToePlayer.O:
formattedBoard += "O";
break;
case TicTacToePlayer.X:
formattedBoard += "X";
break;
default:
formattedBoard += " ";
}
count++;
}
return formattedBoard;
}
}
import 'dart:math';
import 'dartmcts.dart';
enum TicTacToePlayer { X, O }
final Set<int> winningTicTacToeScores = {7, 56, 448, 73, 146, 292, 273, 84};
class TicTacToeGame implements GameState<int?, TicTacToePlayer> {
List<TicTacToePlayer?> board =
List.from([null, null, null, null, null, null, null, null, null]);
TicTacToePlayer? currentPlayer;
TicTacToePlayer? winner;
Map<TicTacToePlayer, int> scores = {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0
};
TicTacToeGame({required this.board, this.currentPlayer, this.winner});
String toString() {
return this.board.toString();
}
static GameState<int?, TicTacToePlayer> newGame() {
return TicTacToeGame(
board:
List.from([null, null, null, null, null, null, null, null, null]),
currentPlayer: TicTacToePlayer.O);
}
import 'package:dartmcts/dartmcts.dart';
import 'package:dartmcts/tictactoe.dart';
@override
GameState<int?, TicTacToePlayer> determine(
GameState<int?, TicTacToePlayer>? initialState) {
return this;
}
@override
List<int?> getMoves() {
if (winner == null) {
return board
.asMap()
.map((index, player) =>
player == null ? MapEntry(index, null) : MapEntry(null, null))
.keys
.where((index) => index != null)
.toList();
}
return [];
}
@override
TicTacToeGame cloneAndApplyMove(int? move) {
if (move == null) {
return this;
}
if (board[move] != null) {
throw InvalidMove();
}
TicTacToePlayer newCurrentPlayer = currentPlayer == TicTacToePlayer.O
? TicTacToePlayer.X
: TicTacToePlayer.O;
TicTacToePlayer? newWinner;
List<TicTacToePlayer?> newBoard = List.from(board);
newBoard[move] = currentPlayer;
Map<TicTacToePlayer, int> scoreByPlayer = {
TicTacToePlayer.O: 0,
TicTacToePlayer.X: 0
};
board.asMap().forEach((index, player) => {
if (player != null)
{
scoreByPlayer.update(
player, (score) => score + pow(2.0, index.toDouble()).toInt(),
ifAbsent: () => pow(2.0, index.toDouble()).toInt())
}
});
for (var player in scoreByPlayer.keys) {
if (winningTicTacToeScores.contains(scoreByPlayer[player])) {
newWinner = player;
}
}
if (getMoves().length == 0 && newWinner == null) {
throw Exception('boom time');
}
return TicTacToeGame(
board: newBoard, winner: newWinner, currentPlayer: newCurrentPlayer);
}
}
MCTSResult<int?, TicTacToePlayer> result =
MCTS(gameState: gameState).getSimulationResult(iterations: 100);
int iterations = 10;
if (gameState.currentPlayer == TicTacToePlayer.X) {
iterations = 100;
}
MCTSResult<int?, TicTacToePlayer> result = MCTS(gameState: gameState)
.getSimulationResult(iterations: iterations);