Home > Mobile >  Checking multiple indexes in a list python 3.8
Checking multiple indexes in a list python 3.8

Time:02-27

I'm making a tic tac toe game and I need a way to check winning conditions. I made an if statement to check if X has 3 in a row, but for some reason I can't reach a winning condition. I can have this X| |X but when I try to fill in the blank it tells me that I can't do that.

tiles = [1, 2, 3, 4, 5, 6, 7, 8, 9]
tiles_str = ("1", "2", "3", "4", "5", "6", "7", "8", "9")

global turn_count
turn_count = 0


def board():
  divider = "-----"
  play_board = str(tiles[0])   "|"   str(tiles[1])   "|"   str(tiles[2])
  play_board_1 = str(tiles[3])   "|"   str(tiles[4])   "|"   str(tiles[5])
  play_board_2 = str(tiles[6])   "|"   str(tiles[7])   "|"   str(tiles[8])
  
  print(play_board)
  print(divider)
  print(play_board_1)
  print(divider)
  print(play_board_2)

while True:

  def Turn_X():
    board()
    x_turn = input("X take your turn: ")
    if x_turn in tiles_str:
      x_turn = int(x_turn)
      if x_turn in tiles:
        if isinstance(tiles[x_turn], int):
          global turn_count
          turn_count = turn_count 1
          tiles[x_turn -1] = "X"
          if turn_count < 9:
            Turn_O()
        else:
          print("Not an option")
          Turn_X()
      else:
        print("Not an option")
        Turn_X()
    else:
      print("Not an option")
      Turn_X()

  def Turn_O():
    board()
    o_turn = input("O take your turn: ")
    if o_turn in tiles_str:
      o_turn = int(o_turn)
      if o_turn in tiles:
        if isinstance(tiles[o_turn], int):
          global turn_count
          turn_count = turn_count 1
          tiles[o_turn -1] = "O"
          print(turn_count)
          Turn_X()
        else:
          print("Not an option")
          Turn_O()
      else:
        print("Not an option")
        Turn_O()
    else:
      print("Not an option")
      Turn_O()
  if turn_count >= 9:
    board()
    print("\nDraw")
    break
    
  if tiles[0] == "X" and tiles[1] == "X" and tiles[2] == "X":
    print("X wins")
    break
  
  Turn_X()
  

This is what I have for my game so far. I don't know if it's interfering with something else because I didn't have this issue before hand.

CodePudding user response:

  x_turn = int(x_turn)
  if x_turn in tiles:
    if isinstance(tiles[x_turn], int):

Python lists are zero-indexed. If the player entered 3, you're checking tiles[3] which is actually the fourth square.

CodePudding user response:

Your architecture has some issues. Don't define functions inside a while loop; prepare all your functions at the front, then USE them.

Don't use recursion for retrying an input. That's wasteful. Instead, use a while loop.

Note that the X and O functions are practically identical. Just use the same code and pass the letter.

Your code only checked for a top line. There's no reason to check X and O separately; just check whether the set of three are identical to each other.

This works:

def board():
  divider = "-----"
  play_board   = f"{tiles[0]}|{tiles[1]}|{tiles[2]}"
  play_board_1 = f"{tiles[3]}|{tiles[4]}|{tiles[5]}"
  play_board_2 = f"{tiles[6]}|{tiles[7]}|{tiles[8]}"
  
  print(play_board)
  print(divider)
  print(play_board_1)
  print(divider)
  print(play_board_2)

def Turn(xo):
    board()
    while True:
        turn = input(xo   " take your turn: ")
        if not "1" <= turn <= "9":
            print( "Not an option." )
            continue
        turn = int(turn)-1
        if isinstance(tiles[turn], int):
              tiles[turn] = xo
              if turn_count < 9:
                  return
        print("Not an option")

def checkdraw(tiles):
    return not any(isinstance(i,int) for i in tiles)

def checkwin(tiles):
    if tiles[0] == tiles[1] == tiles[2]:
        return tiles[0]
    if tiles[3] == tiles[4] == tiles[5]:
        return tiles[3]
    if tiles[6] == tiles[7] == tiles[8]:
        return tiles[6]
    if tiles[0] == tiles[3] == tiles[6]:
        return tiles[0]
    if tiles[1] == tiles[4] == tiles[7]:
        return tiles[1]
    if tiles[2] == tiles[5] == tiles[8]:
        return tiles[2]
    if tiles[0] == tiles[4] == tiles[8]:
        return tiles[4]
    if tiles[2] == tiles[4] == tiles[6]:
        return tiles[4]
    return False

tiles = [1, 2, 3, 4, 5, 6, 7, 8, 9]
turn_count = 0
while True:
    Turn('X')
    turn_count = turn_count 1
    if checkdraw(tiles):
        print("Draw")
        board()
        break
    if checkwin(tiles):
        print("X wins!")
        board()
        break

    Turn('O')
    turn_count = turn_count 1
    if checkdraw(tiles):
        print("Draw")
        board()
        break
    if checkwin(tiles):
        print("O wins!")
        board()
        break

One cute optimization:

def checkwin(tiles):
    for l in (
        (0,1,2),(3,4,5),(6,7,8),
        (0,3,6),(1,4,7),(2,5,8),
        (0,4,8),(2,4,6)
    ):
        if tiles[l[0]] == tiles[l[1]] == tiles[l[2]]:
            return tiles[l[0]]
    return False

CodePudding user response:

Sorry but there is too much wrong to fix it without changing everything. You only check if x won when you have set all 9 fields. Check it before you call turn_o or turn_x.

Look for try: and except: and custom error class instead of the 3 if statements. You can print a break line with \n so you have one variable instead of 4 to print your field and you can do this for example: field = f"{str(tiles[0])}|" And you have much code duplication which you could fix when you use functions with parameters

  • Related