#!/usr/bin/perl # Filename: ttt_combos # Author: David Ljung Madison # See License: http://MarginalHacks.com/License # Description: All legal tic tac toe games use strict; ################################################## # Setup the variables ################################################## my $PROGNAME = $0; $PROGNAME =~ s|.*/||; # We create a tree of all possible games first, then # print out all the legal board positions once (there # can be more than one route to a single board position) # Do we want to print out the creation of the tree as well? my $SHOW_TREE = 0; # Do we include all intermediate board positions, or just # the final endgame boards? my $WIN_GAMES_ONLY = 0; ################################################## # Main code ################################################## my %PERMUTATIONS; sub show { my ($board,@moves) = @_; my $win = checkwin($board); if ($SHOW_TREE && ($win || !$WIN_GAMES_ONLY)) { print $win ? "WIN: " : " " unless $WIN_GAMES_ONLY; print "$board\t@moves\n"; } $PERMUTATIONS{$board}++ if $win || !$WIN_GAMES_ONLY; return $win; } sub show_permutations { my @perms = keys %PERMUTATIONS; my $num = $#perms+1; print "\nLegal board combos: $num\n"; foreach ( @perms ) { print "$_ [$PERMUTATIONS{$_}]\n"; } } sub checkwin { my ($board) = @_; # across return 1 if $board =~ /^(...){0,2}(XXX|OOO)/; # down return 1 if $board =~ /X..X..X/; return 1 if $board =~ /O..O..O/; # diagonal return 1 if $board =~ /^X...X...X/; return 1 if $board =~ /^O...O...O/; return 1 if $board =~ /^..X.X.X/; return 1 if $board =~ /^..O.O.O/; return 0; } sub try { my ($who,$pos,$board,@moves) = @_; push(@moves,$pos); substr($board,$pos,1,$who); return if show($board,@moves); move($who eq "X" ? "O" : "X", $board,@moves); } sub move { my ($who,$board,@moves) = @_; foreach my $pos (0..8) { next unless substr($board,$pos,1) eq "-"; try($who,$pos,$board,@moves); } } my $board = "-"x9; my @moves; move("X",$board,@moves); show_permutations;