Last active
October 18, 2023 18:20
-
-
Save eqhmcow/e29603ae0092b9820681f7494eee6e53 to your computer and use it in GitHub Desktop.
compute all possible tic tac toe games
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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