【Python】贪吃蛇 —— 无聊必备的小项目

简介: 贪吃蛇是一款经典的单机游戏,最早于1976年问世,是由一位俄罗斯程序员创造的。游戏的主要设定是控制一条蛇在一个地图上移动,并不断吃食物。每吃到一颗食物,蛇的身体就会增长一节。游戏会随着时间的推移变得越来越难,需要玩家不断调整操作方式和思路,才能够在游戏中存活更久时间甚至创造高分记录。在游戏中,蛇可以通过键盘或手柄来控制移动方向。而地图上则会出现各种糖果或其他食物,蛇吃下这些食物的同时,也需要避免自己碰到自己的身体或碰到地图中的墙壁,否则就会导致游戏结束。

前言
贪吃蛇是一款经典的单机游戏,最早于1976年问世,是由一位俄罗斯程序员创造的。游戏的主要设定是控制一条蛇在一个地图上移动,并不断吃食物。每吃到一颗食物,蛇的身体就会增长一节。游戏会随着时间的推移变得越来越难,需要玩家不断调整操作方式和思路,才能够在游戏中存活更久时间甚至创造高分记录。

    在游戏中,蛇可以通过键盘或手柄来控制移动方向。而地图上则会出现各种糖果或其他食物,蛇吃下这些食物的同时,也需要避免自己碰到自己的身体或碰到地图中的墙壁,否则就会导致游戏结束。

    贪吃蛇也成为了许多游戏公司甚至平台的必备元素之一,很多手机游戏和拼图游戏里都有它的身影。它不仅是一个经典的单机游戏,更是人们童年或者青年时期的美好回忆。

本篇文章主要使用了PyGame模块


PyGame模块
Pygame是一款为Python程序员封装的2D游戏开发库,它基于SDL库开发,并使得游戏开发变得简便易行。Pygame为游戏开发者提供了一组易于使用的API和工具,使得创建游戏变得愉快和简单。下面是Pygame中一些常用的模块和函数:

pygame.init(): 初始化Pygame模块。
pygame.quit(): 关闭Pygame模块。
pygame.display.set_mode(): 创建一个新的显示窗口。
pygame.display.update(): 更新显示。
pygame.time.Clock(): 创建一个新的时钟对象。
pygame.time.Clock().tick(): 控制游戏的帧率。
pygame.event.get(): 获取游戏中发生的所有事件。
pygame.event.get().type: 获取事件类型。
pygame.surface.blit(): 将一个表面绘制到另一个表面上。
pygame.image.load(); 加载一个图像文件。
除了上述常用的模块以外,Pygame还提供了很多其他的模块来帮助游戏开发者构建自己的游戏,例如:

pygame.mouse: 用于获取鼠标的状态。
pygame.font: 用于使用字体。
pygame.mixer: 用于创建和播放声音或音频文件。
pygame.sprite: 用于管理游戏中的精灵。
pygame.transform: 用于转换图像的大小、旋转等。
总体来说,Pygame是一款非常实用且易于使用的游戏开发库,可以帮助开发者快速开发出自己的2D游戏。

贪吃蛇源码

# -*- coding: utf-8 -*-

import random
import sys
import time
import pygame
from pygame.locals import *
from collections import deque


SCREEN_WIDTH = 600      # 屏幕宽度
SCREEN_HEIGHT = 480     # 屏幕高度
SIZE = 20               # 小方格大小
LINE_WIDTH = 1          # 网格线宽度

# 游戏区域的坐标范围
SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)

# 食物的分值及颜色
FOOD_STYLE_LIST = [(10, (255, 100, 100)), (20, (100, 255, 100)), (30, (100, 100, 255))]

LIGHT = (100, 100, 100)
DARK = (200, 200, 200)      # 蛇的颜色
BLACK = (0, 0, 0)           # 网格线颜色
RED = (200, 30, 30)         # 红色,GAME OVER 的字体颜色
BGCOLOR = (40, 40, 60)      # 背景色


def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
    imgText = font.render(text, True, fcolor)
    screen.blit(imgText, (x, y))


