Vlad
Vlad

Reputation: 45

How to fix a while loop in Python

I've seen that usually, the mistake occurs when you use while inside of a while loop, however, it's not the case here, so I'm asking for help with this "common" mistake

The following part of the code is not important, probably you can just ignore it

crd = ['1 3', '2 3', '3 3', '1 2', '2 2', '3 2', '1 1', '2 1', '3 1']
inp = list(input('Enter cells:'))
wins = 0
result = False


def field(val):
    print('---------')
    for i in range(0, 9, 3):
        print('| ' + '{} {} {}'.format(val[i], val[i+1], val[i+2]).replace('_', ' ') + ' |')
    print('---------')


def win(con):
    global wins
    global result
    if inp[0] == '_':
        result = 'Impossible'
    else:
        win_con = [[con[i], con[i+1], con[i+2]] for i in range(0, 9, 3)] \
                + [[con[i], con[i+3], con[i+6]] for i in range(0, 3, 1)]\
                + [[con[0], con[4], con[8]], [con[2], con[4], con[6]]]

        for i in win_con:
            if (set(i) == {'X'} or set(i) == {'O'}) and wins == 1:
                result = 'Impossible'
            elif set(i) == {'X'}:
                result = 'X wins'
                wins = 1
            elif set(i) == {'O'}:
                result = 'O wins'
                wins = 1

        if result == False:
            try:
                inp.index('_')
                result = 'Game not finished'
            except:
                result = 'Draw'
    print(result)


field(inp)

Bellow is the part of the code with a loop that returns Infinite loop mistake (as far as I understood the mistake is in def move() part

def move():
    move = input('Enter the coordinates:').split(' ')
    while True:
        for n in move:
            if int(n) not in range(1, 4):
                print('Coordinates should be from 1 to 3!')
                move = input('Enter the coordinates:').split(' ')
                continue
            elif int(n) in range(1, 4):
                move = ' '.join(move)
                break


while True:
    move()
    position = [p for p, x in enumerate(crd) if x == move]
    int_pos = int("".join([str(p) for p in position]))

    if inp[int_pos] == '0' or inp[int_pos] == 'X':
        print('This cell is occupied! Choose another one!')
        move()
    elif inp[int_pos] == '_':
        inp[int_pos] = 'X'
        field(inp)
        win(inp)
    if result:
        break

Somehow, once I even managed to fix the infinite loop mistake, nevertheless, a different issue occurred - after checking the first pair of coordinates (and showing that they are out of range) It took input for new pair of coordinates but still proceed to check old pair of coordinates that were already checked.

Upvotes: 0

Views: 243

Answers (1)

mojozinc
mojozinc

Reputation: 194

My guess is you are using function move just to input a valid coords right
you can simplify it as follows

def input_coordinates():
    while True:
        x, y = [int(i) for i in input('Enter the coordinates:').split(' ')]
        if (1 <= x < 4
              and 1 <= y < 4):
           return x, y
        # this will keep looping unless you get valid coordinates

Then you write you main like this

while True:
    x, y = input_coordinates()
    move = "{} {}".format(x, y) # formatting the way you expect it.
    position = [p for p, x in enumerate(crd) if x == move]
    int_pos = int("".join([str(p) for p in position]))

    if inp[int_pos] == '0' or inp[int_pos] == 'X':
        print('This cell is occupied! Choose another one!')
        continue
    elif inp[int_pos] == '_':
        inp[int_pos] = 'X'
        field(inp)
        win(inp)
    if result:
        break
  1. Try to avoid global variables,
  2. you also had a conflict you had string and function both with the name "move"
  3. you didn't need to add one more iteration (for n in move) in you original move() function

Upvotes: 1

Related Questions