Reputation: 13
I am currently trying to program a connect 4 game and I have came across a bug where for some reason it will continue on to the Players 2 turn if Player 1 make an invalid move. I was wondering if there is a way to loop the code until Player 1 makes a valid turn and then proceed to Player 2 as normal.
I have tried a while loop on the checking whos turn it is but it gets stuck in a constant loop and crashes. I attached the code I have with my attempt in how to make it work.
I am using Pygame for the graphical portion of the program.
EDIT: I reverted my code back to the original but with simple while loops. I also attached the is_valid() and the main().
# Graphical representation of dropping the piece
def draw_drop_piece(event, turn):
game_over = False
while turn == 0: # Checks to See if its Player 1 Turn
posx = event.pos[0]
col = int(math.floor(posx / SQUARESIZE))
if is_valid(board, col): # Checks Every Turn if Where the Player is Putting Their Piece is Valid
row = next_open_row(board, col)
drop_piece(board, row, col, 1)
if winning_move(board, 1): # Checks Every Turn if the Player Won
label = FONT.render("PLAYER 1 WINS!", 1, RED)
screen.blit(label, (40, 10))
game_over = True
break
break
else:
label = FONT.render("Enter Valid Spot", 1, BLUE)
screen.blit(label, (40, 10))
while turn != 0:
posx = event.pos[0]
col = int(math.floor(posx / SQUARESIZE))
if is_valid(board, col): # Checks Every Turn if Where the Player is Putting Their Piece is Valid
row = next_open_row(board, col)
drop_piece(board, row, col, 2)
if winning_move(board, 2): # Checks Every Turn if the Player Won
label = FONT.render("PLAYER 2 WINS!", 1, YELLOW)
screen.blit(label, (40, 10))
game_over = True
break
break
else:
label = FONT.render("Enter Valid Spot", 1, BLUE)
screen.blit(label, (40, 10))
return game_over
def is_valid(board, col):
return board[ROW_COUNT - 1][col] == 0
if __name__ == '__main__':
pygame.init()
board = create_board() # Creates Board
print_board(board) # Prints Board
game_over = False # The Game Isn't Over as it Just Started
turn = 0 # Player One Starts First
FONT = pygame.font.SysFont("monospace", 75)
width = COLUMN_COUNT * SQUARESIZE
height = (ROW_COUNT + 1) * SQUARESIZE
size = (width, height)
screen = pygame.display.set_mode(size)
draw_board(board)
pygame.display.update()
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT: # Exiting the game
sys.exit()
track_mouse()
if event.type == pygame.MOUSEBUTTONDOWN:
pygame.draw.rect(screen, BLACK, (0, 0, width, SQUARESIZE))
game_over = draw_drop_piece(turn)
print_board(board)
draw_board(board)
# This makes sure the turn indicator alternates between 1 and 0
turn = (turn + 1) % 2
if game_over:
pygame.time.wait(5000)
Upvotes: 0
Views: 169
Reputation: 104722
Your function needs to be able to return three values, not just the two it returns currently. It needs to signal if the game was won, if it is still ongoing after the move, or if the move was invalid and the turn is not completed yet.
I'm not sure if this is the best approach, but returning None
from the function instead of True
or False
might work if you add special case logic to the calling code:
game_over = draw_drop_piece(turn)
print_board(board)
draw_board(board)
if game_over is not None: # don't change turns if the attempted move was invalid
turn = (turn + 1) % 2
The while
loop doesn't actually need changing because None
is falsey, just like the actual False
value.
Here's the change needed in draw_drop_piece
:
if is_valid(board, col):
... # this part all stays the same
else:
label = FONT.render("Enter Valid Spot", 1, BLUE)
screen.blit(label, (40, 10))
game_over = None # signal an invalid move
Upvotes: 1
Reputation: 93
Try structuring something like I did below. That way in the while loop you disable anything having to do with the other player by stating that player2 is false.
player1 = True
player2 = True
while player1:
player2 = False
Upvotes: 0