Project 2: Connect Four

In this project, you will use the minimax and alpha-beta pruning algorithms to study the game of Connect Four (or sometimes Connect Three).

Part A: Minimax alone

Sample output for Part A

Your program should prompt the user for an initial board size in rows and columns, and an integer n, which will be either three or four. (Connect Two is not a very interesting game, and Connect Five or larger would have too large a state space.) Your program will then use the minimax algorithm to traverse the entire game tree to determine if the first player has a guaranteed win, the second player has a guaranteed win, or neither player is guaranteed to win (either player can force a draw).

Print out the result of the minimax search (guaranteed win, lose, or draw), and then let the user play against the computer, with the computer making the first move, and using the saved minimax actions to play. If your minimax algorithm determined that the first player has a guaranteed win, then the computer should never lose.

Note: You should use a transposition table to cache minimax values and the best moves for game states which occur multiple times in the game tree. If you don't, your minimax search will not be able to search very large state spaces.
Note 2: Do not re-run minimax after every move. Just run minimax at the start of the game and save all the best-move actions.
Hint: For a transposition table, I used a hash table that maps game states (board configurations) to a struct that contains both the minimax value for that game state, and the best move from that game state. Using this, whenever I encounter a state that's already in the map, I don't bother continuing the recursion from that state, I just look up the saved minimax value.

Part B: Minimax with alpha-beta pruning and heuristics

Sample output for Part B

You will notice that Part A will not be able to search the full state space for the "traditionally-sized" game of Connect Four (6 rows, 7 columns) --- there are just too many board configurations to consider. It turns out even alpha-beta pruning will not make this search feasible. Instead, what we will do is similar to what humans do when faced with a game that can continue for a large number of moves: we will only look ahead a fixed number of moves. To do this, we will require a heuristic function that can estimate the quality of an unfinished game state. (See section 5.4 or your notes from class on 9/25).

Your program should prompt the user for an initial board size in rows and columns, and an integer n, which will be either three or four. (If you support larger values of n and larger board sizes, you will get extra credit.) Your program should also ask the user for a number of moves to search ahead, which we will call d (for depth). d counts moves by both players, so if d=1, the computer will only be able to examine the game states resulting from the its own next move. If d=2, the computer will be able to examine game states resulting from its own next move and the user's response move.

Unlike part A, where we used minimax to "pre-process" the game tree to get the best moves, we will use minimax with alpha-beta pruning after each move of the game. The reason for this is since we are using a cut-off depth, if we run a search after each move, we will always be able to look d moves ahead.

Your program should immediately launch a game with the computer moving first. In other words, the computer will run alpha-beta with heuristics, looking ahead d moves, and make what it determines to be the best move. Then the user will get a chance to move, and the computer will run another search, looking d moves ahead again, except because the game has progressed, those d moves get you two levels deeper in the game tree.

Note: Because we are using a cut-off depth, the computer player is not expected to play perfectly, even in cases where in Part A it would have always won. That being said, if we use a deep enough cut-off depth and a good heuristic, the computer player should be pretty good. Part C tests how good.

Part C: Simulation

Sample output for Part C

Let the user type in values for rows, columns, n, and d, as in Part B. Run a simulation of 100 games with the same computer player as Part B against an opponent who plays randomly. The alpha-beta player should move first; the random player should move second. Print the number of games the computer wins.

Getting started

The first thing you should do is write code to support playing Connect Four on an arbitrary sized board (up to "normal-sized", which is six rows and seven columns). You will need code to take an arbitrary game state and generate all successor states (the game states resulting from all possible moves), and code to test a game state to determine if the game is won.

Hints and suggestions

What to turn in

Through Moodle, turn in your code. In addition, turn in a text file which explains what your heuristic function does.

Grading

You will be graded on correctness of your program, and also the quality of your heuristic for Parts B and C (measured by how often the alpha-beta player wins).

Hints