Bumbo McPastry
Bumbo McPastry

Reputation: 57

(Python Snake game) For loop doesn't draw snake

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

Answers (2)

Rabbid76
Rabbid76

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

Noah
Noah

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

Related Questions