You can try
self.values = [["-" for _ in range(3)] for _ in range(3)]
This will let you set up a 3x3 grid without having to draw the whole thing.
Now you can also do
board_str = "\n".join([ " | ".join(row) for row in grid ])
I would also suggest doing away with ...
This is now long past, but having coded my own version, some comments on your code.
You can do simpler. In particular, there is no need for the winning_position and earlier_move variables, simply knowing the value of len(board) % 4 gives you all that is needed.
Whether computer or user played first should not change the algorithm beyond ...
Here are some things that may help you improve your code.
Make sure you have all required #includes
The code in game.h refers to std::ostream and std::istream but doesn't #include <iostream> where those are defined. Also, carefully consider which #includes are part of the interface (and belong in the .h file) and which are part of the implementation. ...
Define simple member functions in the header files
If you define member functions inside the class definition, they can be inlined by the compiler. For simple functions, like CountDown::is_finished(), this will generate much more efficient code, even on a Z80.
Unnecessary casts to std::string
There are several unnecessary casts to std::string in your code, ...
Your constants (screen width, etc.) are fine as they are, but e.g. lives is not a constant - it should not live in the global namespace
Avoid calling pygame initialization methods in the global namespace
moveX and moveY are unused, so delete them
You need to pry apart your logic from your presentation; they're mixed up right now
Consider modularizing your ...
Naming of variables is perfect and you are following the python convention - and that is really good because it makes the code easier to read.
I've executed the code and I've noticed that when you insert an invalid input two things may happen
Input "1A"; Output: "Invalid format. That spot is already taken."
Input "X"; Output: ...
For now, let's assume that your bullets travel in a straight line from left to right, or from right to left.
Your zombies have a position, self.x and self.y. In addition, they also have an image that you draw on the screen (images['l_zombie'] in the Enemy.draw() method).
What I don't see is any mention of left-over pixels in the image. It could be ...
There's several parts of your design that can be improved.
There is currently lots of duplicate code regarding color, allowed moves, and Pawn1, Pawn2, Pawn3 etc.
Is there really any difference between Pawn1, Pawn2, Pawn3, etc? I don't think so. A Piece could be a composition between a player color and an enum class PieceType that lists all the options (...
naming should be consistent, choose either snake case or camel case, but not both.
variables/fields should be declared one per line.
all the fields should be private
name methods in a more meaningful way and do not shorten their names (for example, rng -> randomInt and cls -> clearScreen)
Using System.exit(0) is bad practice, you should use a condition ...
While testing your code, I found that the figure moves on a grid that doesn't actually exist. As such, I found myself running into signs, even though my figure was mostly above the sign. I also noticed that if you click quickly on the WASD keys, the figure doesn't move.
There's a few things to consider in order to address these issues:
You've made your ...