Python 100 líneas para implementar un simple juego de serpientes (con código)

1. Introducción al juego

Snake es un juego muy simple, adecuado para la práctica. Echemos un vistazo a mis capturas de pantalla del juego:

captura de pantalla del juego

Cómo jugar:
Tecla Enter: Iniciar el juego
Barra espaciadora: Pausa/Continuar
↑↓←→ Teclas de flecha o teclas WSAD: Controla la dirección del movimiento.

Hay tres tipos de alimentos: rojo, verde y azul, que corresponden a 10 puntos, 20 puntos y 30 puntos respectivamente. Cada vez que comas un alimento, aumentarás los puntos correspondientes. Cada vez que aumentes 100 puntos, el la velocidad aumentará en un nivel. No hay un punto de control establecido. Pronto, y luego GAME OVER.

2. Análisis del juego

El juego de la serpiente codiciosa es muy simple, aparece un punto al azar en la pantalla que indica "comida", controla el movimiento de la "serpiente" hacia arriba, abajo, izquierda y derecha, después de comer la "comida", el cuerpo de la "serpiente" se alarga, y la "serpiente" toca el marco o el propio cuerpo, el juego termina.

Primero analicemos a qué puntos se debe prestar atención al escribir este juego.

1. ¿Cómo se representan las serpientes?
Podemos dividir toda el área de juego en pequeñas cuadrículas. Un grupo de pequeñas cuadrículas conectadas entre sí forman una "serpiente". Podemos usar diferentes colores para representarlo. Como se muestra en la imagen de arriba, uso oscuro colores Indica el fondo, y el color claro indica "serpiente".

Podemos usar coordenadas para representar cada cuadrado pequeño, y se puede establecer el rango del eje X y el eje Y. Use una lista para almacenar las coordenadas del "cuerpo de serpiente", luego saldrá una "serpiente", y finalmente solo necesita mostrarse en diferentes colores.

2. ¿Cómo se mueve la serpiente?
La primera reacción es mover cada cuadrado pequeño hacia adelante un espacio como una lombriz de tierra, pero es muy difícil de realizar. Estaba atascado aquí desde el principio.

Imagina la serpiente codiciosa que hemos jugado. Cada vez que la "serpiente" se mueve, se siente como si avanzara como un todo. Excluye la "acción" de la "serpiente" en tu mente, y piensa cuidadosamente en la "serpiente" antes y después. después de moverse De hecho, a excepción de la cabeza y la cola, las otras partes no han cambiado en absoluto. Eso es fácil, agregar las coordenadas del siguiente espacio al principio de la lista y eliminar el último elemento de la lista es equivalente a mover la serpiente un espacio hacia adelante.

3. ¿Cómo determinar el final del juego?
Si la "serpiente" se mueve más allá del alcance del área de juego o se toca a sí misma, se considerará una pérdida. El rango de las coordenadas del eje está predeterminado y es fácil juzgar si excede el rango. Entonces, ¿cómo juzgas cuando te encuentras contigo mismo?

Si la imagen de la "serpiente" moviéndose en su mente es realmente difícil, pero en el código, nuestra "serpiente" es una lista, entonces solo necesitamos juzgar si las coordenadas de la siguiente cuadrícula están incluidas en la "serpiente". ¿No estará en la lista?

Con estas preguntas resueltas, podemos comenzar a codificar.

3. Implementación del código
Dado que el programa necesita agregar y eliminar con frecuencia la cabeza y la cola de la "serpiente", para un mejor rendimiento, usamos deque en lugar de list.

Primero, la "serpiente" debe inicializarse. La longitud inicial de la "serpiente" es 3, y la posición se encuentra en la esquina superior izquierda.

# 游戏区域的坐标范围
SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)
# 初始化蛇
snake = deque()
def _init_snake():
    snake.clear()
    snake.append((2, scope_y[0]))
    snake.append((1, scope_y[0]))
    snake.append((0, scope_y[0]))
创建“食物”,在屏幕内随机选取一个点作为“食物”,但是要保证“食物”不在“蛇”身上。
#食物
def create_food(snake):
    food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
    food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
    while (food_x, food_y) in snake:
        # 如果食物出现在蛇身上,则重来
        food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
        food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
    return food_x, food_y

El movimiento de la "serpiente" puede tener 4 direcciones, y se utiliza una tupla para representar la dirección del movimiento, cada vez que se presiona la tecla de dirección, se asigna el valor correspondiente a

# 方向
pos = (1, 0)

for event in pygame.event.get():
    if event.type == QUIT:
        sys.exit()
    elif event.type == KEYDOWN:
        if event.key in (K_w, K_UP):
            # 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER
            if pos[1]:
                pos = (0, -1)
        elif event.key in (K_s, K_DOWN):
            if pos[1]:
                pos = (0, 1)
        elif event.key in (K_a, K_LEFT):
            if pos[0]:
                pos = (-1, 0)
        elif event.key in (K_d, K_RIGHT):
            if pos[0]:
                pos = (1, 0)

El movimiento de la "serpiente" se puede expresar como:

next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
if next_s == food:
    # 吃到了食物
    snake.appendleft(next_s)
    food = create_food(snake)
else:
    if SCOPE_X[0] <= next_s[0] <= SCOPE_X[1] and SCOPE_Y[0] <= next_s[1] <= SCOPE_Y[1] and next_s not in snake:
        snake.appendleft(next_s)
        snake.pop()
    else:
        game_over = True

código completo

"""
贪吃蛇小游戏
"""
import random
import sys
import time
import pygame
from pygame.locals import *
from collections import deque
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 480
SIZE = 20
def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
    imgText = font.render(text, True, fcolor)
    screen.blit(imgText, (x, y))
