I created a Tic_Tac_Toe class to play the game Tic Tac Toe. Is there a better way of coding a game like this? I started learning python 5 days ago and my knowledge is limited.

class Tic_Tac_Toe:
    x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = x9 = ''
    l = '|'
    a1 = a3 = b1 = b3 = c1 = c3 = a4 = a6 = b4 = b6 = c4 = c6 = a7 = a9 = b7 = b9 = c7 = c9 = '   '
    a2 = ' 1 '
    b2 = ' 2 '
    c2 = ' 3 '
    a5 = ' 4 '
    b5 = ' 5 '
    c5 = ' 6 '
    a8 = ' 7 '
    b8 = ' 8 '
    c8 = ' 9 '

    def already_taken(self):
        print('Already taken')

    def pr_r(self):
        print(self.a1 + self.l + self.b1 + self.l + self.c1)
        print(self.a2 + self.l + self.b2 + self.l + self.c2)
        print(self.a3 + self.l + self.b3 + self.l + self.c3)
        print('---+---+---')
        print(self.a4 + self.l + self.b4 + self.l + self.c4)
        print(self.a5 + self.l + self.b5 + self.l + self.c5)
        print(self.a6 + self.l + self.b6 + self.l + self.c6)
        print('---+---+---')
        print(self.a7 + self.l + self.b7 + self.l + self.c7)
        print(self.a8 + self.l + self.b8 + self.l + self.c8)
        print(self.a9 + self.l + self.b9 + self.l + self.c9)

    def turn_x(self):
        player_choice = input()
        if player_choice == '1' and Tic_Tac_Toe.a2 == ' X ' or player_choice == '1' and Tic_Tac_Toe.a2 == '|+|':
            self.already_taken()
        elif player_choice == '1':
            Tic_Tac_Toe.x1 = 1
            Tic_Tac_Toe.a1 = '\ /'
            Tic_Tac_Toe.a2 = ' X '
            Tic_Tac_Toe.a3 = '/ \\'
        elif player_choice == '2' and Tic_Tac_Toe.b2 == ' X ' or player_choice == '2' and Tic_Tac_Toe.b2 == '|+|':
            self.already_taken()
        elif player_choice == '2':
            Tic_Tac_Toe.x2 = 1
            Tic_Tac_Toe.b1 = '\ /'
            Tic_Tac_Toe.b2 = ' X '
            Tic_Tac_Toe.b3 = '/ \\'
        elif player_choice == '3' and Tic_Tac_Toe.c2 == ' X ' or player_choice == '3' and Tic_Tac_Toe.c2 == '|+|':
            self.already_taken()
        elif player_choice == '3':
            Tic_Tac_Toe.x3 = 1
            Tic_Tac_Toe.c1 = '\ /'
            Tic_Tac_Toe.c2 = ' X '
            Tic_Tac_Toe.c3 = '/ \\'
        elif player_choice == '4' and Tic_Tac_Toe.a5 == ' X ' or player_choice == '4' and Tic_Tac_Toe.a5 == '|+|':
            self.already_taken()
        elif player_choice == '4':
            Tic_Tac_Toe.x4 = 1
            Tic_Tac_Toe.a4 = '\ /'
            Tic_Tac_Toe.a5 = ' X '
            Tic_Tac_Toe.a6 = '/ \\'
        elif player_choice == '5' and Tic_Tac_Toe.b5 == ' X ' or player_choice == '5' and Tic_Tac_Toe.b5 == '|+|':
            self.already_taken()
        elif player_choice == '5':
            Tic_Tac_Toe.x5 = 1
            Tic_Tac_Toe.b4 = '\ /'
            Tic_Tac_Toe.b5 = ' X '
            Tic_Tac_Toe.b6 = '/ \\'
        elif player_choice == '6' and Tic_Tac_Toe.c5 == ' X ' or player_choice == '6' and Tic_Tac_Toe.c5 == '|+|':
            self.already_taken()
        elif player_choice == '6':
            Tic_Tac_Toe.x6 = 1
            Tic_Tac_Toe.c4 = '\ /'
            Tic_Tac_Toe.c5 = ' X '
            Tic_Tac_Toe.c6 = '/ \\'
        elif player_choice == '7' and Tic_Tac_Toe.a8 == ' X ' or player_choice == '7' and Tic_Tac_Toe.a8 == '|+|':
            self.already_taken()
        elif player_choice == '7':
            Tic_Tac_Toe.x7 = 1
            Tic_Tac_Toe.a7 = '\ /'
            Tic_Tac_Toe.a8 = ' X '
            Tic_Tac_Toe.a9 = '/ \\'
        elif player_choice == '8' and Tic_Tac_Toe.b8 == ' X ' or player_choice == '8' and Tic_Tac_Toe.b8 == '|+|':
            self.already_taken()
        elif player_choice == '8':
            Tic_Tac_Toe.x8 = 1
            Tic_Tac_Toe.b7 = '\ /'
            Tic_Tac_Toe.b8 = ' X '
            Tic_Tac_Toe.b9 = '/ \\'
        elif player_choice == '9' and Tic_Tac_Toe.c8 == ' X ' or player_choice == '9' and Tic_Tac_Toe.c8 == '|+|':
            self.already_taken()
        elif player_choice == '9':
            Tic_Tac_Toe.x9 = 1
            Tic_Tac_Toe.c7 = '\ /'
            Tic_Tac_Toe.c8 = ' X '
            Tic_Tac_Toe.c9 = '/ \\'
        self.pr_r()
        if Tic_Tac_Toe.a2 == Tic_Tac_Toe.b2 == Tic_Tac_Toe.c2 or Tic_Tac_Toe.a5 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.c5:
            print('You won')
            input()
            quit()
        elif Tic_Tac_Toe.a8 == Tic_Tac_Toe.b8 == Tic_Tac_Toe.c8 or Tic_Tac_Toe.a2 == Tic_Tac_Toe.a5 == Tic_Tac_Toe.a8:
            print('You won')
            input()
            quit()
        elif Tic_Tac_Toe.b2 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.b8 or Tic_Tac_Toe.c2 == Tic_Tac_Toe.c5 == Tic_Tac_Toe.c8:
            print('You won')
            input()
            quit()
        elif Tic_Tac_Toe.a2 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.c8 or Tic_Tac_Toe.a8 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.c2:
            print('You won')
            input()
            quit()
        player_choice = input()
        if player_choice == '1' and Tic_Tac_Toe.a2 == ' X ' or player_choice == '1' and Tic_Tac_Toe.a2 == '|+|':
            self.already_taken()
        elif player_choice == '1':
            Tic_Tac_Toe.x1 = 1
            Tic_Tac_Toe.a1 = ' - '
            Tic_Tac_Toe.a2 = '|+|'
            Tic_Tac_Toe.a3 = ' - '
        elif player_choice == '2' and Tic_Tac_Toe.b2 == ' X ' or player_choice == '2' and Tic_Tac_Toe.b2 == '|+|':
            self.already_taken()
        elif player_choice == '2':
            Tic_Tac_Toe.x2 = 1
            Tic_Tac_Toe.b1 = ' - '
            Tic_Tac_Toe.b2 = '|+|'
            Tic_Tac_Toe.b3 = ' - '
        elif player_choice == '3' and Tic_Tac_Toe.c2 == ' X ' or player_choice == '3' and Tic_Tac_Toe.c2 == '|+|':
            self.already_taken()
        elif player_choice == '3':
            Tic_Tac_Toe.x3 = 1
            Tic_Tac_Toe.c1 = ' - '
            Tic_Tac_Toe.c2 = '|+|'
            Tic_Tac_Toe.c3 = ' - '
        elif player_choice == '4' and Tic_Tac_Toe.a5 == ' X ' or player_choice == '4' and Tic_Tac_Toe.a5 == '|+|':
            self.already_taken()
        elif player_choice == '4':
            Tic_Tac_Toe.x4 = 1
            Tic_Tac_Toe.a4 = ' - '
            Tic_Tac_Toe.a5 = '|+|'
            Tic_Tac_Toe.a6 = ' - '
        elif player_choice == '5' and Tic_Tac_Toe.b5 == ' X ' or player_choice == '5' and Tic_Tac_Toe.b5 == '|+|':
            self.already_taken()
        elif player_choice == '5':
            Tic_Tac_Toe.x5 = 1
            Tic_Tac_Toe.b4 = ' - '
            Tic_Tac_Toe.b5 = '|+|'
            Tic_Tac_Toe.b6 = ' - '
        elif player_choice == '6' and Tic_Tac_Toe.c5 == ' X ' or player_choice == '6' and Tic_Tac_Toe.c5 == '|+|':
            self.already_taken()
        elif player_choice == '6':
            Tic_Tac_Toe.x6 = 1
            Tic_Tac_Toe.c4 = ' - '
            Tic_Tac_Toe.c5 = '|+|'
            Tic_Tac_Toe.c6 = ' - '
        elif player_choice == '7' and Tic_Tac_Toe.a8 == ' X ' or player_choice == '7' and Tic_Tac_Toe.a8 == '|+|':
            self.already_taken()
        elif player_choice == '7':
            Tic_Tac_Toe.x7 = 1
            Tic_Tac_Toe.a7 = ' - '
            Tic_Tac_Toe.a8 = '|+|'
            Tic_Tac_Toe.a9 = ' - '
        elif player_choice == '8' and Tic_Tac_Toe.b8 == ' X ' or player_choice == '8' and Tic_Tac_Toe.b8 == '|+|':
            self.already_taken()
        elif player_choice == '8':
            Tic_Tac_Toe.x8 = 1
            Tic_Tac_Toe.b7 = ' - '
            Tic_Tac_Toe.b8 = '|+|'
            Tic_Tac_Toe.b9 = ' - '
        elif player_choice == '9' and Tic_Tac_Toe.c8 == ' X ' or player_choice == '9' and Tic_Tac_Toe.c8 == '|+|':
            self.already_taken()
        elif player_choice == '9':
            Tic_Tac_Toe.x9 = 1
            Tic_Tac_Toe.c7 = ' - '
            Tic_Tac_Toe.c8 = '|+|'
            Tic_Tac_Toe.c9 = ' - '
        self.pr_r()
        if Tic_Tac_Toe.a2 == Tic_Tac_Toe.b2 == Tic_Tac_Toe.c2 or Tic_Tac_Toe.a5 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.c5:
            print('You won')
            input()
            quit()
        elif Tic_Tac_Toe.a8 == Tic_Tac_Toe.b8 == Tic_Tac_Toe.c8 or Tic_Tac_Toe.a2 == Tic_Tac_Toe.a5 == Tic_Tac_Toe.a8:
            print('You won')
            input()
            quit()
        elif Tic_Tac_Toe.b2 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.b8 or Tic_Tac_Toe.c2 == Tic_Tac_Toe.c5 == Tic_Tac_Toe.c8:
            print('You won')
            input()
            quit()
        elif Tic_Tac_Toe.a2 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.c8 or Tic_Tac_Toe.a8 == Tic_Tac_Toe.b5 == Tic_Tac_Toe.c2:
            print('You won')
            input()
            quit()


round = Tic_Tac_Toe()
round.turn_x()
round.turn_x()
round.turn_x()
round.turn_x()
round.turn_x()
round.turn_x()
round.turn_x()
round.turn_x()
up vote 17 down vote accepted

You have many problems within your code, including:

  • Meaningless variable names (why, for example, is the user input named aaa?!);
  • Repetition;
  • Inconsistent whitespace;
  • Repetition;
  • Compound statements (the call the pa() should be on a separate line); and
  • Repetition.

I'd strongly recommend reading Python's style guide and following its guidance. However, your fundamental problem is that you're trying to write the game logic using the same structures you use for presenting the outcome - you don't need to.

Instead, note that the information you actually need to hold for the logic could look something like:

board = [[None, None,  'X'],
         [ 'O', None,  'X'],
         [None, None,  'O']]

This is a single, mutable structure, which can be easily passed around through various functions. You can then print out the current state based on this, using e.g. str.format:

# template for the board display

TEMPLATE = '''
              { }|{ }|{ }
              { }|{ }|{ }
              { }|{ }|{ }
              ---+---+---
              { }|{ }|{ }
              { }|{ }|{ }
              { }|{ }|{ }
              ---+---+---
              { }|{ }|{ }
              { }|{ }|{ }
              { }|{ }|{ }
'''

