Tic-Tac-Toe for Introduction to C programming (t3i2c)

At the Massachusetts Institute of Technology (MIT) there is a High School Studies Program (HSSP) run by the Educational Studies Program (ESP) that I have taken part in since 1996. A class I took in 1999 was Introduction to C Programming (I2C) as taught by Neel Pandeya. A project he gave us was to write a tic-tac-toe program in C using what we had learned so far (up to arrays and functions).

I started one boring Sunday morning and am still working on it. The current version is 0.11 and may be found in the file t3i2c-0.11.tar.gz. This file includes the C source, a README file, and a man page.

Compiling is simply a gcc tic-tac-toe.c -o t3i2c. It should compile with neither warning nor error. Running it is simply ./t3i2c. I am constantly updating it, so send me your suggestions, fixen, money, et cetera. Have fun!

How to use it

There seems to be some confusion as to how to use it. Here's how it works. The game board has three rows and three columns, numbered from 0 to 2. The empty game board looks as follows:

   0 1 2
0   | |
   -----
1   | |
   -----
2   | |

The player enters the coordinates of where it wants to go as this: r, c, where r is the row number and c is the column number. For example, to go to the center of the board, enter 1, 1.

In one-player mode, after the player makes a move the computer goes. The computer's coordinates are shown on the screen. Then, if the computer wins, that is printed to the screen. Else, the player takes another turn.

The artificial intelligence for one player mode is rather elaborate and it may be difficult to impossible to beat. I have trouble beating it myself! Look at the code for information on how to beat it.

In two player mode, the players alternate turns until either someone wins or the board is filled. If someone wins either one- or two-player mode, their name is added to the highscore file. The file may be redefined with the preprocessor statement #define "/path/to/highscore.lst".

How'd I do it?

I first divided it up into a main function, a function for the player to move, and a function to check if the spot on the game board is taken. main() takes the number of arguments and the arguments from the command line and returns an integer. It asks how many players there are and for the name of all the players. Then it prints the game board and calls the functions for the player and computer to make their move.

The playerMove() function takes no arguments and returns an integer. It first asks for the player's coordinates to move to. After checking that these moves are not taken, it sets the spot chosen to the player's. Then the turn is given to the next player, either the computer or player two.

I then wrote the function to check if the spot is taken, notTaken. It is a simple four-liner that returns false if the spot is taken and true otherwise. This function takes the row and column as its argument.

I encoded the owner of each spot on the game board with a number from 0 to 2. 0 is an empty spot, 1 is 'X' and is taken by player one, and 2 is an 'O' and is taken by player two or computer. I wrote a simple function retChar that takes the coordinates and returns the character that matches it; one of ' ' (a space), a 'X' (a X), or 'O' (an O).

Two functions were written to print often-used information. printBoard() takes no arguments and returns 1. It prints the board. Simple really.

The function to perform the computer's moves was the most interesting to write. It is a full artificial intelligence so the computer may beat you every time. It first attempts an offensive style move, where it looks if it may win. It basically looks f there is a two in a row, including wrapping (so the computer will match the middle spot). Then it tries for a defensive-type match, where it makes sure you can not get three in a row. If both offensive and defensive fails, it will try to get the middle spot. If even that fails (logically impossible), it will just rely on randomness. Then it prints the board, checks it for an end of game, and changes the player to the first player. It returns 0.

Another major function is checkBoard(). This function checks if there is a possible ending to the game, via three of the same type in a row or a lack of spaces left to move to. The section that checks for a winner uses a sixteen-line if statement. It then copies the name of the last player to the variable winner, unless the winner is the computer. It prints the winner's name, writes the name to the highscore list, and exits. To check for a full board, it adds up all the spaces with a value greater than 0. If they sum up to 9, the game is over. Otherwise, it returns 0.

I just have to know; have you ever ended a sentence with a semi-colon? Have I been working on this program too long?

I had to write a test function for the highscore file because this is my first time dealing with file input/output. After I figured it out pretty well, I wrote readHSL() and writeHSL(). Function readHSL reads the highscore list file and prints each line.

The function writeHSL writes to the highscore list. Simple, eh?

That's basically how its done. Now go write it your self.

Retrospective,

I sure do wish I had a copy of this. I wonder why I had functions that always returned 1 or 0.

The player enters the coordinates of where it wants to go as this: r, c, where r is the row number and c is the column number. For example, to go to the center of the board, enter 1, 1.

I really gave 1, 1 as the example?

Home - Contents - Search

Mike Burns <mike@mike-burns.com>