Hans
Hans

Reputation: 1

Python - OOP Tic Tac Toe

I'm writing a tic-tac-toe game for an assignment. It needs to use object-oriented programming.

My problem is to implement a method that checks if the board is full and restarts the game with the same players. I have already tried to iterate through the playing field, checking if all fields are full but with no success.

I have also some trouble with promote the winning player and promote the previous player if he selects an occupied field. I think i need to change the for loop in my main function to keep track of the player or the turn but i have no clue how.

class Player(object):
    def __init__(self, name, symbol, initial_score=0):
        self.name= name
        self.symbol= symbol
        self.score= initial_score

    def won_match(self):
        self.score+= 100

    def lost_match(self):
        self.score-= 50

    def show_score(self):
        print('Player {}: {} points'.format(self.name, self.score))

class PlayingField(object):
    def __init__(self):
        self.field= [
                     [None, None, None],
                     [None, None, None],
                     [None, None, None]
                    ]

    def show_field(self):
        for row in self.field:
            for player in row:
                print('_' if player is None else player.symbol,end=' ')
            print()

    def set_player(self, x, y, player):
        if self.field[y][x] is not None:
            return False

        self.field[y][x]= player

        return True

    def full_board(self):
    for row in self.field:
        for col in row:
            if col is None:
                return False
        return True

    def check_won(self, x, y, player):
    if self.field[0][x] == player and self.field[1][x] == player and self.field[2][x] == player:
        return True
    elif self.field[y][0] == player and self.field[y][1] == player and self.field[y][2] == player:
        return True
    elif self.field[0][0] == player and  self.field[1][1] == player and self.field[2][2] == player:
        return True
    elif self.field[0][2] == player and  self.field[1][1] == player and  self.field[2][0] == player:
        return True
    else:
        return False


def main():
    name_1= input('Name of Player 1: ')
    name_2= input('Name of Player 2: ')

    players= [
              Player(name_1, 'X'),
              Player(name_2, 'O')
              ]

    field= PlayingField()

    while True:
        for player in players:
            field.show_field()

            x= int(input('Player {} choose your column: '.format(player.name))) - 1

            y= int(input('Player {} choose your row: '.format(player.name))) - 1

            if not field.set_player(x, y, player):
                print('That field is already occupied.')

            elif field.full_board():
            field.show_field()
            print('full board')
            for player in players:
                print('{}: {}'.format(player.name, player.score))
            field= PlayingField()

            elif field.check_won(player):
                field.show_field()
                print('Player {} won the game.'.format(player.name))
                print('Score')
                for player in players:
                    if field.check_won(player) == True:
                        player.won_match()
                    elif field.check_won(player) == False:
                        player.lost_match()
                    print('{}: {}'.format(player.name, player.score))
                field= PlayingField()

if __name__ == '__main__':
    main()

Upvotes: 0

Views: 4635

Answers (1)

chatton
chatton

Reputation: 596

In order to check to see if the board is full, we just need to iterate through every element and check for a non-None value.

you currently have

def full_board(self):
    for row in self.field:
        for col in self.field:
            if col == '_':
                return False
            else:
                return True

remember, self.field is a list of lists. What we want to do is examine all of the elements in all three lists.

def full_board(self):
    for row in self.field: # all good so far
        for col in row: # <-- now we're iterating through each list in self.field
        if col is None:
            return False   # the board is not full if there's at least one empty space
    return True  # we looked at every element and they were all occupied

your mistake was returning too early. In your version, you check one element, then determine a True/False value based on that. In order to check all of the elements, you need to return True after the for loop.

As for the validation of chosen location, all you need to do is continuously prompt until a position is valid.

in your while loop, you could have something like this

x, y = prompt_for_position()

while not pos_is_valid(x,y):
    x, y = prompt_for_position()

# now we can be sure that the chosen position is valid

Here, prompt_for_position can just ask the user for an x/y, and pos_is_valid can take in an x and y and tells you if it's a valid position. (i.e. None/Empty square)

Hopefully this was useful for you!

Upvotes: 1

Related Questions