I am trying to make a tic-tac-toe game, and I currently have a 3×3 tiled board
grid to represent the game. When a user clicks a square, the program sets board[x][y]
to 1
.
board = [[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Unfortunately, whenever I click a tile, it seems to ignore whatever x
value I put; every time I click a tile, it sets the entire row instead of a single tile. So, essentially, if I set board[0][y]
to 1
, it will set board[0][y]
, board[1][y]
, and board[2][y]
all to 1
.
I tried to create a minimal reproducible example, but when I took out the drawing function game
, (and set the board
variable to a 3×3 grid of 0s manually) the program failed to change the last two rows of board
upon clicking on what would have been a tile.
# tic-tac-toe import pygame windowsize = (300, 300) length = 3 # length, width of the array width = 3 kx = windowsize[0] // length # the size of a tile ky = windowsize[1] // length pygame.init() win = pygame.display.set_mode(windowsize) win.fill((255,255,255)) inPlay = True debug = True board = [] firstrun = True if debug: width = length * 2 length = 3 # this function takes the board and draws the game. # it's purpose is solely for visuals. def game(flash): # Initialize grid for first time global board if flash == True: # Fill board with 0s board = [] line = [] for i in range(length): line.append(0) for i in range(length): board.append(line) # Draw grid. for i in range(length): for j in range(length): # Draw X/O tiles r = pygame.Rect((i * kx + 1, j * ky + 1), (kx - 2, ky - 2)) colour = (255,255,255) if board[i][j] == 1: colour = (0,0,0) #elif board[i][j] == 2: # colour = (255,255,0) pygame.draw.rect(win, colour, r) #pygame.draw.line(win, (255,0,0), (i * kx, 0), (i * kx, 2 ** 20), width) #pygame.draw.line(win, (255,0,0), (0, i * ky), (2 ** 20, i * ky), width) while inPlay: pygame.time.delay(10) win.fill((5,255,255)) game(firstrun) firstrun = False for event in pygame.event.get(): if event.type == pygame.QUIT: inPlay = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: inPlay = False if event.type == pygame.MOUSEBUTTONDOWN: clickPos = pygame.mouse.get_pos() # find tile coordinates by dividing by 100 x = clickPos[0] // kx y = clickPos[1] // ky board[0][y] = 1 if debug: print(str(x), str(y)) print (board) print(clickPos) pygame.display.update() pygame.quit()
Advertisement
Answer
Actually, you don’t create a grid, you create a list of references to the same line. To create a grid you need 2 nested loops:
def game(flash): # Initialize grid for first time global board if flash == True: # Fill board with 0s board = [] for i in range(length): line = [] for j in range(length): line.append(0) board.append(line) # [...]
Or even shorter (see List Comprehensions):
def game(flash): # Initialize grid for first time global board if flash == True: # Fill board with 0s board = [[0] * length for _ in range(length)] # [...]
Also, there seems to be a typo in your code:
board[0][y] = 1
board[x][y] = 1