Skip to content
Advertisement

Cannot Change Individual Elements in an Array

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
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement