[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] Tic Tac Toe Exercise



Hi,

I previously asked for some help on putting a GUI interface on our tic tac
toe program exercise and got some great responses from the list members.
We've just about finished the GUI interface; the code is set forth below.
The last major stumbling block is to make the buttons appear only at the
beginning of each game, and disappear during game play.  If anyone can show
us how to set the visibility boolean for a button control, we'd appreciate
it.

Lastly, where can we read about MacPerl Toolbox subroutines generally?  The
MacPerl pod help isn't detailed enough (and Inside Macintosh is too
detailed) for beginners like us. We've already looked at MacPerl Power and
Ease.

Thanks!

Darryl Tang and kids

___________

#perl -w

use Mac::Windows;
use Mac::QuickDraw;
use Mac::Events;
use Mac::Controls;
Mac::Fonts;

my($style, $title, $win, $winr, $xp, $yp);

@groups = ([1, 2, 3], [8, 0, 4], [7, 6, 5],
		   [1, 8, 7], [2, 0, 6], [3, 4, 5],
		   [1, 0, 5], [7, 0, 3]);

@xycoord = ([70,130], [10,70], [70,70],
           [130,70], [130,130], [130,190],
           [70,190], [10,190], [10,130]);

@gridhash = ([1, 2, 3], [8, 0, 4], [7, 6, 5]);

$style = floatProc();
$title = 'Tic Tac Toe';
$winr = Rect->new(300, 200, 500, 450);
$win = MacWindow->new(NewCWindow($winr, $title, 1, $style, 1));

$conmac = $win->new_control(
	Rect->new(77, 225, 122, 245),# rectangle
	'Mac',# title
	1,# visibility boolean
	0, 0, 0,# default, min., and max. values
	pushButProc()# type
);

$conme = $win->new_control(
	Rect->new(140, 225, 185, 245),# rectangle
	'Me',# title
	1,# visibility boolean
	0, 0, 0,# default, min., and max. values
	pushButProc()# type
);

$conmac->sethook('hit' => \&macs_turn);
$conme->sethook('hit' => \&my_turn);

$win->sethook('redraw' => \&drawgrid);
$win->sethook('click' => \&click_me);
$win->sethook('goaway' => \&handle_close_box);

sub initialize {
	@xandos = (" ", " ", " ", " ", " ", " ", " ", " ", " ");
	$buttonflag = 0;
	$movestring = (); # keeps record of moves made
	@winningmoves = qw(147 163 127 183 138 172 157 021 253 271 240 280);
	@drawmoves = qw(103 013 201 203 210 230 260);

	SetPort($win->window);
	RGBForeColor(new_color(65535, 65535, 65535)); #white
	PaintRect(Rect->new(0, 0, 200, 198));
	drawgrid();
}

$xwins = 0;
$owins = 0;
$draws = 0;

MAINLOOP: for (;;) {

	initialize();
	WAITPUSH:  while ($win->window()) {
		WaitNextEvent();
		if ($buttonflag == 1) {
			last WAITPUSH;
		}
	 }


	for $s (1..9) {
		if ($turn eq "x") {
			if (length($movestring) == 0) { # make first move
				randompick();
				rotatemoves($pick);
				# print "\nPicking for x...\n\n";
				# $xandos[$pick] = $turn;
				# $movestring .= $pick;
			}
			elsif (length($movestring) == 1) { # make second move
				$pick = "";
				rotatemoves($movestring);
				foreach $drawstring (@drawmoves) {
					if ($drawstring =~ /^$movestring/) {
						$pick = substr($drawstring,
1, 1);
						# print "\nPicking for
x...\n\n";
						$xandos[$pick] = $turn;
						$movestring .= $pick;
						last;
					}
				}
				if ($pick eq "") {
					randompick();
				}
			}
			elsif (length($movestring) == 2) { # make third move
				$pick = "";
				foreach $winstring (@winningmoves) {
					if ($winstring =~ /^$movestring/) {
						$pick = substr($winstring,
2, 1);
						# print "\nPicking for
x...\n\n";
						$xandos[$pick] = $turn;
						$movestring .= $pick;
						last;
					}
				}
				if ($pick eq "") {
					randompick();
				}
			}
			elsif (($pick = winorblock()) ne "") { # look for
win or block move
				# print "\nPicking for x...\n\n";
				$xandos[$pick] = $turn;
				$movestring .= $pick;
			}
			elsif (($pick = testforsetup()) ne "") { # look for
conclusive set up move
				# print "\nPicking for x...\n\n";
				$xandos[$pick] = $turn;
				$movestring .= $pick;
			}
			else { # make a random pick
				randompick();
			}
		}
		else { # o's turn
			WAITEVENT:  while ($win->window()) {
				WaitNextEvent();
				if ($clickflag == 1) {
					$clickflag = 0;
					last WAITEVENT;
				}
			 }
		}
		if ($turn eq "x") {
			$turn = "o";
		}
		else {
			$turn = "x";
		}

		drawgrid();
		if (testwon() =~ /(x)|(o)/) {
			# print "$+ is the winner!\n";
			if ($+ eq "x") {
				$xwins++;
			}
			elsif ($+ eq "o") {
				$owins++;
			}
			last;
		}
		elsif (length($movestring) == 9) {
			# print "There was no winner.  Game over, man\!\n";
			$draws++;
		}
	}
	sleep(2);
}



