Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Scaffold Your Game

00:00 Scaffold a Generic Tic-Tac-Toe Game Engine. At this point, you should have all the domain models defined for your tic-tac-toe library. Now it’s time to build a game engine that will take advantage of these model classes.

00:14 To facilitate tic-tac-toe gameplay, go ahead and create three more Python modules inside the tic_tac_toe.game package as seen on-screen.

00:26 The engine module is the centerpiece of the virtual gameplay, where you’ll implement the game’s main loop. You’ll define abstract interfaces that the game engine uses, along with a sample computer player, in the players and renderers module.

00:41 By the end of this step, you’ll be set to write a tangible front end for the tic-tac-toe library. At the very minimum, to play a tic-tac-toe game, you need to have two players, something to draw on, and a set of rules to follow.

00:55 Fortunately, you can express these elements as immutable data classes, which take advantage of the existing domain model from your library.

01:05 First, create the TicTacToe class in the engine module.

01:22 Both Player and Renderer will be implemented in the following sections as Python’s abstract base classes. These only describe the high-level interface for the game engine.

01:32 They’ll eventually get replaced with concrete classes, some of which may come from an externally defined front end. The player will know what move to make, and the renderer will be responsible for visualizing the grid. To play the game, you must decide which player should make the first move, or you can assume the default one, which is the player with crosses.

01:53 You should also begin with a blank grid of cells and an initial game state.

02:41 The engine requests that the renderer update the view and then uses a pull strategy to advance the game by asking both players to make their moves in alternating rounds.

02:51 These steps are repeated in an infinite loop until the game is over. GameState only knows about the current player’s mark, which can be either X or O, but it doesn’t know about the specific player objects that were assigned those marks.

03:05 Therefore, you need to map the current mark to a player object using this helper method.

03:18 Here you compare enum members by their identities using Python’s is operator. If the current player’s mark, determined by the game state, is the same as the mark assigned to the first player, then that’s the player who should be making the next move.

03:33 Both players supplied to the TicTacToe object should have opposite marks. Otherwise, you wouldn’t be able to play the game without violating the rules, so it’s reasonable to validate the player’s marks when instantiating the TicTacToe class.

03:59 You add a post-initialization hook to the data class and call another validation function that you have to add into your validators module.

04:32 You use the identity comparison again to check both players’ marks and prevent the game from starting when both players use the same mark. There’s one more thing that can go wrong. Because it’s up to the players, including human players, to decide what move they make, their choice could be invalid.

04:52 Currently, the TicTacToe class catches the InvalidMove exception, but it doesn’t do anything useful with it other than ignore such a move and ask the player to make a different choice.

05:03 It would probably help to let the front end handle errors by, for example, showing a suitable message.

05:16 To let the front end decide how to take care of an invalid move, you expose a hook in the class by introducing an optional .error_handler callback, which will receive the exception.

05:26 You define the callback’s type using a type alias, making its type declaration more concise.

05:40 The TicTacToe game will trigger this callback in case of an invalid move, as long as you provide the error handler.

05:58 Having implemented an abstract tic-tac-toe game engine, you can proceed to code an artificial player. In the next section of the course, you’ll define a generic player interface and implement it with a sample computer player that makes moves at random.

Become a Member to join the conversation.