Skip to content

Instantly share code, notes, and snippets.

@eqhmcow
Last active October 18, 2023 18:20
Show Gist options
  • Save eqhmcow/e29603ae0092b9820681f7494eee6e53 to your computer and use it in GitHub Desktop.
Save eqhmcow/e29603ae0092b9820681f7494eee6e53 to your computer and use it in GitHub Desktop.
compute all possible tic tac toe games
#include <stdio.h>
#include <stdbool.h>
#define SIZE 9
// Winning combinations
const int WINNING_COMBINATIONS[8][3] = {
{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{0, 4, 8}, {2, 4, 6}
};
int checked_games = 0;
int good_games = 0;
int games_draw = 0;
int games_win_x[SIZE+1] = {0};
int games_win_o[SIZE+1] = {0};
void generate_possible_games(char board[], int moves_made, char current_player);
bool is_winning_board(char board[]);
void initial_board() {
for (int position = 0; position < SIZE; position++) {
char board[SIZE+1] = {0};
board[position] = 'x';
generate_possible_games(board, 1, 'o');
}
}
void generate_possible_games(char board[], int moves_made, char current_player) {
if (moves_made == SIZE) {
games_draw++;
good_games++;
return;
}
char next_player = (current_player == 'x') ? 'o' : 'x';
moves_made++;
for (int position = 0; position < SIZE; position++) {
if (board[position] != 0) continue;
char new_board[SIZE+1];
for (int i = 0; i < SIZE; i++) {
new_board[i] = board[i];
}
new_board[position] = current_player;
if (moves_made >= 5 && is_winning_board(new_board)) {
if (current_player == 'x') games_win_x[moves_made]++;
else games_win_o[moves_made]++;
good_games++;
continue;
}
generate_possible_games(new_board, moves_made, next_player);
}
}
bool is_winning_board(char board[]) {
checked_games++;
for (int i = 0; i < 8; i++) {
int a = WINNING_COMBINATIONS[i][0];
int b = WINNING_COMBINATIONS[i][1];
int c = WINNING_COMBINATIONS[i][2];
if (board[a] && board[a] == board[b] && board[a] == board[c]) {
return true;
}
}
return false;
}
int main() {
initial_board();
printf("Checked games: %d\n", checked_games);
printf("Good games: %d\n", good_games);
printf("Draw games: %d\n", games_draw);
printf("Wins for x:\n");
for (int i = 5; i <= SIZE; i++) {
printf(" %d moves: %d\n", i, games_win_x[i]);
}
printf("Wins for o:\n");
for (int i = 5; i <= SIZE; i++) {
printf(" %d moves: %d\n", i, games_win_o[i]);
}
return 0;
}
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use constant WINNING_COMBINATIONS => (
[0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns
[0, 4, 8], [2, 4, 6] # Diagonals
);
my %games;
my $checked_games = 0;
my $good_games = 0;
sub initial_board {
foreach my $position (0..8) {
my @board = ('') x 9;
$board[$position] = 'x';
generate_possible_games(\@board, 1, 'o');
}
}
sub generate_possible_games {
my ($board, $moves_made, $current_player) = @_;
# Check for draw
if ($moves_made == 9) {
record_draw();
return;
}
# Determine the next player
my $next_player = $current_player eq 'x' ? 'o' : 'x';
$moves_made++; # Increment moves_made after checking for draw
foreach my $position (0..8) {
next if $board->[$position];
my @new_board = @$board;
$new_board[$position] = $current_player;
# Check for win after 5 or more moves
if ($moves_made >= 5 && is_winning_board(\@new_board)) {
record_win($current_player, $moves_made);
next;
}
generate_possible_games(\@new_board, $moves_made, $next_player);
}
}
sub is_winning_board {
my ($board) = @_;
$checked_games++;
foreach my $combo (WINNING_COMBINATIONS) {
my ($a, $b, $c) = @$combo;
if ($board->[$a] && $board->[$a] eq $board->[$b] && $board->[$a] eq $board->[$c]) {
return 1;
}
}
return 0;
}
sub record_draw {
$games{draw}++;
$good_games++;
}
sub record_win {
my ($winner, $moves_made) = @_;
$games{win}{$winner}{$moves_made}++;
$good_games++;
}
# Start the game generation
initial_board();
# Print results
print "Checked games: $checked_games\n";
print "Good games: $good_games\n";
print Dumper \%games;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment