当前位置: 首页 > news >正文

Python 贪吃蛇

文章目录

  • 效果图:
  • 项目目录结构
    • main.py
    • game/apple.py
    • game/base.py
    • game/snake.py
    • constant.py

效果图:

请添加图片描述

项目目录结构

在这里插入图片描述

main.py

from snake.game.apple import Apple  # 导入苹果类
from snake.game.base import *  # 导入游戏基类
from snake.game.snake import Snake  # 导入蛇类class SnakeGame(GameBase):"""贪吃蛇游戏"""def __init__(self):"""初始化游戏"""super(SnakeGame, self).__init__(game_name=GAME_NAME, icon=ICON,  # 调用基类的初始化方法screen_size=SCREEN_SIZE,display_mode=DISPLAY_MODE,loop_speed=LOOP_SPEED,font_size=FONT_SIZE,background=WHITE,font_name=None)# 绘制背景self.prepare_background()# 创建游戏对象self.apple_count = 0  # 苹果计数器self.high_score = 0  # 记录最高分self.snake = Snake(self)  # 创建蛇对象self.apple = Apple(self)  # 创建苹果对象# 绑定按键事件self.add_key_binding(KEY_UP, self.snake.turn, direction=UP)  # 绑定上方向键self.add_key_binding(KEY_DOWN, self.snake.turn, direction=DOWN)  # 绑定下方向键self.add_key_binding(KEY_LEFT, self.snake.turn, direction=LEFT)  # 绑定左方向键self.add_key_binding(KEY_RIGHT, self.snake.turn, direction=RIGHT)  # 绑定右方向键self.add_key_binding(KEY_RESTART, self.restart)  # 绑定R键(重启游戏)self.add_key_binding(KEY_PAUSE, self.pause)  # 绑定R键(重启游戏)self.add_key_binding(KEY_EXIT, self.quit)  # 绑定退出键# 添加绘图函数self.add_draw_action(self.draw_score)  # 添加绘制分数的函数def prepare_background(self):"""准备背景"""self.background.fill(BACKGROUND_COLOR)  # 用背景颜色填充背景for _ in range(CELL_SIZE, SCREEN_WIDTH, CELL_SIZE):  # 绘制垂直网格线self.draw.line(self.background, GRID_COLOR, (_, 0), (_, SCREEN_HEIGHT))for _ in range(CELL_SIZE, SCREEN_HEIGHT, CELL_SIZE):  # 绘制水平网格线self.draw.line(self.background, GRID_COLOR, (0, _), (SCREEN_WIDTH, _))def restart(self):"""重启游戏"""if not self.snake.is_alive:  # 如果蛇已经死亡self.apple_count = 0  # 重置苹果计数器self.apple.drop()  # 重新放置苹果self.snake.restart_pawn()  # 重生蛇self.running = True  # 继续游戏循环def draw_score(self):"""绘制分数"""text = f"Apple: {self.apple_count}"  # 准备要绘制的文本self.high_score = max(self.high_score, self.apple_count)  # 更新最高分self.draw_text(text, (0, 0), (255, 255, 33))  # 绘制文本if not self.snake.is_alive:  # 如果蛇已经死亡self.draw_text(" 游戏结束 ", (SCREEN_WIDTH / 2 - 54, SCREEN_HEIGHT / 2 - 10),  # 绘制游戏结束文本(255, 33, 33), WHITE)self.draw_text(" 按R键重启 ", (SCREEN_WIDTH / 2 - 85, SCREEN_HEIGHT / 2 + 20),  # 绘制重启提示文本GREY, DARK_GREY)self.draw_text(f"当前最高分: {self.high_score}", (SCREEN_WIDTH / 2 - 114, SCREEN_HEIGHT / 2 + 50),  # 绘制最高分文本(255, 33, 33), WHITE)  # 展示最高分if not self.running and self.snake.is_alive:  # 如果游戏暂停且蛇还活着self.draw_text("游戏暂停 ", (SCREEN_WIDTH / 2 - 55, SCREEN_HEIGHT / 2 - 10),  # 绘制游戏暂停文本LIGHT_GREY, DARK_GREY)if __name__ == '__main__':SnakeGame().run()  # 运行游戏

game/apple.py

from random import randint
from snake.constant import *class Apple:"""苹果类:表示游戏中的苹果,蛇吃到苹果会增长身体长度。"""def __init__(self, game):"""初始化苹果对象。:param game: 游戏对象。"""self.game = gameself.x = self.y = 0  # 苹果的初始位置self.game.add_draw_action(self.draw)  # 将 draw 方法添加到游戏的绘制动作列表中self.drop()  # 生成一个新的苹果def drop(self):"""生成一个新的苹果,确保苹果不在蛇的身体上。"""snake = self.game.snake.body + [self.game.snake.head]  # 获取蛇的身体和头部的所有位置while True:(x, y) = randint(0, COLUMNS - 1), randint(0, ROWS - 1)  # 随机生成一个位置if (x, y) not in snake:  # 如果这个位置不在蛇的身体上self.x, self.y = x, y  # 将苹果的位置设置为这个位置break  # 退出循环def draw(self):"""绘制苹果。"""self.game.draw_cell((self.x, self.y),  # 苹果的位置CELL_SIZE,  # 每个单元格的大小APPLE_COLOR_SKIN,  # 苹果的外框颜色APPLE_COLOR_BODY  # 苹果的主体颜色)

game/base.py

import os
import sys
import time
from snake.constant import *# 使窗口居中
os.environ["SDL_VIDEO_CENTERED"] = "1"# MyGame 默认值
GAME_NAME = "贪吃蛇 By stormsha"
SCREEN_SIZE = 640, 480
DISPLAY_MODE = pygame.HWSURFACE | pygame.DOUBLEBUF
LOOP_SPEED = 60
# noinspection SpellCheckingInspection
FONT_NAME = "resources/MONACO.ttf"
FONT_SIZE = 16
KEY_PAUSE = pygame.K_PAUSEclass GameBase(object):"""pygame模板类"""def __init__(self, **kwargs):"""初始化可选参数:game_name       游戏名称icon            图标文件名screen_size     画面大小display_mode    显示模式loop_speed      主循环速度font_name       字体文件名font_size       字体大小"""pygame.init()pygame.mixer.init()self.game_name = kwargs.get("game_name") or GAME_NAMEpygame.display.set_caption(self.game_name)self.screen_size = kwargs.get("screen_size") or SCREEN_SIZEself.screen_width, self.screen_height = self.screen_sizeself.display_mode = kwargs.get("display_mode") or DISPLAY_MODEself.images = {}self.sounds = {}self.musics = {}self.icon = kwargs.get("icon") or Noneself.icon and pygame.display.set_icon(pygame.image.load(self.icon))self.screen = pygame.display.set_mode(self.screen_size,self.display_mode)self.loop_speed = kwargs.get("loop_speed") or LOOP_SPEEDself.font_size = kwargs.get("font_size") or FONT_SIZEself.background = None# noinspection SpellCheckingInspection''' 支持中文的字体新细明体:PMingLiU细明体:MingLiU标楷体:DFKai - SB黑体:SimHei宋体:SimSun新宋体:NSimSun仿宋:FangSong楷体:KaiTi仿宋_GB2312:FangSong_GB2312楷体_GB2312:KaiTi_GB2312微软正黑体:Microsoft JhengHei微软雅黑体:Microsoft YaHei'''self.font_name = kwargs.get("font_name") or pygame.font.match_font('SimHei')  # 获取系统字体self.font = pygame.font.Font(self.font_name, self.font_size)self.clock = pygame.time.Clock()self.now = 0self.background_color = kwargs.get("background") or BLACKself.set_background()self.key_bindings = {}  # 按键与函数绑定字典self.add_key_binding(KEY_PAUSE, self.pause)self.game_actions = {}  # 游戏数据更新动作self.draw_actions = [self.draw_background]  # 画面更新动作列表self.running = Trueself.draw = pygame.drawdef run(self):"""主循环"""while True:self.now = pygame.time.get_ticks()self.process_events()if self.running:self.update_game_data()self.update_display()self.clock.tick(self.loop_speed)def pause(self):"""暂停游戏"""self.running = not self.runningif self.running:for action in self.game_actions.values():if action["next_time"]:action["next_time"] = self.now + action["interval"]def process_events(self):"""事件处理"""for event in pygame.event.get():if event.type == pygame.QUIT:self.quit()elif event.type == pygame.KEYDOWN:action, kwargs = self.key_bindings.get(event.key, (None, None))# noinspection allaction(**kwargs) if kwargs else action() if action else Nonedef update_game_data(self):"""更新游戏数据"""for action in self.game_actions.values():if not action["next_time"]:action["run"]()elif self.now >= action["next_time"]:action["next_time"] += action["interval"]action["run"]()def update_display(self):"""更新画面显示"""for action in self.draw_actions:action()pygame.display.flip()def draw_background(self):"""绘制背景"""self.screen.blit(self.background, (0, 0))def add_key_binding(self, key, action, **kwargs):"""增加按键绑定"""self.key_bindings[key] = action, kwargs# TODO: 更新动作若有次序要求,则用字典保存不合适def add_game_action(self, name, action, interval=0):"""添加游戏数据更新动作"""next_time = self.now + interval if interval else Noneself.game_actions[name] = dict(run=action,interval=interval,next_time=next_time)def add_draw_action(self, action):"""添加画面更新动作"""self.draw_actions.append(action)def draw_text(self, text, loc, color, bgcolor=None):if bgcolor:surface = self.font.render(text, True, color, bgcolor)else:surface = self.font.render(text, True, color)self.screen.blit(surface, loc)def draw_cell(self, xy, size, color1, color2=None):x, y = xyrect = pygame.Rect(x * size, y * size, size, size)self.screen.fill(color1, rect)if color2:self.screen.fill(color2, rect.inflate(-4, -4))@staticmethoddef quit():"""退出游戏"""pygame.quit()sys.exit(0)@staticmethoddef load_music(filename):pygame.mixer.music.load(filename)@staticmethoddef play_music():pygame.mixer.music.play(-1)@staticmethoddef pause_music():pygame.mixer.music.pause()@staticmethoddef resume_music():pygame.mixer.music.unpause()@staticmethoddef stop_music():pygame.mixer.music.stop()def save_screenshots(self):filename = time.strftime('screenshots/%Y%m%d%H%M%S.png')pygame.image.save(self.screen, filename)def load_images(self, filename, sub_img=None):sub_img = sub_img or {}image = pygame.image.load(filename).convert_alpha()  # 文件打开失败for name, rect in sub_img.items():x, y, w, h = rectself.images[name] = image.subsurface(pygame.Rect((x, y), (w, h)))def set_background(self, background=None):if isinstance(background, str):self.background = pygame.image.load(background)else:self.background = pygame.Surface(self.screen_size)self.background_color = background \if isinstance(background, tuple) else (0, 0, 0)self.background.fill(self.background_color)def load_sounds(self, **sounds):"""@summary: 加载音乐:param sounds::return:"""for name, filename in sounds.items():self.sounds[name] = pygame.mixer.Sound(filename)def play_sound(self, name):self.sounds[name].play()if __name__ == '__main__':GameBase().run()

