Tic-Tac-Toe and Connect Four
One of the best ways to get practice with object-oriented programming is implementing games.
This post is part of the book Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. Suggested citation: Skycak, J. (2021). Tic-Tac-Toe and Connect Four. In Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. https://justinmath.com/tic-tac-toe-and-connect-four/
Want to get notified about new posts? Join the mailing list.
One of the best ways to get practice with object-oriented programming is implementing games. Tic-tac-toe and connect four are great for learning the ropes. Later on, we will also use these implementations for developing AI players.
Exercise: Tic-Tac-Toe with Random Players
Develop a tic-tac-toe game in which two random players play against each other. You can implement your game however you want, provided that you adhere to the constraints below.
- There should be a
Game
class and aRandomPlayer
class. The game should be initialized viagame = Game(player1, player2)
, whereplayer1
andplayer2
are both instances ofRandomPlayer
andplayer1
moves first. - The
Game
should have an attributegame.board
, and there should be a methodplayer.choose_move(self, board)
in thePlayer
class that takes a copy of the tic-tac-toe board as input and returns a random (but legal) move as output. - Players should NOT actually update the board themselves -- otherwise, they could cheat by changing the board in any way they please. Rather, the game should ask the player what move it chooses, and then the game should update its own board (provided that it's a legal move). If a player attempts to make an illegal move, then the game should skip that player's turn.
- You should be able to run an entire game via
game.run(log)
. Iflog == true
, then the game should print out the sequence of board states and player moves (as well as whether or not the move was legal). Be sure to implement logging as soon as you start coding up the game, because printing out logs will save you a lot of time debugging.
Exercise: Tic-Tac-Toe with Manual Player
Then, create a ManualPlayer
class that allows you to play manually via the command line. You can use Python’s built-in input()
function for this.
player1 = RandomPlayer()
player2 = ManualPlayer()
game = Game(player1, player2)
game.run()
Be sure to test your game by manually playing a handful of games against the random player. (Don’t try to win every game – you’ll need to tie and lose some games for testing purposes.)
Exercise: Strategy Functions
Currently, you have two types of tic-tac-toe players: RandomPlayer
and ManualPlayer
. The only difference between these players is in how they choose moves. The rest of the code is duplicated, which is not ideal. There should really be just one Player
class, where the choose_move
method is automatically adjusted as desired.
To make your code cleaner, implement a single Player
class that is initialized via player = Player(strategy_function)
where strategy_function(board)
is a function that takes a copy of the tic-tac-toe board as input and returns a random move as output. Then player.choose_move(self, board)
will simply call the strategy_function
on the board and return the result.
player1 = Player(random_strategy_function)
player2 = Player(manual_strategy_function)
game = Game(player1, player2)
game.run()
Once you’ve implemented this, test your game again by manually playing a handful of games against the random player. Additionally, make sure that you are always able to beat the “cheater” strategy shown below. (If the cheater strategy wins, then it probably means that you’re allowing the player to access the actual game board instead of giving it a copy of the board.)
def cheater_strategy_function(board):
# put our own pieces everywhere on the board
for i in range(3):
for j in range(3):
board[i][j] = our own piece
# doesn't really matter what we return;
# we'll arbitrarily move into top-left corner
return (0,0)
Exercise: Custom Strategy
Create a custom strategy that beats the random player most of the time.
Exercise: Connect Four
Repeat the above exercises for the game of connect four. There are really only two differences:
- A player chooses a column to place their piece into, rather than an actual board space. So, a move will be a single integer rather than a tuple.
- Checking whether a player has won is more complicated.
This post is part of the book Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. Suggested citation: Skycak, J. (2021). Tic-Tac-Toe and Connect Four. In Introduction to Algorithms and Machine Learning: from Sorting to Strategic Agents. https://justinmath.com/tic-tac-toe-and-connect-four/
Want to get notified about new posts? Join the mailing list.