Related
i made a function to check if there is a win in my socket tic tac toe game, the problem is, its to hard to read.
Is there a way i can make it more simple? i thought about for loops but i think it wont be right in my case
if board[0][0] == board[1][0] and board[1][0] == board[2][0]:
if board[0][0] == 'X':
client_sockets[0].send("you win")
client_sockets[1].send("you lose")
else:
client_sockets[1].send("you win")
client_sockets[0].send("you lose")
if board[0][1] == board[1][1] and board[1][1] == board[2][1]:
if board[0][1] == 'X':
client_sockets[0].send("you win")
client_sockets[1].send("you lose")
else:
client_sockets[1].send("you win")
client_sockets[0].send("you lose")
if board[0][2] == board[1][2] and board[1][2] == board[2][2]:
if board[0][0] == 'X':
client_sockets[0].send("you win")
client_sockets[1].send("you lose")
else:
client_sockets[1].send("you win")
client_sockets[0].send("you lose")
and so on...
this is a very cool project that uses sockets - https://github.com/Suvoo/TicTacToe-Using-Socket-Server
try this snippet snippet:
import random
class TicTacToe:
def __init__(self):
self.board = []
def create_board(self):
for i in range(3):
row = []
for j in range(3):
row.append('-')
self.board.append(row)
def get_random_first_player(self):
return random.randint(0, 1)
def fix_spot(self, row, col, player):
self.board[row][col] = player
def is_player_win(self, player):
win = None
n = len(self.board)
# checking rows
for i in range(n):
win = True
for j in range(n):
if self.board[i][j] != player:
win = False
break
if win:
return win
# checking columns
for i in range(n):
win = True
for j in range(n):
if self.board[j][i] != player:
win = False
break
if win:
return win
# checking diagonals
win = True
for i in range(n):
if self.board[i][i] != player:
win = False
break
if win:
return win
win = True
for i in range(n):
if self.board[i][n - 1 - i] != player:
win = False
break
if win:
return win
return False
for row in self.board:
for item in row:
if item == '-':
return False
return True
def is_board_filled(self):
for row in self.board:
for item in row:
if item == '-':
return False
return True
def swap_player_turn(self, player):
return 'X' if player == 'O' else 'O'
def show_board(self):
for row in self.board:
for item in row:
print(item, end=" ")
print()
def start(self):
self.create_board()
player = 'X' if self.get_random_first_player() == 1 else 'O'
while True:
print(f"Player {player} turn")
self.show_board()
# taking user input
row, col = list(
map(int, input("Enter row and column numbers to fix spot: ").split()))
print()
# fixing the spot
self.fix_spot(row - 1, col - 1, player)
# checking whether current player is won or not
if self.is_player_win(player):
print(f"Player {player} wins the game!")
break
# checking whether the game is draw or not
if self.is_board_filled():
print("Match Draw!")
break
# swapping the turn
player = self.swap_player_turn(player)
# showing the final view of board
print()
self.show_board()
# starting the game
tic_tac_toe = TicTacToe()
tic_tac_toe.start()
more info
You could encode the current state of the board in a string instead of a nested list.
So for example,
board = [['O', 'X', ''], ['O', 'X', ''], ['X', 'X', '']]
could also be encoded as:
sboard = "OX OX XX "
(Replacing all the list by tuples would also work.)
Next, you write two functions:
def xwins():
client_sockets[0].send("you win")
client_sockets[1].send("you lose")
def owins():
client_sockets[1].send("you win")
client_sockets[0].send("you lose")
Finally, you create a dictionary of all game ending boards.
This is possible because strings are hashable, and can therefore be used as dictionary keys.
victory = {
"OX OX XX ": xwins,
"OX OX OX ": ywins,
# et cetera
}
Note how we reference the functions, but do not call them here.
After every move, you create a new sboard string, based on the old one and user input.
If the board is a winning move, you call the correct function via the dictionary:
if sboard in victory:
victory[sboard]()
exit_game()
# else continue playing.
There is a bug in your 3rd condition under if board[0][2] == 'X'..., you checking checking if board[0][0] == 'X'.
This highlights why all this code duplication is error prone. Hence the DRY principle.
When you have repeated code like this, think 'indirection'. Data structures and meta-data are the key to writing generic code that doesn't repeat itself.
For example, lets say you have a list of coordinate triplets that correspond to the 8 "lines" of your tic-tac-toe board. You could loop through this list and only implement the condition once using the coordinate triplets:
winCoords = [ [(0,0),(0,1),(0,2)],
[(1,0),(1,1),(1,2)],
[(2,0),(2,1),(2,2)],
[(0,0),(1,0),(2,0)],
[(0,1),(1,1),(2,1)],
[(0,2),(1,2),(2,2)],
[(0,0),(1,1),(2,2)],
[(0,2),(1,1),(2,0)] ]
for (r0,c0),(r1,c1),(r2,c2) in winCoords:
if board[r0][c0] == board[r1][c1] == board[r2][c2]:
winner,loser = (1,0) if board[r0][c0] == "X" else (0,1)
client_sockets[winner].send("you win")
client_sockets[loser].send("you lose")
break
Note that your sample code doesn't describe how you handle unplayed lines where all 3 values will be equal but neither "X" nor "O", which would seemingly result in a winning condition for 'O' (unless the default values are all distinct)
I am a little confused on how parameters work and calling functions with return statements. I am trying to create a new graph from the old one so that if I play again it will start over. I have tried copying the list in the run function and printing it out but it seems as though the new values are being placed in the old list. I also believe that my check_win function could be simplified greatly although I am not sure how to do so.
graph = [[' ', '|', ' ', '|', ' '],
['-','+', '-', '+', '-'],
[' ', '|', ' ', '|', ' '],
['-', '+', '-', '+', '-'],
[' ', '|', ' ', '|', ' ']]
def draw_graph(new_graph):
for row in new_graph:
for col in row:
print(col, end = '')
print()
def play_game():
again = 'yes'
while again == 'yes':
new_graph = graph
draw_graph(new_graph)
won = False
current_player = 'player1'
while not won:
pos = input("Which spot do you want to place your piece (1-9)? ")
if current_player == 'player1':
symbol = 'X'
elif current_player == 'player2':
symbol = 'O'
place_spot(pos, symbol, new_graph)
draw_graph(new_graph)
won = check_win(new_graph)
current_player = flip_player(current_player)
print("Thank you for playing.")
again = input("Do you want to play again? (yes/no) ")
def place_spot(pos, symbol, new_graph):
answer = ''
while answer != 'good':
if pos == '1':
new_graph[0][0] = symbol
break
if pos == '2':
new_graph[0][2] = symbol
break
if pos == '3':
new_graph[0][4] = symbol
break
if pos == '4':
new_graph[2][0] = symbol
break
if pos == '5':
new_graph[2][2] = symbol
break
if pos == '6':
new_graph[2][4] = symbol
break
if pos == '7':
new_graph[4][0] = symbol
break
if pos == '8':
new_graph[4][2] = symbol
break
if pos == '9':
new_graph[4][4] = symbol
break
else:
print("Please enter a number (1-9).")
def check_win(new_graph):
#top row win
if new_graph[0][0] == 'X' and new_graph[0][2] == 'X' and new_graph[0][4] == 'X':
print(f"Player 1 wins!")
won = True
return won
#middle row win
elif new_graph[2][0] == 'X' and new_graph[2][2] == 'X' and new_graph[2][4] == 'X':
print(f"Player 1 wins!")
won = True
return won
#bottom row win
elif new_graph[4][0] == 'X' and new_graph[4][2] == 'X' and new_graph[4][4] == 'X':
print(f"Player 1 wins!")
won = True
return won
#left diagonal win
elif new_graph[0][0] == 'X' and new_graph[2][2] == 'X' and new_graph[4][4] == 'X':
print(f"Player 1 wins!")
won = True
return won
#right diagonal win
elif new_graph[0][4] == 'X' and new_graph[2][2] == 'X' and new_graph[4][0] == 'X':
print(f"Player 1 wins!")
won = True
return won
#Player 2
#top row win
elif new_graph[0][0] == 'O' and new_graph[0][2] == 'O' and new_graph[0][4] == 'O':
print(f"Player 2 wins!")
won = True
return won
#middle row win
elif new_graph[2][0] == 'O' and new_graph[2][2] == 'O' and new_graph[2][4] == 'O':
print(f"Player 2 wins!")
won = True
return won
#bottom row win
elif new_graph[4][0] == 'O' and new_graph[4][2] == 'O' and new_graph[4][4] == 'O':
print(f"Player 2 wins!")
won = True
return won
#left diagonal win
elif new_graph[0][0] == 'O' and new_graph[2][2] == 'O' and new_graph[4][4] == 'O':
print(f"Player 2 wins!")
won = True
return won
#right diagonal win
elif new_graph[0][4] == 'O' and new_graph[2][2] == 'O' and new_graph[4][0] == 'O':
print(f"Player 2 wins!")
won = True
return won
def flip_player(player):
if player == 'player1':
current_player = 'player2'
return current_player
elif player == 'player2':
current_player = 'player1'
return current_player
play_game()
You can recursively copy a list using copy.deepcopy:
>>> x = [[1], [2], [3]]
>>> y = copy.copy(x) # a shallow copy
>>> y[0][0] = 5 # this modifies 'x[0]' as well
>>> x
[[5], [2], [3]]
>>> z = copy.deepcopy(x)
>>> z[0][0] = 9
>>> x
[[5], [2], [3]]
I'm not that new to programming, but I haven't tried making too many things without following a tutorial before. This is my first attempt at a REAL project without following a video or copy-pasting code. I created a simple tic tac toe game, it works fine if both players manually choose positions, but when I tried to implement a simple AI using the minimax algorithm, it will play all of the AI moves at once and I have no idea why.
I reviewed the code so many times but I can't figure out why the AI can keep placing pieces/making moves when the player can only make 1 move. According to the code, only 1 move at a time should be allowed. What is going on? When it gets to the AI's turn, the AI places pieces until it wins, no regard for turn or anything. Player pieces are placed too, which is strange because Player needs to be prompted for selection input. I think the problem lies in the minimax function itself, but I can't pinpoint where. Any help would be greatly appreciated! Thank you so much. Full file:
import random
from time import sleep
from math import inf
PLAYER = 0
AI = 1
BOARD = [[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' ']]
#AVAILABLE = [[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]]
AVAILABLE = [1,2,3,4,5,6,7,8,9]
SELECTION = 0
TURN = random.randint(0, 1)
def display_board(board):
print(f'\t[{board[0][0]}] [{board[0][1]}] [{board[0][2]}]\n\t[{board[1][0]}] [{board[1][1]}] [{board[1][2]}]\n\t[{board[2][0]}] [{board[2][1]}] [{board[2][2]}]')
def convert_position(available_locations, position):
if position in available_locations:
available_locations.remove(position)
position -= 1
converted = (position // 3, position % 3)
return converted
def is_valid_location(board):
pass
def place_piece(board, position, player):
a, b = position
if a in [0, 1, 2] and b in [0, 1, 2]:
if board[a][b] == ' ' and player == PLAYER:
board[a][b] = 'X'
if board[a][b] == ' ' and player == AI:
board[a][b] = 'O'
def clear_board(board):
board = [[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' ']]
return board
def is_win_player(board):
if board[0][0] != ' ' and board[0][1] == board[0][0] and board[0][2] == board[0][0]:
if board[0][0] == 'X':
return True
if board[1][0] != ' ' and board[1][1] == board[1][0] and board[1][2] == board[1][0]:
if board[1][0] == 'X':
return True
if board[2][0] != ' ' and board[2][1] == board[2][0] and board[2][2] == board[2][0]:
if board[2][0] == 'X':
return True
if board[0][0] != ' ' and board[1][1] == board[0][0] and board[2][2] == board[0][0]:
if board[0][0] == 'X':
return True
if board[2][0] != ' ' and board[1][1] == board[2][0] and board[0][2] == board[2][0]:
if board[2][0] == 'X':
return True
if board[0][0] != ' ' and board[1][0] == board[0][0] and board[2][0] == board[0][0]:
if board[0][0] == 'X':
return True
if board[0][1] != ' ' and board[1][1] == board[0][1] and board[2][1] == board[0][1]:
if board[0][1] == 'X':
return True
if board[0][2] != ' ' and board[1][2] == board[0][2] and board[2][2] == board[0][2]:
if board[0][2] == 'X':
return True
def is_win_ai(board):
if board[0][0] != ' ' and board[0][1] == board[0][0] and board[0][2] == board[0][0]:
if board[0][0] == 'O':
return True
if board[1][0] != ' ' and board[1][1] == board[1][0] and board[1][2] == board[1][0]:
if board[1][0] == 'O':
return True
if board[2][0] != ' ' and board[2][1] == board[2][0] and board[2][2] == board[2][0]:
if board[2][0] == 'O':
return True
if board[0][0] != ' ' and board[1][1] == board[0][0] and board[2][2] == board[0][0]:
if board[0][0] == 'O':
return True
if board[2][0] != ' ' and board[1][1] == board[2][0] and board[0][2] == board[2][0]:
if board[2][0] == 'O':
return True
if board[0][0] != ' ' and board[1][0] == board[0][0] and board[2][0] == board[0][0]:
if board[0][0] == 'O':
return True
if board[0][1] != ' ' and board[1][1] == board[0][1] and board[2][1] == board[0][1]:
if board[0][1] == 'O':
return True
if board[0][2] != ' ' and board[1][2] == board[0][2] and board[2][2] == board[0][2]:
if board[0][2] == 'O':
return True
def score_eval(board):
for row in range(0, 3):
if board[row][0] == board[row][1] and board[row][1] == board[row][2]:
if board[row][0] == 'O':
return 10
if board[row][0] == 'X':
return -10
for col in range(0, 3):
if board[0][col] == board[1][col] and board[1][col] == board[2][col]:
if board[row][0] == 'O':
return 10
if board[row][0] == 'X':
return -10
if board[0][0] == board[1][1] and board[1][1] == board[2][2]:
if board[0][0] == 'O':
return 10
if board[0][0] == 'X':
return -10
if board[2][0] == board[1][1] and board[1][1] == board[0][2]:
if board[2][0] == 'O':
return 10
if board[2][0] == 'X':
return -10
def is_tie(board):
counter = 0
for array in board:
for index in array:
if index == ' ':
counter += 1
if counter == 0:
return True
def is_terminal(board):
return is_tie(board) or is_win_player(board) or is_win_ai(board)
def minimax(board, depth, maximizingPlayer, available_positions):
valid_locations = available_positions
print(valid_locations)
terminal = is_terminal(board)
if depth == 0 or terminal:
if terminal:
if is_win_ai(board):
return None, 99999999
if is_win_player(board):
return None, -99999999
if is_tie(board):
return None, 1
else:
return None, score_eval(board)
if maximizingPlayer:
value = -inf
selection = random.choice(valid_locations)
for num in valid_locations:
board_copy = board.copy()
position = convert_position(valid_locations, num)
place_piece(board_copy, position, AI)
new_score = minimax(board_copy, depth-1, False, valid_locations)[1]
if new_score > value:
value = new_score
selection = num
return selection, value
else:
value = inf
selection = random.choice(valid_locations)
for num in valid_locations:
board_copy = board.copy()
position = convert_position(valid_locations, num)
place_piece(board_copy, position, PLAYER)
new_score = minimax(board_copy, depth-1, True, valid_locations)[1]
if new_score < value:
value = new_score
selection = num
return selection, value
while SELECTION != 'QUIT':
print('\t< Tic Tac Toe >\n')
print('\tPlease make a selection:')
print("\t'PLAY' to play a game")
print("\t'QUIT' to exit application\n")
SELECTION = input('> ').upper()
if SELECTION != 'QUIT' and SELECTION != 'PLAY':
print(SELECTION)
print('Please enter a valid selection.')
elif SELECTION == 'PLAY':
game_over = False
while not game_over:
display_board(BOARD)
if is_tie(BOARD):
print('Tie game. No winner.')
input('Press any key to continue...')
game_over = True
elif TURN == PLAYER:
print("Player's turn!")
position = int(input('Please enter a number 1 - 9 to make a mark: '))
selection = convert_position(AVAILABLE, position)
place_piece(BOARD, selection, PLAYER)
if is_win_player(BOARD):
print('Player has won the game!')
display_board(BOARD)
game_over = True
elif TURN == AI:
print("AI's turn!")
sleep(0.9)
x, y = minimax(BOARD, 7, True, AVAILABLE) #x = position, y = score
selection = convert_position(AVAILABLE, x)
place_piece(BOARD, selection, AI)
if is_win_ai(BOARD):
print('AI has won the game!')
display_board(BOARD)
game_over = True
TURN += 1
TURN = TURN % 2
print(AVAILABLE)
BOARD = clear_board(BOARD)
AVAILABLE = [1,2,3,4,5,6,7,8,9]
One of the possible culprits is the bit which attempts to "clone" the board in your minimax function:
board_copy = board.copy()
In Python, list.copy method returns a shallow copy of a list, which is essentially a new list with 3 elements which are references to the "rows" in your original board. Try using copy.deepcopy() documentation
import copy
...
board_copy = copy.deepcopy(board)
I want the computer playing with the player with until one of them scores 10 points:
from graphics import *
board=[[0,0,0],[0,0,0],[0,0,0]]#as bourd
window=GraphWin("Tic Tac Toe",700,700)
L0=Line(Point(250,50),Point(250,650)).draw(window)
L1=Line(Point(450,50),Point(450,650)).draw(window)
L2=Line(Point(50,250),Point(650,250))
L2.draw(window)
L3=Line(Point(50,450),Point(650,450))
L3.draw(window)
xTurn=True
num=0
while num<9:
b=window.getMouse()
pa,pb=int((b.x-50)/200)+1,int((b.y-50)/200)+1
if board[pb-1][pa-1]==0:
num+=1
if xTurn:
tex="X"
xTurn=False
else:
tex="O"
xTurn=True
h=Text(Point(pa*150+50*(pa-1),pb*150+50*(pb-1)),tex).draw(window)
h.setSize(36)
if xTurn:
h.setFill("blue")
board[pb-1][pa-1]=1
else:
h.setFill("red")
board[pb-1][pa-1]=2
if num>4:
if (board[0][0]==1 and board[0][1]==1 and board[0][2]==1) or(board[1][0]==1 and board[1][1]==1 and board[1][2]==1) or(board[2][0]==1 and board[2][1]==1 and board[2][2]==1):
print(" O is winner")
break
elif (board[0][0]==2 and board[0][1]==2 and board[0][2]==2) or(board[1][0]==2 and board[1][1]==2 and board[1][2]==2) or (board[2][0]==2 and board[2][1]==2 and board[2][2]==2):
print(" X is winner")
break
elif (board[0][0]==2 and board[1][0]==2 and board[2][0]==2) or(board[0][1]==2 and board[1][1]==2 and board[2][1]==2) or (board[0][2]==2 and board[1][2]==2 and board[2][2]==2):
print(" X is winner")
break
elif (board[0][0]==1 and board[1][0]==1 and board[2][0]==1) or(board[0][1]==1 and board[1][1]==1 and board[2][1]==1) or (board[0][2]==1 and board[1][2]==1 and board[2][2]==1):
print(" O is winner")
break
elif (board[0][0]==1 and board[1][1]==1 and board[2][2]==1) or(board[0][2]==1 and board[1][1]==1 and board[2][0]==1):
print(" O is winner")
break
elif (board[0][0]==2 and board[1][1]==2 and board[2][2]==2) or(board[0][2]==2 and board[1][1]==2 and board[2][0]==2):
print(" X is winner")
break
if num>=9:
print("There is no winner!")
I took your program apart and put it back together again to streamline it and allow it to play ten games before quitting. It prints the results of the ten games as it exits. This isn't exactly what you are after, but I believe gives you the tools you need to do what you want:
from graphics import *
from time import sleep
PLAYERS = ['Draw', 'O', 'X']
DRAW = PLAYERS.index('Draw')
COLORS = ['black', 'blue', 'red']
EMPTY = 0
window = GraphWin("Tic Tac Toe", 700, 700)
Line(Point(250, 50), Point(250, 650)).draw(window)
Line(Point(450, 50), Point(450, 650)).draw(window)
Line(Point(50, 250), Point(650, 250)).draw(window)
Line(Point(50, 450), Point(650, 450)).draw(window)
turn = PLAYERS.index('X')
scores = [0] * len(PLAYERS)
tokens = []
while sum(scores) < 10:
for token in tokens:
token.undraw()
board = [[EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY], [EMPTY, EMPTY, EMPTY]]
squares_played = 0
while squares_played < 9:
point = window.getMouse()
x, y = int((point.x - 50) / 200), int((point.y - 50) / 200)
if board[y][x] == EMPTY:
squares_played += 1
board[y][x] = turn
text = PLAYERS[turn]
token = Text(Point(200 * x + 150, 200 * y + 150), text)
token.setSize(36)
token.setFill(COLORS[turn])
token.draw(window)
tokens.append(token)
turn = len(PLAYERS) - turn
if squares_played > 4:
if EMPTY != board[0][0] == board[0][1] == board[0][2]:
print("{} is winner".format(PLAYERS[board[0][0]]))
scores[turn] += 1
break
elif EMPTY != board[1][0] == board[1][1] == board[1][2]:
print("{} is winner".format(PLAYERS[board[1][1]]))
scores[turn] += 1
break
elif EMPTY != board[2][0] == board[2][1] == board[2][2]:
print("{} is winner".format(PLAYERS[board[2][2]]))
scores[turn] += 1
break
elif EMPTY != board[0][0] == board[1][0] == board[2][0]:
print("{} is winner".format(PLAYERS[board[0][0]]))
scores[turn] += 1
break
elif EMPTY != board[0][1] == board[1][1] == board[2][1]:
print("{} is winner".format(PLAYERS[board[1][1]]))
scores[turn] += 1
break
elif EMPTY != board[0][2] == board[1][2] == board[2][2]:
print("{} is winner".format(PLAYERS[board[2][2]]))
scores[turn] += 1
break
elif EMPTY != board[0][0] == board[1][1] == board[2][2]:
print("{} is winner".format(PLAYERS[board[1][1]]))
scores[turn] += 1
break
elif EMPTY != board[0][2] == board[1][1] == board[2][0]:
print("{} is winner".format(PLAYERS[board[1][1]]))
scores[turn] += 1
break
if squares_played >= 9:
print("There is no winner!")
scores[DRAW] += 1
sleep(2)
for index, player in enumerate(PLAYERS):
print("{}: {}".format(player, scores[index]))
My rework relies on some parallel arrays, which is better than no arrays, but should evolve to a real data structure.
I'm in the process of writing a rudimentary Connect 4 game, with the board built into the command line, etc. My problem is that I cant get the code to execute past the 2nd elif statement. I set it up so that if a certain cell in the grid does not have an underscore, it should proceed to place the piece in the next row. However, the following move always only replaces whatever piece is in the cell in row 2. I've tried starting from rows other than the bottom 2 rows, just to try to troubleshoot, but it never gets past the 1st elif statement. Can anyone tell me where I'm going wrong with my elifs?
board = []
for x in range(0, 6):
board.append(["_"] * 7)
def print_board(board):
for i in range(1,7):
print(i, end=" ")
print(7)
for row in board:
print("|".join(row))
print_board(board)
for turn in range(42):
print('Turn', turn+1)
if turn % 2 == 0:
player1 = int(input('Player 1, choose your column: '))
while player1 not in range(1,8):
player1 = int(input('You must enter a column number from 1-7: '))
if board[5][player1-1] == '_':
board[5][player1-1] = 'O'
elif board[5][player1-1] != '_':
board[4][player1-1] = 'O'
elif board[4][player1-1] != '_':
board[3][player1-1] = 'O'
elif board[3][player1-1] != '_':
board[2][player1-1] = 'O'
elif board[2][player1-1] != '_':
board[1][player1-1] = 'O'
elif board[1][player1-1] != '_':
board[0][player1-1] = 'O'
print_board(board)
elif turn % 2 != 0:
player2 = int(input('Player 2, choose your column: '))
while player2 not in range(1,8):
player2 = int(input('You must enter a column number from 1-7: '))
if board[5][player2-1] == '_':
board[5][player2-1] = 'X'
elif board[5][player2-1] != '_':
board[4][player2-1] = 'X'
elif board[4][player2-1] != '_':
board[3][player2-1] = 'X'
elif board[3][player2-1] != '_':
board[2][player2-1] = 'X'
elif board[2][player2-1] != '_':
board[1][player2-1] = 'X'
elif board[1][player2-1] != '_':
board[0][player2-1] = 'X'
print_board(board)
You should test the cells using ==, not !=. Also, you should change the same cell you test on, not the one below it:
board = []
for x in range(0, 6):
board.append(["_"] * 7)
def print_board(board):
for i in range(1,7):
print(i, end=" ")
print(7)
for row in board:
print("|".join(row))
print_board(board)
for turn in range(42):
print('Turn', turn+1)
if turn % 2 == 0:
player1 = int(input('Player 1, choose your column: '))
while player1 not in range(1,8):
player1 = int(input('You must enter a column number from 1-7: '))
if board[5][player1-1] == '_':
board[5][player1-1] = 'O'
elif board[4][player1-1] == '_':
board[4][player1-1] = 'O'
elif board[3][player1-1] == '_':
board[3][player1-1] = 'O'
elif board[2][player1-1] == '_':
board[2][player1-1] = 'O'
elif board[1][player1-1] == '_':
board[1][player1-1] = 'O'
elif board[0][player1-1] == '_':
board[0][player1-1] = 'O'
print_board(board)
elif turn % 2 != 0:
player2 = int(input('Player 2, choose your column: '))
while player2 not in range(1,8):
player2 = int(input('You must enter a column number from 1-7: '))
if board[5][player2-1] == '_':
board[5][player2-1] = 'X'
elif board[4][player2-1] == '_':
board[4][player2-1] = 'X'
elif board[3][player2-1] == '_':
board[3][player2-1] = 'X'
elif board[2][player2-1] == '_':
board[2][player2-1] = 'X'
elif board[1][player2-1] == '_':
board[1][player2-1] = 'X'
elif board[0][player2-1] == '_':
board[0][player2-1] = 'X'
print_board(board)