Problems for player play order in Tic-tac-toe

Asked

Viewed 142 times

0

I have trouble with the job players(), because I can’t increment the variable n, the function is only returning "X". I know it sounds pretty simple, but I can’t identify the problem. Can anyone help me?

def players():
    n = 0
    if n % 2 == 0:
        n = n + 1
        return 'X'
    else:
        n = n + 1
        return 'O'

def play():
    gon = 0
    while gon != 9:
        pos = input('Insira a posição que deseja jogar: ')
        if pos == '1':
            paper[0][0] = players()
            gon += 1
        elif pos == '2':
            paper[1][0] = players()
            gon += 1
        elif pos == '3':
            paper[2][0] = players()
            gon += 1
        elif pos == '4':
            paper[3][0] = players()
            gon += 1
        elif pos == '5':
            paper[4][0] = players()
            gon += 1
        elif pos == '6':
            paper[5][0] = players()
            gon += 1
        elif pos == '7':
            paper[6][0] = players()
            gon += 1
        elif pos == '8':
            paper[7][0] = players()
            gon += 1
        elif pos == '9':
            paper[8][0] = players()
            gon += 1
        else:
            print('Dígito inválido! Tente novamente.')

        print(' %s | %s | %s ' % (paper[0][0],paper[1][0],paper[2][0]))
        print('-----------')
        print(' %s | %s | %s ' % (paper[3][0],paper[4][0],paper[5][0]))
        print('-----------')
        print(' %s | %s | %s ' % (paper[6][0],paper[7][0],paper[8][0]))
    if gon == 9:
        print('\n Empate!')

paper = [[' '],[' '],[' '],
         [' '],[' '],[' '],
         [' '],[' '],[' ']]

print('Bem-vindo ao Jogo da Velha!')
print('Cliente é X;')
print('Servidor é O.')
play()
  • 1

    Its function players() this setando every time the n zero, whenever it is called, that n = 0 can’t be in there

2 answers

4

The problem can be verified by making a simple table test in function players. Basically, it starts with n = 0, I mean, every time you call players(), the first thing she will do is set the value zero in the variable n. At all times, every time it’s called.

So you’ll always be in if. If you want the behavior to vary according to the value of n, then probably what you want is for the function to receive the value as parameter:

def players(n):
    if n % 2 == 0:
        return 'X'
    else:
        return 'O'

You can still simplify and improve some things in the code. For example, the function play:

def play():
    paper = [ ' ' ] * 9
    gon = 0
    n = 0
    while gon != 9:
        try:
            pos = int(input('Insira a posição que deseja jogar: '))
            if 1 <= pos <= 9:
                paper[pos - 1] = players(n)

                n = 1 - n # se n for 1, vira zero, se for zero, vira 1
                gon += 1

                for i in range(0, len(paper), 3):
                    print(' {} | {} | {} '.format(paper[i],paper[i + 1],paper[i + 2]))
                    if i < 6:
                        print('-----------')
            else:
                print('Valor deve estar entre 1 e 9')
        except ValueError:
            print('Valor inválido! Tente novamente.')

    if gon == 9:
        print('\n Empate!')

I convert the result of input to number using int (and if it’s not a number, it launches a ValueError, that I capture with except). And I only update the board if the position value is valid.

If the board is always the same, you can create it within the same function (I saw no sense in creating it outside, unless it could have varied size, then it could be a function parameter, for example).

I also made a "board" as a list with 9 positions. Of course being a list of lists (a "matrix") would be more "faithful", but leaving it as a simple list simplifies that lot of if's.

When printing the board, I used a range of 3 in 3, so it is possible to print each "line" of the "matrix" at once.


Of course you can improve more, because the code does not check if a position has already been occupied, does not make a fact check if there was a winner, etc. An example:

def players(n):
    if n % 2 == 0:
        return 'X'
    else:
        return 'O'

def jogo_terminou(tabuleiro):
    posicoes_vencedoras = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8], # horizontal
        [0, 3, 6], [1, 4, 7], [2, 5, 8], # vertical
        [0, 4, 8], [2, 4, 6] # diagonal
    ]
    # verifica todas as combinações de posições vencedoras
    for pos1, pos2, pos3 in posicoes_vencedoras:
        if tabuleiro[pos1] == tabuleiro[pos2] == tabuleiro[pos3] and tabuleiro[pos1] in ('X', 'O'):
            print(f'Temos um vencedor: {tabuleiro[pos1]}! Parabéns!') # mudei a mensagem para mostrar quem ganhou
            # se já encontrei um vencedor, posso retornar direto (não precisa continuar verificando as outras combinações)
            return True

    # não tem vencedor, verifica se todas as posições estão ocupadas (não preciso mais do contador de jogadas)
    if all(posicao in ('X', 'O') for posicao in tabuleiro):
        print('Deu velha! Ninguém ganhou.')
        return True

    # jogo ainda não terminou
    return False

