Site icon FSIBLOG

How to Fix an Index Error in My Snake Game

How to Fix an Index Error in My Snake Game

How to Fix an Index Error in My Snake Game

When I started building my own version of the classic Snake game using Python and Tkinter, I was pretty excited. But like any good coding adventure, it wasn’t long before I hit my first real wall an IndexError. Specifically:

IndexError: list index out of range

I wasn’t sure what I had done wrong. I was trying to randomly place food on the 10×10 grid, but the game would crash before even starting. It took me a bit of digging, but here’s what I found and how I fixed it.

The Problem

I was getting the error at this line in my code:

self.square_list[self.foody][self.foodx].config(bg='red')

This line is supposed to place the red-colored food square on a random cell. But for some reason, it was trying to access a cell that didn’t exist.

The Cause

The issue was with how I built the self.square_list. It’s a 2D list meant to represent the grid, where each row is a list of square widgets. But here’s the mistake I made:

for row, rowList in enumerate(self.game):
for column, columnEntry in enumerate(self.game):
square = tkinter.Label(self.screen, text=' ', relief='raised')
square.grid(row=row, column=column)
square.config(bg='black')
self.square_list[row].append(square) # This line fails!

The problem? I never actually initialized self.square_list[row]. I had created an empty list of rows but didn’t fill them in correctly.

The Fix

Here’s how I corrected the logic:

for row in range(10):
square_row = []
for column in range(10):
square = tkinter.Label(self.screen, text=' ', relief='raised')
square.grid(row=row, column=column)
square.config(bg='black')
square_row.append(square)
self.square_list.append(square_row)

By properly building each square_row and appending it to self.square_list, I made sure every [row][column] reference would actually exist.

Other Issues I Found and Fix

Direction Binding Were Broken

Initially, I wrote:

self.screen.bind('w', self.up())  # 

This actually calls the function right away instead of assigning it to the keypress. The fix:

self.screen.bind('w', lambda e: self.up())
self.screen.bind('s', lambda e: self.down())
self.screen.bind('a', lambda e: self.left())
self.screen.bind('d', lambda e: self.right())

Now the functions are only called when the player presses the keys.

Infinite Loop in __init__ Freezes GUI

Another major issue was using a while True: loop in the constructor:

while True:
time.sleep(self.delay)
self.update()

This blocked the GUI thread, causing the window to freeze. Instead, I used after() to schedule updates:

self.run_game()

def run_game(self):
self.update()
self.screen.after(int(self.delay * 1000), self.run_game)

Practice Functionalities I Added

Once the basics were stable, I added a few features to improve the game and sharpen my Python skills.

Game Over on Wall Collision

import tkinter.messagebox

if self.head.x > 9 or self.head.x < 0 or self.head.y > 9 or self.head.y < 0:
tkinter.messagebox.showinfo("Game Over", "You hit the wall!")
self.screen.destroy()

Game Over on Self-Collision

for segment in self.segments:
if self.head.x == segment.x and self.head.y == segment.y:
tkinter.messagebox.showinfo("Game Over", "You hit yourself!")
self.screen.destroy()

Score Tracking

In the constructor:

self.score = 0
self.score_label = tkinter.Label(self.screen, text="Score: 0", fg="white", bg="black")
self.score_label.grid(row=0, column=10)

And when food is eaten:

self.score += 1
self.score_label.config(text=f"Score: {self.score}")

Final Thought

Fixing the IndexError was just the beginning of making my Snake game run properly. Along the way, I learned how easy it is to accidentally misuse lists, how to properly bind keys in Tkinter, and why event-driven programming is critical in GUI development.

Exit mobile version