game/snake.py

import pygamefrom snake import constantclass Snake:"""贪吃蛇"""def __init__(self, game):self.game = gameself.sound_hit = pygame.mixer.Sound("resources/hit.wav")self.sound_eat = pygame.mixer.Sound("resources/eat.wav")self.game.add_draw_action(self.draw)# 初始化数据self.head = (constant.SNAKE_X, constant.SNAKE_Y)  # 蛇头当前位置self.body = [(-1, -1)] * constant.SNAKE_BODY_LENGTH  # 蛇身长度self.direction = constant.SNAKE_DIRECTION  # 当前方向self.new_direction = constant.SNAKE_DIRECTION  # 移动方向self.speed = constant.SNAKE_SPEED  # 移动速度self.is_alive = True  # 是否存活def set_speed(self, speed):"""@summary: 设置蛇的移动速度:param speed: 移动速度:return:"""self._speed = speedself.game.add_game_action("snake.move", self.move, 1000 // speed)def get_speed(self):"""@summary: 获取当前蛇的移动速度:return:"""return self._speed@propertydef speed(self):return self._speed@speed.setterdef speed(self, speed):self._speed = speedself.game.add_game_action("snake.move", self.move, 1000 // speed)def draw(self):"""@summary: 绘制小蛇:return: """skin_color = constant.SNAKE_COLOR_SKIN if self.is_alive else constant.SNAKE_COLOR_SKIN_DEADbody_color = constant.SNAKE_COLOR_BODY if self.is_alive else constant.SNAKE_COLOR_BODY_DEADhead_color = constant.SNAKE_COLOR_HEAD if self.is_alive else constant.SNAKE_COLOR_HEAD_DEADfor cell in self.body:self.game.draw_cell(cell, constant.CELL_SIZE, skin_color, body_color)self.game.draw_cell(self.head, constant.CELL_SIZE, skin_color, head_color)def turn(self, direction):"""@summary: 改变小蛇方向:param direction: :return: """if (self.direction in (constant.LEFT, constant.RIGHT) and direction in (constant.UP, constant.DOWN) orself.direction in (constant.UP, constant.DOWN) and direction in (constant.LEFT, constant.RIGHT)):self.new_direction = directiondef move(self):"""@summary: 移动小蛇:return: """if not self.is_alive:return# 设定方向self.direction = self.new_direction# 检测前方x, y = meeting = (self.head[0] + self.direction[0],self.head[1] + self.direction[1])# 死亡判断if meeting in self.body or x not in range(constant.COLUMNS) or y not in range(constant.ROWS):self.die()return# 判断是否吃了苹果if meeting == (self.game.apple.x, self.game.apple.y):self.sound_eat.play()self.game.apple.drop()self.game.apple_count += 1else:self.body.pop()# 蛇头变成脖子self.body = [self.head] + self.body# 蛇头移动到新位置self.head = meetingdef restart_pawn(self):"""重生"""self.head = (constant.SNAKE_X, constant.SNAKE_Y)self.body = [(-1, -1)] * constant.SNAKE_BODY_LENGTHself.direction = constant.SNAKE_DIRECTIONself.new_direction = constant.SNAKE_DIRECTIONself.speed = constant.SNAKE_SPEEDself.is_alive = Truedef die(self):self.sound_hit.play()self.is_alive = False