# how to display a single character

X_TOP = r'\ /'
X_MID = r' X '
X_BOT = r'/ \\'

...

def display(board):
    """Format the template according to the board state."""
    ...

Note that I've used multiline strings (''') for the template, to handle multiple lines, and raw (r'') strings for the components, to avoid escaping (most of!) the backslashes.

A further step could be to create a Board class, which holds both the current state (as an instance attribute) and the display functionality (as the __str__ method). However, I think OOP might be too much at this point.

  • Unless Python3.x is different you still can't end raw strings with backslashes, a fact I've only found out recently. Also why not make the character representation a raw multiline string? – SuperBiasedMan Oct 16 '15 at 8:40
  • 1
    @SuperBiasedMan ack, you're right; thanks. I figured it would be easier to insert each line separately, there's no easy way (AFAIK) to do multiple lines neatly. – jonrsharpe Oct 16 '15 at 9:08

jonrsharpe's answer is fantastic. I'm just posting to correct a misunderstanding of the pass keyword.

def pa():
    print('Already taken')
    pass

pass does nothing here. Technically, that's always what it does but it doesn't even need to do nothing in this case. pass is mostly used to deal with the fact that Python raises SyntaxErrors if you leave out a block of code, for example:

if value1:
    some_function()
elif value2:

elif value3:
    some_function(arg)

The above code will raise an error because Python expects something to happen after elif value2:, but if you're in the process of writing a script and want to test around this, you could add pass. That way there is valid code in the block, but it's code that just doesn't do anything anyway.

In your case, I suspect you thought that you needed to use it to end the function somehow, or indicate that the user's input made no change, but it does neither of those things. Removing it will have your function behave exactly the same.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.