简体   繁体   中英

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM