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
Here are the issues:
The return
statement in the __str__
method of Terrain
is 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 put None
in 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 second if
should really be an else
, as otherwise it will also execute if the first if
block was executed (as it increments self.tour
)
self.grille[n] == 'X'
is wrong. That grid should consist of Case
instances, and not be overwritten. What needs to be set is an attribute of the Case
instance at that index. This is what the jouer2
method 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 a range
object. 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 the str()
function.
Don't put a number in a method name, like you have jouer1
and jouer2
, 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 the join
method.
I would also replace the 9 Case()
calls with list comprehension.
The if
constructs in the jouer
method can be replaced by statements which work correctly for both cases of self.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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.