# 初始化蛇
def init_snake():
    snake = deque()
    snake.append((2, SCOPE_Y[0]))
    snake.append((1, SCOPE_Y[0]))
    snake.append((0, SCOPE_Y[0]))
    return snake


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


def get_food_style():
    return FOOD_STYLE_LIST[random.randint(0, 2)]


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption('贪吃蛇')

    font1 = pygame.font.SysFont('SimHei', 24)  # 得分的字体
    font2 = pygame.font.Font(None, 72)  # GAME OVER 的字体
    fwidth, fheight = font2.size('GAME OVER')

    # 如果蛇正在向右移动,那么快速点击向下向左,由于程序刷新没那么快,向下事件会被向左覆盖掉,导致蛇后退,直接GAME OVER
    # b 变量就是用于防止这种情况的发生
    b = True

    # 蛇
    snake = init_snake()
    # 食物
    food = create_food(snake)
    food_style = get_food_style()
    # 方向
    pos = (1, 0)

    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
                        snake = init_snake()
                        food = create_food(snake)
                        food_style = get_food_style()
                        pos = (1, 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[1]:
                        pos = (0, -1)
                        b = False
                elif event.key in (K_s, K_DOWN):
                    if b and not pos[1]:
                        pos = (0, 1)
                        b = False
                elif event.key in (K_a, K_LEFT):
                    if b and not pos[0]:
                        pos = (-1, 0)
                        b = False
                elif event.key in (K_d, K_RIGHT):
                    if b and not pos[0]:
                        pos = (1, 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 not game_over:
            curTime = time.time()
            if curTime - last_move_time > speed:
                if not pause:
                    b = True
                    last_move_time = curTime
                    next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
                    if next_s == food:
                        # 吃到了食物
                        snake.appendleft(next_s)
                        score += food_style[0]
                        speed = orispeed - 0.03 * (score // 100)
                        food = create_food(snake)
                        food_style = get_food_style()
                    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, food_style[1], (food[0] * SIZE, food[1] * 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}')

        if game_over:
            if start:
                print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)

        pygame.display.update()


if __name__ == '__main__':
    main()

image.png

目录
相关文章
|
4天前
|
数据采集 存储 架构师
上进计划 | Python爬虫经典实战项目——电商数据爬取!
在如今这个网购风云从不间歇的时代,购物狂欢持续不断,一年一度的“6.18年中大促”、“11.11购物节”等等成为了网购电商平台的盛宴。在买买买的同时,“如何省钱?”成为了大家最关心的问题。 比价、返利、优惠券都是消费者在网购时的刚需,但在这些“优惠”背后已产生灰色地带。
|
1月前
|
机器学习/深度学习 存储 网络架构
Python 智能项目:6~10(5)
Python 智能项目:6~10(5)
38 0
|
1月前
|
机器学习/深度学习 存储 TensorFlow
Python 智能项目:1~5(5)
Python 智能项目:1~5(5)
34 0
|
28天前
|
存储 Python
Python实战项目(十三)使用 Tkinter GUI 库构建闹钟应用程序
Python实战项目(十三)使用 Tkinter GUI 库构建闹钟应用程序
20 0
|
4天前
|
数据可视化 数据挖掘 定位技术
Python实践项目
Python实践项目
19 2
|
20天前
|
SQL Java 编译器
使用pypy来提升你的python项目性能
使用pypy来提升你的python项目性能
17 0
|
20天前
|
Python
python实现贪吃蛇小游戏(附源码)
python实现贪吃蛇小游戏(附源码)
25 0
|
21天前
|
开发者 Python
解码pip:Python项目依赖的得力助手
解码pip:Python项目依赖的得力助手
10 0
|
27天前
|
机器学习/深度学习 Python
Python “贪吃蛇”游戏,在不断改进中学习pygame编程
Python “贪吃蛇”游戏,在不断改进中学习pygame编程
29 0
Python “贪吃蛇”游戏,在不断改进中学习pygame编程
|
28天前
|
传感器 机器人 C++
ROS 2机器人编程实战:基于现代C++和Python 3实现简单机器人项目
ROS 2机器人编程实战:基于现代C++和Python 3实现简单机器人项目
35 0

相关产品

  • 云迁移中心