sub click_me {

	if ($buttonflag == 0) {
		return();
	}

	# get h & v coordinates
	my $pt = $_[1];

	my $vpos = $pt->v;
	my $hpos = $pt->h;

	for $i (0, 1, 2) {
		for $j (0, 1, 2) {
			if (($vpos >= $i *60 +20) and ($vpos <= ($i + 1) *
60)) {
				if (($hpos >= $j *60 +20) and ($hpos <= ($j
+ 1) * 60)) {
					$pick = $gridhash[$i][$j];

				}
			}
		}
	}

	# test if pick was valid

	$clickflag = 0;

	if ($xandos[$pick] eq " ") {
		$xandos[$pick] = $turn;
		$movestring .= $pick;
		$clickflag = 1;
	}

}

sub drawgrid {  # draws the grid

	# SetPort($win->window);
	RGBForeColor(new_color(0, 0, 0)); #black
	MoveTo(70, 10);
	LineTo(70, 190);
	MoveTo(130, 10);
	LineTo(130, 190);
	MoveTo(10, 70);
	LineTo(190, 70);
	MoveTo(10, 130);
	LineTo(190, 130);

	for ($i = 0; $i < 9; $i++) {
		MoveTo($xycoord[$i][0] + 17, $xycoord[$i][1] - 17);
		if ($xandos[$i] eq "x") {
			RGBForeColor(new_color(65535, 0, 0)); # red
		}
		elsif ($xandos[$i] eq "o") {
			RGBForeColor(new_color(4413, 49152, 8598)); # green

		}
		TextSize(40);
		DrawString($xandos[$i]);
	}
	RGBForeColor(new_color(0, 0, 0)); # black
	MoveTo(0, 199);
	LineTo(200, 199);

	RGBForeColor(new_color(49152, 49152, 49152)); # platinum
	PaintRect(Rect->new(0, 200, 200, 250));

	RGBForeColor(new_color(0, 0, 0)); # black
	MoveTo(6, 212);
	TextSize(10);
	DrawString("X:  $xwins");
	MoveTo(6, 226);
	TextSize(10);
	DrawString("O:  $owins");
	MoveTo(6, 240);
	TextSize(10);
	DrawString("D:  $draws");

	DrawControls $win->window;
}

sub testwon { # tests if anyone has won yet
	for $q (0 .. 7) {
		if (($xandos[$groups[$q]->[0]] . $xandos[$groups[$q]->[1]]
. $xandos[$groups[$q]->[2]]) =~ /(x{3})|(o{3})/) {
			$winner = substr($+, 0, 1);
			return($winner);
		}
	}
}

