Add a Command-Line Interface
00:00
Add a Command-Line Interface. You are almost done building your tic-tac-toe front end. However, it’s time to add the finishing touches and turn it into a playable game by implementing a useful command-line interface using the argparse
module.
00:16
That way, you’ll be able to choose the player types and the starting mark before running the game. The entry point to your console front end is the special __main__.py
module, which makes the containing package runnable through the python
command.
00:31 Because it’s customary to put minimal wrapper code in it, you’ll keep the module lightweight by delegating the processing to a function imported from another module.
00:46
This makes the code that’s defined in cli.py
more reusable across many places and easier to test in isolation. Here’s how that code might look.
00:59
You import the game engine, your new console renderer, and a helper function, parse_args()
, which will be able to read the command-line arguments and, based on them, return two-player objects and the starting player’s mark.
01:28
To implement the passing of arguments, you can start by defining the available player types as a Python dictionary, which associates everyday names, such as human, with concrete classes extending the abstract Player
.
01:57
This will make it more straightforward to add more player types in the future. Next, you can write a function that will use the argparse
module to get the expected arguments from the command line.
03:27
This code translates to the three optional arguments seen on screen, all of which have default values. At this point, the function parses those arguments and stores their values as strings in a special NameSpace
object under the attributes named .player_x
, .player_o
, and .starting_mark
, respectively.
03:47 But the function is expected to return a tuple consisting of custom data types instead of strings. To make the function’s body comply with its signature, you can map strings provided by the user to the respective classes using your dictionary.
04:09 You translate the user-supplied names to concrete player classes. If the starting player’s mark is different from the default one, then you swap the two players before returning them from the function.
04:28 To make the code slightly cleaner and more expressive, you may replace the generic tuple with a typed named tuple.
04:49
First, you define a typing.NamedTuple
subclass comprising precisely three named and typed elements. You then return an instance of your NamedTuple
instead of a generic tuple.
05:05 Doing so gives you additional type safety and access to the tuple’s elements by name, as well as by index.
05:29 To play against another human, you can run your console front end with these arguments.
05:43
If you’d like to try your chances against the computer, then replace the value of either the -X
or -O
option with random, which is currently the only computer player type available.
05:53 Unfortunately, it isn’t particularly challenging to play against a computer making moves at random. So in the next chapter of the course, you’ll implement a more advanced computer player leveraging the minimax algorithm, making it practically undefeatable.
Become a Member to join the conversation.