14
Apr
10

Tic-Tac-Toe: Awk

Awk’s original intended use is as a stream processor, and in fact in its most basic form you can’t even do explicit input. My first version of this used gawk/nawk extensions for that purpose, but I figured it would be a bit more fun to use input patterns, so that’s what you see here.

Perl fans (and thus, Ruby and Python fans) might recognize an ancestor here.

#!/usr/bin/env awk -f

BEGIN {
	split("1 2 3 4 5 6 7 8 9", spaces)
	player = "X"

	print_board()
	print_prompt()
}

/[0-9]/ { place_move($1) }
/./ { print_board(); print_prompt() }

function print_board () {
	print ""
	for (i = 1; i <= 9; i++) {
		space = spaces[i]
		if (space ~ /[0-9]/)
			printf("(%d)", space);
		else
			printf(" %s ", space);

		if (i % 3 == 0) {
			if (i / 3 < 3) {
				printf "\n---+---+---\n";
			}
		} else {
			printf "|";
		}
	}

	print "\n"
}

function print_prompt () {
	printf "Select a square, %s: ", player
}

function read_move () {
	getline move
}

function place_move (move) {
	if (move && spaces[move] == move) {
		spaces[move] = player
		good_move = 0

		if (keep_playing()) {
			swap_player()
		} else {
			exit 0
		}
	}
}

function swap_player () {
	if (player == "X")
		player = "O"
	else
		player = "X"
}

function m3(i, j, k) {
	return spaces[i] == spaces[j] && spaces[j] == spaces[k]
}

function has_winner () {
	return m3(1,2,3) ||
		   m3(4,5,6) ||
		   m3(7,8,9) ||
		   m3(1,4,7) ||
		   m3(2,5,8) ||
		   m3(3,6,9) ||
		   m3(1,5,9) ||
		   m3(3,5,7);
}

function is_draw () {
	for (i = 1; i <= 9; i++) {
		space = spaces[i]
		if (space ~ /[0-9]/)
			return 0;
	}
	return 1
}

function keep_playing() {
	if (has_winner()) {
		print_board()
		printf("%s Wins!\n", player)
		return 0;
	} else if (is_draw()) {
		print_board()
		print("It's a Draw!")
		return 0;
	} else
		return 1;
}
Advertisement

0 Responses to “Tic-Tac-Toe: Awk”



  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.