Reputation: 57
This is a small problem, been working on a snake game in python, it's not complete yet and there's just one thing I would like to know. I originally had the code pygame.draw.rect(SCREEN, GREEN, (x_pos[i], y_pos[i], WIDTH, HEIGHT))
in the move_snake function. The code drew the snake just fine while I had it like that, however now I'm trying to grow the snake, so I've moved it into the for loop in the grow_snake function. It won't draw the snake anymore, however it still exists apparently as if I press the keys it will eventually hit a border and end the game. Just want to know why it won't draw the snake anymore. Thank you. I'm a noob at programming so if you want to look through the code and give me tips on how to improve it, that would be much appreciated. Keep in mind this is a work in progress so there are many obvious segments to the game that are missing that I will add in later.
# Snake game
import pygame
import random
pygame.init()
pygame.display.set_caption("Snake Game and AI")
WIDTH = 24
HEIGHT = 24
SCREEN = pygame.display.set_mode((500, 500))
RED = (255, 0, 0)
BLACK = (0, 0, 0)
GREEN = (0, 128, 0)
WHITE = (255, 255, 255)
SPEED = 25
x_head = 251
y_head = 251
direction = None
apple_x = random.randrange(26, 476, 25)
apple_y = random.randrange(26, 476, 25)
length = 0
x_pos = [x_head]
y_pos = [y_head]
def grid():
for x in range(25, 500, 25):
pygame.draw.rect(SCREEN, WHITE, (x, 25, 1, 450))
for y in range(25, 500, 25):
pygame.draw.rect(SCREEN, WHITE, (25, y, 450, 1))
def press_key():
global direction
global keys
if keys[pygame.K_RIGHT] and direction != 'left':
direction = 'right'
if keys[pygame.K_LEFT] and direction != 'right':
direction = 'left'
if keys[pygame.K_UP] and direction != 'down':
direction = 'up'
if keys[pygame.K_DOWN] and direction != 'up':
direction = 'down'
def move_snake():
global x_head
global y_head
global SCREEN
global WIDTH
global HEIGHT
if direction == 'right':
x_head += SPEED
if direction == 'left':
x_head -= SPEED
if direction == 'up':
y_head -= SPEED
if direction == 'down':
y_head += SPEED
def eat_apple():
global apple_x
global apple_y
global length
if x_head == apple_x and y_head == apple_y:
apple_x = random.randrange(26, 476, 25)
apple_y = random.randrange(26, 476, 25)
if direction == 'right':
pass
if direction == 'left':
pass
if direction == 'up':
pass
if direction == 'down':
pass
length += 1
pygame.draw.rect(SCREEN, RED, (apple_x, apple_y, WIDTH, HEIGHT))
def grow_snake():
move_snake()
global x_pos
global y_pos
for i in range(length):
pygame.draw.rect(SCREEN, GREEN, (x_pos[i], y_pos[i], WIDTH, HEIGHT))
def game_over():
global is_running
if x_head < 26 or x_head > 456 or y_head < 26 or y_head > 456:
is_running = False
is_running = True
while is_running:
pygame.time.delay(150)
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
keys = pygame.key.get_pressed()
press_key()
move_snake()
SCREEN.fill(BLACK)
grid()
grow_snake()
eat_apple()
game_over()
pygame.display.update()
pygame.quit()
Upvotes: 3
Views: 736
Reputation: 210908
You don't need x_head
, y_head
and length
at all. The position of the snake is stored in the lists x_pos
and y_pos
, use it:
(zip()
aggregates the elements of a list)
def grow_snake():
for x, y in zip(x_pos, y_pos):
pygame.draw.rect(SCREEN, GREEN, (x, y, WIDTH, HEIGHT))
If you want to know the length of the snake the you can get it by the length of the lists (e.g. len(x_pos
).
To move the snake, compute the new position of the head, add the new position at the head of the lists and remove the tail of the list
def move_snake():
global SCREEN, WIDTH, HEIGHT, x_pos, y_pos
# compute new head
x_head, y_head = x_pos[0], y_pos[0]
if direction == 'right':
x_head += SPEED
if direction == 'left':
x_head -= SPEED
if direction == 'up':
y_head -= SPEED
if direction == 'down':
y_head += SPEED
# add new head at head of lists
x_pos = [x_head] + x_pos
y_pos = [y_head] + y_pos
# delete tail of snake
del x_pos[-1]
del y_pos[-1]
If you eat an apple the add a new element at the tail of the snake:
def eat_apple():
global apple_x, apple_y, x_pos, y_pos
if x_pos[0] == apple_x and y_pos[0] == apple_y:
apple_x = random.randrange(26, 476, 25)
apple_y = random.randrange(26, 476, 25)
x_pos.append(x_pos[-1])
y_pos.append(y_pos[-1])
pygame.draw.rect(SCREEN, RED, (apple_x, apple_y, WIDTH, HEIGHT))
Code without x_head
, y_head
and length
:
# Snake game
import pygame
import random
pygame.init()
pygame.display.set_caption("Snake Game and AI")
WIDTH = 24
HEIGHT = 24
SCREEN = pygame.display.set_mode((500, 500))
RED = (255, 0, 0)
BLACK = (0, 0, 0)
GREEN = (0, 128, 0)
WHITE = (255, 255, 255)
SPEED = 25
direction = None
apple_x = random.randrange(26, 476, 25)
apple_y = random.randrange(26, 476, 25)
x_pos = [251]
y_pos = [251]
def grid():
for x in range(25, 500, 25):
pygame.draw.rect(SCREEN, WHITE, (x, 25, 1, 450))
for y in range(25, 500, 25):
pygame.draw.rect(SCREEN, WHITE, (25, y, 450, 1))
def press_key():
global direction
global keys
if keys[pygame.K_RIGHT] and direction != 'left':
direction = 'right'
if keys[pygame.K_LEFT] and direction != 'right':
direction = 'left'
if keys[pygame.K_UP] and direction != 'down':
direction = 'up'
if keys[pygame.K_DOWN] and direction != 'up':
direction = 'down'
def move_snake():
global SCREEN, WIDTH, HEIGHT, x_pos, y_pos
x_head, y_head = x_pos[0], y_pos[0]
if direction == 'right':
x_head += SPEED
if direction == 'left':
x_head -= SPEED
if direction == 'up':
y_head -= SPEED
if direction == 'down':
y_head += SPEED
x_pos = [x_head] + x_pos
y_pos = [y_head] + y_pos
del x_pos[-1]
del y_pos[-1]
def eat_apple():
global apple_x, apple_y, x_pos, y_pos
if x_pos[0] == apple_x and y_pos[0] == apple_y:
apple_x = random.randrange(26, 476, 25)
apple_y = random.randrange(26, 476, 25)
x_pos.append(x_pos[-1])
y_pos.append(y_pos[-1])
pygame.draw.rect(SCREEN, RED, (apple_x, apple_y, WIDTH, HEIGHT))
def grow_snake():
for x, y in zip(x_pos, y_pos):
pygame.draw.rect(SCREEN, GREEN, (x, y, WIDTH, HEIGHT))
def game_over():
global is_running
if x_pos[0] < 26 or x_pos[0] > 456 or y_pos[0] < 26 or y_pos[0] > 456:
is_running = False
is_running = True
while is_running:
pygame.time.delay(150)
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
keys = pygame.key.get_pressed()
press_key()
move_snake()
SCREEN.fill(BLACK)
grid()
grow_snake()
eat_apple()
game_over()
pygame.display.update()
pygame.quit()
Upvotes: 1
Reputation: 132
In your code you initialise the length
to 0
. Take this simplified code for example, that shows your problem clearly.
length = 0
for i in range(length):
print(i)
This snippet produces no output, as range
gives all integers up to, but not inclusive of, the stop
parameter.
To fix your issue, change your range
to range(length+1)
.
The Code Review site is the proper place to get improvement suggestions on working code. You'll get advice on things like performance, commenting, readability and style.
Keep in mind a suggestion you might get there is to refactor your code and initialise length
to 1
. Although 0
might be handy for list indexing, it doesn't accurately reflect how long the snake is, and sometimes leads to problems like the one you have in this question.
Upvotes: 0