Prosseguindo com o desafio de criar um snake game, vamos relembrar o código do tópico passado:
import pygame
import pygame.locals as pl
# Inicia pygame
pygame.init()
# Adiciona título à janela
pygame.display.set_caption('Snake')
# Seleciona o tamanho da tela
tela = pygame.display.set_mode((600, 500))
# Cria a cobra
snake = [(150, 150), (160, 150), (170, 150), (180, 150)]
snake_corpo = pygame.Surface((10, 10))
# Cria a maçã
apple = pygame.Surface((10, 10))
apple.fill((255, 0, 0))
apple_posicao = (300, 300)
while True:
# Recebe todos os eventos do jogador na tela
for event in pygame.event.get():
# Se o evento for QUIT, ao clicar no botão de quit, fecha o programa
if event.type == pl.QUIT:
pygame.quit()
# Muda a cor da tela para verde
tela.fill((93, 205, 84))
tela.blit(apple, apple_posicao)
for posicao in snake:
tela.blit(snake_corpo, posicao)
# Mantém a tela aberta
pygame.display.update()
Rodando o código acima nós temos a cobra estática e uma maçã numa posição fixa, que no meu grid eu defini que seria um ponto na posição (300, 300). Mas o jogo é dinâmico e a maçã não vai sempre aparecer na posição 300, 300. Aqui, para fazer com que a maçã apareça em locais aleatórios, vou usar a biblioteca random, mais especificamente a função choice.
A função choice da lib random pega um valor aleatório dentro de um iterável. Por exemplo:
In [1]: from random import choice
In [2]: choice([1, 2, 3, 4, 5])
Out[2]: 5
In [3]: choice([1, 2, 3, 4, 5])
Out[3]: 5
In [4]: choice([1, 2, 3, 4, 5])
Out[4]: 1
In [5]: choice([1, 2, 3, 4, 5])
Out[5]: 1
In [6]: choice([1, 2, 3, 4, 5])
Out[6]: 3
In [7]: choice([1, 2, 3, 4, 5])
Out[7]: 4
Então eu preciso criar um iterável que vai corresponder às possíveis posições dentro do meu grid nas quais a maçã poderá aparecer. Aqui, precisamos pensar um pouco.
Eu defini que cada parte da cobra irá ocupar um espaço de 10 x 10, e cada maçã terá o tamanho de 10 por 10.
Minha tela é do tamanho de 600 x 500. Então eu posso definir que meu grid de posições nos quais a maçã poderá aparecer é algo assim:
In [12]: x_grid = tuple(x for x in range(0, 590))
In [13]: y_grid = tuple(y for y in range(0, 490))
Agora, para que eu faça minha maçã aparecer no tabuleiro em posições aleatórias, eu posso trocar isto:
apple_posicao = (300, 300)
Por isto:
apple_pos = (choice(x_grid), choice(y_grid))
Vamos fazer uns testes para ver as possíveis posições da maçã:
In [24]: (choice(x_grid), choice(y_grid))
Out[24]: (79, 30)
In [25]: (choice(x_grid), choice(y_grid))
Out[25]: (27, 213)
In [26]: (choice(x_grid), choice(y_grid))
Out[26]: (217, 342)
In [27]: (choice(x_grid), choice(y_grid))
Out[27]: (389, 255)
In [28]: (choice(x_grid), choice(y_grid))
Out[28]: (402, 471)
Algo de podre por aqui.
Relembrem que minha cobra tem cada pedaço dela num tamanho de 10 por 10, e a maçã também. Se as posições da maçã não forem múltiplos de 10, é capaz de minha cobra não passar completamente por cima da maçã, o que geraria comportamentos como este:

Percebam que a cobra passa por cima mas não completamente por cima da maçã. E na lógica do jogo, para que a cobra coma a maçã, eu defini que a posição da cabeça da cobra seja igual à posição da maçã.
Para corrigir esse tipo de comportamento, como minha cobra só ocupa espaços múltiplos de 10 no meu grid, minha maçã só pode aparecer em posições múltiplas de 10 também. Então preciso corrigir meu grid:
In [29]: x_grid = tuple(x for x in range(0, 590) if x % 10 == 0)
In [30]: y_grid = tuple(y for y in range(0, 490) if y % 10 == 0)
In [31]: (choice(x_grid), choice(y_grid))
Out[31]: (540, 150)
In [32]: (choice(x_grid), choice(y_grid))
Out[32]: (330, 140)
In [33]: (choice(x_grid), choice(y_grid))
Out[33]: (80, 320)
In [34]: (choice(x_grid), choice(y_grid))
Out[34]: (420, 430)
Ou seja, eu só adicionei à minha tupla que representa o grid valores que divididos por 10 tenham resto igual a 0, ou seja, múltiplos de 10. Ao pedir tuplas com os valores de x e y, só obtivemos valores múltiplos de 10. Agora é possível que minha cobra passe por cima da maçã perfeitamente:

Portanto, adicionando mais esse pedaço de código ao nosso código original, o código todo está assim até o momento:
import pygame
import pygame.locals as pl
from random import choice
# Inicia pygame
pygame.init()
# Adiciona título à janela
pygame.display.set_caption('Snake')
# Seleciona o tamanho da tela
tela = pygame.display.set_mode((600, 500))
# Cria o grid
x_grid = tuple(x for x in range(0, 590) if x % 10 == 0)
y_grid = tuple(y for y in range(0, 490) if y % 10 == 0)
# Cria a cobra
snake = [(150, 150), (160, 150), (170, 150), (180, 150)]
snake_corpo = pygame.Surface((10, 10))
# Cria a maçã
apple = pygame.Surface((10, 10))
apple.fill((255, 0, 0))
apple_posicao = (choice(x_grid), choice(y_grid))
while True:
# Recebe todos os eventos do jogador na tela
for event in pygame.event.get():
# Se o evento for QUIT, ao clicar no botão de quit, fecha o programa
if event.type == pl.QUIT:
pygame.quit()
# Muda a cor da tela para verde
tela.fill((93, 205, 84))
tela.blit(apple, apple_posicao)
for posicao in snake:
tela.blit(snake_corpo, posicao)
# Mantém a tela aberta
pygame.display.update()
Rodando o código mais de uma vez podemos ver que nossa maçã já aparece em posições aleatórias:



Mas nossa cobra ainda não se mexe. No próximo tópico iremos fazer a cobra conseguir se movimentar e controlá-la usando as setas do teclado.