def play():
    paper = [ ' ' ] * 9
    n = 0
    while True:
        try:
            pos = int(input('Insira a posição que deseja jogar: '))
            if 1 <= pos <= 9:
                if paper[pos - 1] == ' ': # verifica se posição não está ocupada
                    paper[pos - 1] = players(n)

                    n = 1 - n # se n for 1, vira zero, se for zero, vira 1

                    for i in range(0, len(paper), 3):
                        print(' {} | {} | {} '.format(paper[i],paper[i + 1],paper[i + 2]))
                        if i < 6:
                            print('-----------')
                else:
                    print('posição já ocupada')
            else:
                print('Valor deve estar entre 1 e 9')
        except ValueError:
            print('Valor inválido! Tente novamente.')

        if jogo_terminou(paper):
            break
  • Thank you, hkotsubo! (y). On confirmation that there is a winner or not, I made 6 boolean conditions according to the rows, columns and diagonals of the matrix I made. Thanks again!

  • @jmb2001 If the answer solved your problem, you can accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. And when I get 15 points, you can also vote in all the answers you found useful.

  • The condition that the value must be between 1 and 9 (occupied position) does not work. I thought to put an if of that position of the paper for False since it does not contain anything for now. But even so, tou in doubt.

  • @jmb2001 What exactly doesn’t work? Because "does not work" is very vague, the way I did works yes, because I tested it well before posting the code. What I think which may be the problem (or at least one of them) is that in this answer I changed the board to be a list with 9 positions (paper = [ ' ' ] * 9), but in his another question, in function winner you still consider it as a list list, and then of course it won’t work because it will be a list with 3 positions (and each position has another list with 3 positions). However I already commented there with a link...

  • ... this link, that has the function jogo_terminou, which checks if there is a winner (whereas the board is a list of 9 positions, which is what I am using in this code).

  • In this occupied position condition, I enter the value in position 1. When it is the other player’s turn, he inserts the value in position 1. Then the exchange happens, when it was to say that the position is already occupied.

  • 1

    @jmb2001 In the last paragraph of the answer: "Of course you can improve more, because the code does not check whether a position has already been occupied." - just make a if before entering the value in position (if already occupied, ask the user to type again, etc)

  • 1

    @jmb2001 Anyway, I added a code at the end of the reply with that check

  • Okay. Thank you!

  • Where do I say the problem was solved here in stackoverflow?

  • @jmb2001 That’s all accept the answer, just click on (If you can’t find it, see on the link).

  • @jmb2001 In addition to accepting the answer, you can also vote in it, if you have found it useful. In fact, as you already have more than 15 points, you can vote on any question or answer of the site

Show 7 more comments

1

Dear jmb2001, without wanting to modify much your program but seeking to simplify it I did it in the following way:

import os

def players(flag):

    if flag:
        return 'X'
    else:
        return 'O'

def play():
    flag = True
    gon = 0
    while gon != 9:
        os.system('clear')

        print(' %s | %s | %s ' % tuple(paper[0:3]))
        print('-----------')
        print(' %s | %s | %s ' % tuple(paper[3:6]))
        print('-----------')
        print(' %s | %s | %s ' % tuple(paper[6:9]))
        print()

        pos = input('Insira a posição que deseja jogar: ')
        if pos in 'qQ':
            exit(0)

        elif pos in '123456789':
                paper[int(pos)-1] = players(flag)
                gon += 1
                flag = not flag

        else:
            print('Dígito inválido! Tente novamente.')

    if gon == 9:
        print('\n Empate!')


paper = [' '] * 9 # copie do hkotsubo

print('Bem-vindo ao Jogo da Velha!')
print('Cliente é X;')
print('Servidor é O.')

play()

I thought it best to change the name of your control variable n to flag, which means flag in English because that’s what the flag variable does.

It works as a flip-flop changing its state each time the line ( flag = not flag ) runs.

I added the instruction os.system('clear') so that the screen is cleaned and the print’s always exit in the same positions of the terminal.

Also includes an option allowing the user to terminate the program by typing q or Q.

Finally I agree with hkotsubo about the fact that it remains to verify whether the position is already occupied or not and other things more.

But you’re on the right track, keep it up...

And be Happy

  • Just one detail, if you type in the position 12, or 23 or 3456 etc, will give error: https://ideone.com/NTmyJd

  • You are right. So to solve this problem just put the Try except instructions practically in the same positions as hkotsubo put

  • Thank you, Washington Luis!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.