constant.py

import pygame# 颜色设定
BLACK = 0, 0, 0
WHITE = 255, 255, 255
DARK_GREY = 33, 33, 33
GREY = 127, 127, 127
LIGHT_GREY = 192, 192, 192
BACKGROUND_COLOR = BLACK
GRID_COLOR = DARK_GREY
APPLE_COLOR_SKIN = 255, 127, 127
APPLE_COLOR_BODY = 255, 66, 66
SNAKE_COLOR_SKIN = 33, 255, 33
SNAKE_COLOR_BODY = 33, 192, 33
SNAKE_COLOR_HEAD = 192, 192, 33
SNAKE_COLOR_SKIN_DEAD = LIGHT_GREY
SNAKE_COLOR_BODY_DEAD = GREY
SNAKE_COLOR_HEAD_DEAD = DARK_GREY# 一般设定
GAME_NAME = "SnakeGame"
SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
CELL_SIZE = 20
COLUMNS, ROWS = SCREEN_WIDTH // CELL_SIZE, SCREEN_HEIGHT // CELL_SIZE
DISPLAY_MODE = pygame.HWSURFACE | pygame.DOUBLEBUF
LOOP_SPEED = 60
# noinspection SpellCheckingInspection
FONT_NAME = "resources/MONACO.TTF"
FONT_SIZE = 16
# noinspection SpellCheckingInspection
ICON = "resources/snake.png"
UP, DOWN, LEFT, RIGHT = (0, -1), (0, 1), (-1, 0), (1, 0)# 按键设定
KEY_EXIT = pygame.K_ESCAPE
KEY_UP = pygame.K_UP
KEY_DOWN = pygame.K_DOWN
KEY_LEFT = pygame.K_LEFT
KEY_RIGHT = pygame.K_RIGHT
KEY_RESTART = pygame.K_r
K_PAUSE = pygame.K_PAUSE# 蛇的默认值
SNAKE_X = 0
SNAKE_Y = 0
SNAKE_BODY_LENGTH = 5
SNAKE_DIRECTION = RIGHT
SNAKE_SPEED = 10

源码地址:https://gitcode.com/stormsha1/games/overview

http://www.lryc.cn/news/342226.html

相关文章:

  • 计算机网络 2.4差错检验与校正
  • uniapp遍历数组对象的常见方法
  • Milvus向量数据库(一)Milvus存储byte[]类型源向量数据
  • Jupyter Notebook魔术命令
  • python基础---生成器
  • wangEditor 富文本详解
  • 文献速递:深度学习医学影像心脏疾病检测与诊断--从SPECT/CT衰减图中深度学习冠状动脉钙化评分提高了对重大不良心脏事件的预测
  • Java多线程:常见的线程的创建方法及Thread类详解
  • 一招搞定生产管理
  • 学习CSS3,实现红色心形loading特效
  • 深度学习之基于Matlab神经网络的活体人脸和视频人脸识别系统
  • 充电桩测试:负载箱的重要性
  • 贪心算法、Dijkstra和A*类路径搜索算法
  • Debian是什么?有哪些常用命令
  • 万兴PDF专家 PDFelement Pro v10.3.8 破姐版!
  • Ubuntu22.04 私钥登录
  • Java_JVM_JVMs
  • Linux系统编程之基本指令
  • [1702]java旅游资源网上填报系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
  • 【Flask 系统教程 3】请求与响应
  • jsp校园商城派送系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
  • 【Linux】System V 共享内存
  • 拼多多标准推广怎么玩
  • HFSS学习-day2-T形波导的优化设计
  • 贪吃蛇小游戏(c语言)
  • 多商户Docker Supervisor进程管理器部署
  • Vue--》从零开始打造交互体验一流的电商平台(一)
  • uniapp 自定义相机插件(组件版、缩放、裁剪)组件 Ba-CameraView
  • 如何在Python中生成随机密码?
  • 【Git管理工具】使用Docker+浪浪云服务器部署GitLab服务器