def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption('贪吃蛇')
    light = (100, 100, 100)  # 蛇的颜色
    dark = (200, 200, 200)  # 食物颜色

    font1 = pygame.font.SysFont('SimHei', 24)  # 得分的字体
    font2 = pygame.font.Font(None, 72)  # GAME OVER 的字体
    red = (200, 30, 30)  # GAME OVER 的字体颜色
    fwidth, fheight = font2.size('GAME OVER')
    line_width = 1  # 网格线宽度
    black = (0, 0, 0)  # 网格线颜色
    bgcolor = (40, 40, 60)  # 背景色
    # 方向,起始向右
    pos_x = 1
    pos_y = 0
    # 如果蛇正在向右移动,那么快速点击向下向左,由于程序刷新没那么快,向下事件会被向左覆盖掉,导致蛇后退,直接GAME OVER
    # b 变量就是用于防止这种情况的发生
    b = True
    # 范围
    scope_x = (0, SCREEN_WIDTH // SIZE - 1)
    scope_y = (2, SCREEN_HEIGHT // SIZE - 1)
    # 蛇
    snake = deque()
    # 食物
    food_x = 0
    food_y = 0
    # 初始化蛇
    def _init_snake():
        nonlocal snake
        snake.clear()
        snake.append((2, scope_y[0]))
        snake.append((1, scope_y[0]))
        snake.append((0, scope_y[0]))
    # 食物
    def _create_food():
        nonlocal food_x, food_y
        food_x = random.randint(scope_x[0], scope_x[1])
        food_y = random.randint(scope_y[0], scope_y[1])
        while (food_x, food_y) in snake:
            # 为了防止食物出到蛇身上
            food_x = random.randint(scope_x[0], scope_x[1])
            food_y = random.randint(scope_y[0], scope_y[1])
    _init_snake()
    _create_food()
    game_over = True
    start = False  # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER
    score = 0  # 得分
    orispeed = 0.5  # 原始速度
    speed = orispeed
    last_move_time = None
    pause = False  # 暂停

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_RETURN:
                    if game_over:
                        start = True
                        game_over = False
                        b = True
                        _init_snake()
                        _create_food()
                        pos_x = 1
                        pos_y = 0
                        # 得分
                        score = 0
                        last_move_time = time.time()
                elif event.key == K_SPACE:
                    if not game_over:
                        pause = not pause
                elif event.key in (K_w, K_UP):
                    # 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER
                    if b and not pos_y:
                        pos_x = 0
                        pos_y = -1
                        b = False
                elif event.key in (K_s, K_DOWN):
                    if b and not pos_y:
                        pos_x = 0
                        pos_y = 1
                        b = False
                elif event.key in (K_a, K_LEFT):
                    if b and not pos_x:
                        pos_x = -1
                        pos_y = 0
                        b = False
                elif event.key in (K_d, K_RIGHT):
                    if b and not pos_x:
                        pos_x = 1
                        pos_y = 0
                        b = False

        # 填充背景色
        screen.fill(bgcolor)
        # 画网格线 竖线
        for x in range(SIZE, SCREEN_WIDTH, SIZE):
            pygame.draw.line(screen, black, (x, scope_y[0] * SIZE), (x, SCREEN_HEIGHT), line_width)
        # 画网格线 横线
        for y in range(scope_y[0] * SIZE, SCREEN_HEIGHT, SIZE):
            pygame.draw.line(screen, black, (0, y), (SCREEN_WIDTH, y), line_width)
        if game_over:
            if start:
                print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER',
                           red)
        else:
            curTime = time.time()
            if curTime - last_move_time > speed:
                if not pause:
                    b = True
                    last_move_time = curTime
                    next_s = (snake[0][0] + pos_x, snake[0][1] + pos_y)
                    if next_s[0] == food_x and next_s[1] == food_y:
                        # 吃到了食物
                        _create_food()
                        snake.appendleft(next_s)
                        score += 10
                        speed = orispeed - 0.03 * (score // 100)
                    else:
                        if scope_x[0] <= next_s[0] <= scope_x[1] and scope_y[0] <= next_s[1] <= scope_y[1] \
                                and next_s not in snake:
                            snake.appendleft(next_s)
                            snake.pop()
                        else:
                            game_over = True

        # 画食物
        if not game_over:
            # 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了
            pygame.draw.rect(screen, light, (food_x * SIZE, food_y * SIZE, SIZE, SIZE), 0)

        # 画蛇
        for s in snake:
            pygame.draw.rect(screen, dark, (s[0] * SIZE + line_width, s[1] * SIZE + line_width,
                                            SIZE - line_width * 2, SIZE - line_width * 2), 0)
        print_text(screen, font1, 30, 7, f'速度: {
      
      score // 100}')
        print_text(screen, font1, 450, 7, f'得分: {
      
      score}')
        pygame.display.update()
if __name__ == '__main__':
    main()

por fin

Para agradecer a los lectores, me gustaría compartir con ustedes algunos de mis productos secos de programación favoritos recientes, para retribuir a cada lector, y espero ayudarlos.
Hay un conjunto completo de información adecuada para principiantes ~ ¡
Ven y crece con Xiaoyu!
① Más de 100 libros electrónicos de Python (debe haber libros convencionales y clásicos disponibles)
② Información de la biblioteca estándar de Python (la versión china más completa)
③ Código fuente de proyectos de reptiles (cuarenta o cincuenta proyectos interesantes y clásicos de práctica manual y código fuente )
④ Introducción básica de Python, reptiles, desarrollo web y videos de análisis de big data (adecuados para principiantes)
⑤ Hoja de ruta de aprendizaje de Python (diga adiós al aprendizaje sin refinar)

material

Supongo que te gusta

Origin blog.csdn.net/Modeler_xiaoyu/article/details/128202301
Recomendado
Clasificación