'Tic Tac Toe game: Printing the value of a class object inside a list
I have to design a simple tic tac toe game for an assignment. The instructions are to make a Case (for the square) class initiated with an "occupe" variable that starts with ' ' and will be filled with an 'X' if it's player's 1 turn and an 'O' if it's player's 2 turn.
Then I have to build a class Terrain (for the board) which inherits the Case and constructs a grid (the "grille") with a list of nine Case objects.
But then I just can't figure out how to print the content of the squares and not the method itself.
Is my 'Case' class badly defined?
Here is the code:
class Case:
def __init__(self):
self.occupe = ' '
def jouer1(self):
if self.occupe == ' ':
self.occupe = 'O'
else:
print('La case est déjà occupée')
def jouer2(self):
if self.occupe == ' ':
self.occupe = 'X'
else:
print('La case est déjà occupée')
def __str__(self):
return self.occupe.__str__()
class Terrain(Case):
def __init__(self):
b = [Case(),Case(),Case(),Case(),Case(),Case(),Case(),Case(),Case()]
self.grille = b
self.tour = 1
def __str__(self):
return self.grille[0].__str__() + '|' + self.grille[1].__str__()
+ '|' + self.grille[2].__str__() + '|' + '\n'
+ self.grille[3].__str__() + '|' + self.grille[4].__str__() + '|'
+ self.grille[5].__str__() + '|' + '\n'
+ self.grille[6].__str__() + '|' + self.grille[7].__str__() + '|'
+ self.grille[8].__str__() + '|' + '\n'
def jouer(self, n= range(0,8)):
if self.tour == 1:
self.grille[n] = self.grille[n].jouer1
self.tour = self.tour +1
if self.tour == 2:
self.grille[n] == 'X'
self.tour = self.tour - 1
T1 = Terrain()
T1.jouer(0)
print(T1)
The result:
<bound method Case.jouer1 of <__main__.Case object at 0x7f27c7d0fc90>>| | |
I expected to get an "X" in the print results
Solution 1:[1]
Here are the issues:
The
returnstatement in the__str__method ofTerrainis split over multiple lines, but is not interpreted like that. You should either wrap that expression in parentheses or use a line continuation character (\) at each line wrap.Parentheses are missing after
grille[n].jouer1, so the function is never called.grille[n].jouer1()does not return a value, so it should not be assigned to anything, otherwise you putNonein your grid. Moreover, that method already assigns the correct character to that entry in the grid, so it should not happen here.In
jouer, the secondifshould really be anelse, as otherwise it will also execute if the firstifblock was executed (as it incrementsself.tour)self.grille[n] == 'X'is wrong. That grid should consist ofCaseinstances, and not be overwritten. What needs to be set is an attribute of theCaseinstance at that index. This is what thejouer2method does, so call it.n=range(0,8)is not doing what you intended. I guess you wanted to indicate what the limits are for this parameter, but instead it defines a default value, which is arangeobject. As your code expects it to be a number, you should omit this.
The above are the errors/mistakes in your code. But there are other things you should modify:
You should not call the
__str__method explicitly, but (if needed) call thestr()function.Don't put a number in a method name, like you have
jouer1andjouer2, which leads to code repetition. Instead pass that number as argument to a method that treats it accordingly.The expression in your second
__str__method (which spans several lines) can be reduced by using the power of loops, list comprehension syntax and thejoinmethod.I would also replace the 9
Case()calls with list comprehension.The
ifconstructs in thejouermethod can be replaced by statements which work correctly for both cases ofself.tour
Here is how the resulting code could look:
class Case:
def __init__(self):
self.occupe = ' '
def jouer(self, tour): # Don't put number in method name; pass it as argument
if self.occupe == ' ':
self.occupe = ' OX'[tour] # Dynamically determine the character
else:
print('La case est déjà occupée')
def __str__(self):
return str(self.occupe) # Call str, not __str__
class Terrain(Case):
def __init__(self):
self.grille = [Case() for _ in range(9)] # List comprehension
self.tour = 1
def __str__(self):
# no need to call __str__, but call str(). Use comprehension & join
return "\n".join("|".join(map(str, self.grille[i*3:i*3+3])) for i in range(3))
def jouer(self, n): # Not default value as range
self.grille[n].jouer(self.tour) # Call - don't assign
self.tour = 3 - self.tour # Toggle
T1 = Terrain()
T1.jouer(0)
T1.jouer(4)
T1.jouer(3)
print(T1)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | trincot |