sub winorblock { # tests if it can win or needs to block
	my($wbstring, $location);

	for $q (0 .. 7) {
		$wbstring = ($xandos[$groups[$q]->[0]] .
$xandos[$groups[$q]->[1]] . $xandos[$groups[$q]->[2]]);
		if ($wbstring =~ /( xx)|(x x)|(xx )/) {
			if    ($+ =~ " xx") {$location = $groups[$q]->[0]}
			elsif ($+ =~ "x x") {$location = $groups[$q]->[1]}
			elsif ($+ =~ "xx ") {$location = $groups[$q]->[2]}
			return($location);
		}
	}
	for $q (0 .. 7) {
		$wbstring = ($xandos[$groups[$q]->[0]] .
$xandos[$groups[$q]->[1]] . $xandos[$groups[$q]->[2]]);
		if ($wbstring =~ /( oo)|(o o)|(oo )/) {
			if    ($+ =~ " oo") {$location = $groups[$q]->[0]}
			elsif ($+ =~ "o o") {$location = $groups[$q]->[1]}
			elsif ($+ =~ "oo ") {$location = $groups[$q]->[2]}
			return($location);
		}
	}
	return ("");
}

sub testforsetup { # tests for initiating a setup a win or preventing a setup
	my($string, @intersecs, %seen, $item);

	for $q (0 .. 7) {
		$string = ($xandos[$groups[$q]->[0]] .
$xandos[$groups[$q]->[1]] . $xandos[$groups[$q]->[2]]);
		if ($string =~ /(x  )|( x )|(  x)/) {
			if ($+ =~ "x  ") {
				push (@intersecs, $groups[$q]->[1],
$groups[$q]->[2]);
			}
			elsif ($+ =~ " x ") {
				push (@intersecs, $groups[$q]->[0],
$groups[$q]->[2]);
			}
			elsif ($+ =~ "  x") {
				push (@intersecs, $groups[$q]->[0],
$groups[$q]->[1]);
			}
		}
	}

	foreach $item (@intersecs) {
		if ($seen{$item}++) {
			return($item);
		}
	}
	return ("");
	initialize();
	sleep(1);

}

sub randompick { # picks at random
	my($q, @temparray);
	for $q (0 .. 8){
		push(@temparray, $q) if ($xandos[$q] eq " ")
	}
	$pick = $temparray[rand @temparray];
	$xandos[$pick] = $turn;
	$movestring .= $pick;
}

sub rotatemoves { # rotates the winningmoves and drawmoves arrays based on
first pick
	my($shift, $i);
	my($firstpick) = shift(@_);
	if ($firstpick =~ /0|1|2/) {
		return();
	}
	elsif ($firstpick =~ /3|4/) {
		$shift = 2;
	}
	elsif ($firstpick =~ /5|6/) {
		$shift = 4;
	}
	elsif ($firstpick =~ /7|8/) {
		$shift = 6;
	}
	for ($i = 0; $i <= $#winningmoves; $i++) {
		$winningmoves[$i] = mod8it($winningmoves[$i], $shift);
	}
	for ($i = 0; $i <= $#drawmoves; $i++) {
		$drawmoves[$i] = mod8it($drawmoves[$i], $shift);
	}
}


sub mod8it { # rotates each character of a string; works with rotatemoves
subroutine
	my($y, $tempchar);
	my($x, $shift) = @_;
	while ($x =~ /(.)/g) {
		$tempchar = $1;
		unless ($tempchar eq "0") {
			$tempchar = ($tempchar + $shift) % 8;
			if ($tempchar eq "0") {
				$tempchar = "8";
			}
		}
		$y .= $tempchar;
	}
	return ($y);
}

sub handle_close_box {
	if ($win) {
		dispose $win;
	}
	exit();
}

sub new_color {
	bless(\pack('SSS', @_[0..2]), 'RGBColor');
}

sub macs_turn {
	if ($buttonflag == 1) {
		return();
	}
	$buttonflag = 1;
	$turn = "x";
}

sub my_turn {
	if ($buttonflag == 1) {
		return();
	}
	$buttonflag = 1;
	$turn = "o";
}


_________________________________________________________

Yoshi's Franchise Corporation
of America, Inc.

http://www.yoshisonline.com


-end message-





===== Want to unsubscribe from this list?
===== Send mail with body "unsubscribe" to macperl-request@macperl.org