Python实现贪吃蛇大作战

初始版本

初始版本,只存在基本数据结构——双向队列。

游戏思路

贪吃蛇通过不断得吃食物来增长自身,如果贪吃蛇碰到边界或者自身则游戏失败。

食物是绿色矩形来模拟,坐标为随机数生成,定义一个蛇长变量,判断蛇头坐标和食物坐标是否接近,如果蛇头接近食物,蛇长增加一个单位。

蛇结构体通过双向队列实现蛇的移动和增长。用pygame相应库函数读取键盘事件,每次事件发生都对应蛇头的相应方向,例如按键盘下键贪吃蛇向下走。蛇的移动是通过在队头添加一个新的坐标,然后删掉队尾元素实现的。队列的长度始终为蛇长变量的值。

得分变量为蛇长变量减去一个单位,初始化的时候蛇长就为1个单位长度,故而需要减1。

完整代码

import pygame
import random

pygame.init()

# 以RGB的形式定义颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)

# 设置窗体大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇 KevenDuan1.0')

# 创建clock对象
clock = pygame.time.Clock()

# 蛇的宽度
snake_block = 15
# 蛇的速度
snake_speed = 15

# 从系统库里获取字体
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)

def Your_score(score):
    value = score_font.render("Score: " + str(score), True, yellow)
    # 在主surface里添加字体surface
    dis.blit(value, [0, 0])

def our_snake(snake_block, snake_list):
    for x in snake_list:
        pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])

def message(msg, color):
    mesg = font_style.render(msg, True, color)
    dis.blit(mesg, [dis_width // 2 - 180, dis_height // 2])

def gameLoop():
    game_over = False
    game_close = False

    x1 = dis_width / 2
    y1 = dis_height / 2

    x1_change = 0
    y1_change = 0

    # 存放蛇的身体
    snake_List = []
    # 蛇的长度
    Length_of_snake = 1

    # 食物坐标随机生成
    foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
    foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
    print(foodx, foody)

    while not game_over:
        while game_close == True:
            dis.fill(blue)
            message("Game over, press p again or q quit!", red)
            Your_score(Length_of_snake - 1)
            # 修改得分
            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_p:
                        gameLoop()

        # 获取事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP or event.key == pygame.K_w:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    y1_change = snake_block
                    x1_change = 0

        if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
            # 判断为游戏失败
            game_close = True

        x1 += x1_change
        y1 += y1_change

        dis.fill(blue)
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_List.append(snake_Head)
        # 贪吃蛇的移动
        if len(snake_List) > Length_of_snake:
            del snake_List[0]

        # 判断是否咬到自身
        for x in snake_List[:-1]:
            if x == snake_Head:
                game_close = True

        # 画蛇出来
        our_snake(snake_block, snake_List)
        Your_score(Length_of_snake - 1)

        # 更新画面
        pygame.display.update()

        # 判断蛇是否迟到食物
        if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
            foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
            foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
            # print(foodx, foody)
            Length_of_snake += 1

        # 调节帧率来控制蛇的速度
        clock.tick(snake_speed)

    pygame.quit()
    quit()

gameLoop()

代码讲解

使用的pygamerandom两个库。Pygame是一种流行的Python游戏开发库,它提供了许多功能,使开发人员可以轻松创建2D游戏。它具有良好的跨平台支持,可以在多个操作系统上运行。random库是用来获取随机数的,后面使用其获取食物的随机坐标。

import pygame
import random

初始化一些后期用到的参数,以及初始化pygame,创建clock时钟对象。

# 初始化pygame
pygame.init()
# 以RGB的形式定义颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)

# 设置窗体大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
# 设置窗体的名称
pygame.display.set_caption('贪吃蛇 KevenDuan1.0')

# 创建clock对象
clock = pygame.time.Clock()

# 蛇的宽度
snake_block = 15
# 蛇的速度
snake_speed = 15

# 从系统库里获取字体
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)

定义得分函数,实际上就是在画面中添加字体。

def Your_score(score):
    value = score_font.render("Score: " + str(score), True, yellow)
    # 在主surface里添加字体surface
    dis.blit(value, [0, 0])

定义蛇体函数,实际上就是遍历蛇身队列,依次在画面中画出矩形。

def our_snake(snake_block, snake_list):
    for x in snake_list:
        pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])

定义文本函数,实际上就是在画面中显示文字。

def message(msg, color):
    mesg = font_style.render(msg, True, color)
    dis.blit(mesg, [dis_width // 2 - 180, dis_height // 2])

两个循环结构一个判断游戏是否结束一个判断游戏是否需要退出。

    while not game_over:
        while game_close == True:
            dis.fill(blue)
            message("Game over, press p again or q quit!", red)
            Your_score(Length_of_snake - 1)
            # 修改得分
            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_p:
                        gameLoop()

获取键盘事件改变蛇头方向

# 获取事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP or event.key == pygame.K_w:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    y1_change = snake_block
                    x1_change = 0

蛇的移动是通过在队头添加一个新的坐标,然后删掉队尾元素实现的。队列的长度始终为蛇长变量的值。

		x1 += x1_change
        y1 += y1_change

        dis.fill(blue)
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_List.append(snake_Head)
        # 贪吃蛇的移动
        if len(snake_List) > Length_of_snake:
            del snake_List[0]

        # 判断是否咬到自身
        for x in snake_List[:-1]:
            if x == snake_Head:
                game_close = True

        # 画蛇出来
        our_snake(snake_block, snake_List)
        Your_score(Length_of_snake - 1)

        # 更新画面
        pygame.display.update()

判断蛇头是否吃到食物,设置一定的范围,防止出现永远吃不到的bug

# 判断蛇是否吃到食物
        if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
            foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
            foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
            # print(foodx, foody)
            Length_of_snake += 1

增加菜单功能

通过查阅资料,发现pygame_menu提供了比较完善的游戏菜单功能。我通过pip下载后,查阅了官方样例代码,这个菜单确实是比较精美的,正是我所需要给游戏添加的东西。

import pygame
import pygame_menu

pygame.init()

surface = pygame.display.set_mode((600, 400))

def set_difficulty(value, difficulty):
    # Do the job here !
    print(1)
    pass

def start_the_game():
    # Do the job here !
    pass

menu = pygame_menu.Menu('Welcome', 600, 400,
                       theme=pygame_menu.themes.THEME_BLUE)

menu.add.text_input('Name :', default='kevenduan')
menu.add.selector('Difficulty :', [('Hard', 1), ('Easy', 2)], onchange=set_difficulty)
menu.add.button('Play', start_the_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(surface)

最终版本


新功能

最终版本添加了游戏界面菜单,有查询得分记录的功能,以及可以选择两个难度。

查询分数通过列表记录后,通过排序来显示得分前5的分数。

难度的控制是由蛇的速度来控制,由于咬到自身就游戏失败有点坑,在这里删除了。

完整代码

import pygame
import random
import pygame_menu

score = [0, 0, 0, 0, 0]
pygame.init()
# 以RGB的形式定义颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)

# 设置窗体大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Snakes KevenDuan 1.0')

# 创建clock对象
clock = pygame.time.Clock()

# 蛇的宽度
snake_block = 15
# 蛇的速度
snake_speed = 15

# 从系统库里获取字体
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)

def Your_score(score):
    value = score_font.render("Score: " + str(score), True, yellow)
    # 在主surface里添加字体surface
    dis.blit(value, [0, 0])

def our_snake(snake_block, snake_list):
    for x in snake_list:
        pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])

def message(msg, color):
    mesg = font_style.render(msg, True, color)
    dis.blit(mesg, [dis_width // 2 - 150, dis_height // 2])

def gameLoop():
    game_over = False
    game_close = False

    x1 = dis_width / 2
    y1 = dis_height / 2

    x1_change = 0
    y1_change = 0

    # 存放蛇的身体
    snake_List = []
    # 蛇的长度
    Length_of_snake = 1

    # 食物坐标随机生成
    foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
    foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
    print(foodx, foody)

    while not game_over:
        while game_close == True:
            dis.fill(blue)
            score.append(Length_of_snake - 1)
            message(f"Game Over! your score is {Length_of_snake - 1}", red)
            Your_score(Length_of_snake - 1)
            # 修改得分
            pygame.display.update()
            pygame.time.wait(2000)
            # 显示出菜单
            menu.mainloop(dis)

        # 获取事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP or event.key == pygame.K_w:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    y1_change = snake_block
                    x1_change = 0

        if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
            # 判断为游戏失败
            game_close = True

        x1 += x1_change
        y1 += y1_change

        dis.fill(blue)
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_List.append(snake_Head)
        # 贪吃蛇的移动
        if len(snake_List) > Length_of_snake:
            del snake_List[0]

        # 判断是否咬到自身
        # for x in snake_List[:-1]:
        #     if x == snake_Head:
        #         game_close = True

        # 画蛇出来
        our_snake(snake_block, snake_List)
        Your_score(Length_of_snake - 1)

        # 更新画面
        pygame.display.update()

        # 判断蛇是否吃到食物
        if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
            foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
            foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
            # print(foodx, foody)
            Length_of_snake += 1

        # 调节帧率来控制蛇的速度
        clock.tick(snake_speed)

    pygame.quit()
    quit()



def set_difficulty(value, difficulty):
    # Do the job here !
    global snake_speed
    if snake_speed == 15: snake_speed = 30
    else: snake_speed = 15

def start_the_game():
    # Do the job here !
    gameLoop()

def rank():
    # flag = True
    while True:
        dis.fill(blue)
        score.sort()
        print(score)
        mesg1 = font_style.render(f"Your highest score is {score[-1]}", True, yellow)
        dis.blit(mesg1, [dis_width // 2 - 150, dis_height // 2 - 30])
        mesg2 = font_style.render(f"Ranking of scores:{score[-1:-6:-1]}", True, yellow)
        dis.blit(mesg2, [dis_width // 2 - 190, dis_height // 2 + 10])

        pygame.display.update()
        pygame.time.wait(3000)
        menu.mainloop(dis)
        # menu.add.button('Quit', pygame_menu.events.EXIT)
        # for event in pygame.event.get():
        #     if event.type == pygame.QUIT:
        #         flag = True

menu = pygame_menu.Menu('Welcome to my game', 800, 600,
                       theme=pygame_menu.themes.THEME_BLUE)

menu.add.text_input('Author :', default='KevenDuan')
menu.add.selector('Difficulty :', [('Easy', 1), ('Hard', 2)], onchange=set_difficulty)
menu.add.button('Yours socres', rank)
menu.add.button('Play', start_the_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(dis)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/899495.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

需求分析基础指南:从零开始理解需求分析

目录 从零开始理解需求分析什么是需求分析&#xff1f;需求分析的目标需求分析的基本原则需求分析的各个阶段需求分析的常用方法和工具编写需求文档总结 从零开始理解需求分析 需求分析是软件开发过程中不可或缺的一环&#xff0c;它帮助我们明确用户的需求&#xff0c;确保最…

养殖场大型全自动饲料颗粒加工机械设备

随着养殖业的快速发展&#xff0c;对饲料加工设备的需求也日益增长。全自动饲料颗粒机作为现代养殖场的重要制粒设备&#xff0c;其自动化、高效化和智能化特点&#xff0c;不仅提高了饲料生产效率&#xff0c;还保障了饲料质量&#xff0c;为养殖业的可持续发展提供了有力支持…

关于jmeter中没有jp@gc - response times over time

1、问题如下&#xff1a; jmeter没有我们要使用的插件 2、解决方法&#xff1a; 选择下面文件&#xff0c;点击应用&#xff1b; 3、问题解决 ps&#xff1a;谢谢观看&#xff01;&#xff01;&#xff01;

【AIGC】AI如何匹配RAG知识库:混合检索

混合搜索 引言单检索的局限性单检索例子 混合检索拆解实现完整代码 总结 引言 RAG作为减少模型幻觉和让模型分析、回答私域相关知识最简单高效的方式&#xff0c;我们除了使用之外可以尝试了解其是如何实现的。在实现RAG的过程中&#xff0c;最重要的是保证召回的知识的准确性…

红日靶场(三)1、环境介绍及环境搭建

1、靶场介绍 红日靶场03是一个用于安全测试和渗透测试的虚拟化环境&#xff0c;可以帮助用户通过模拟攻击和防御场景来提升网络安全技能。该靶场包含了多个虚拟机和网络配置&#xff0c;用户可以在其中进行各种安全测试活动&#xff0c;如信息收集、漏洞利用、权限提升等。 2…

npm install node-sass安装失败

需求&#xff1a;搭建前端开发环境时&#xff0c;npm install报错&#xff0c;错误提示安装node_modules时&#xff0c;node-sass依赖包安装失败&#xff0c;网上找了好久解决方法&#xff0c;大家提示采用淘宝源等方式安装&#xff0c;都失败了了&#xff0c;尝试了很久终于找…

BUUCTF 之Basic 1(BUU BRUTE 11)

今天我们继续BUUCTF之Basic 1的第二关卡。 1、老规矩&#xff0c;进入地址BUUCTF在线评测 (buuoj.cn)打开对应靶场进行启动&#xff0c;会看一个页面&#xff0c;就代表启动成功。 首先分析一下&#xff0c;看到这个页面我们就可以得出是爆破的题目&#xff0c;常用于登陆&am…

1208. 尽可能使字符串相等

Problem: 1208. 尽可能使字符串相等 题目描述 给定两个相同长度的字符串 s 和 t&#xff0c;将字符串 s 转换为字符串 t 需要消耗开销&#xff0c;开销是两个字符的 ASCII 码差值的绝对值。还有一个最大预算 maxCost&#xff0c;我们需要在这个预算范围内&#xff0c;找到 s 中…

基于知识图谱的诗词推荐系统

你是否曾经想在浩如烟海的古代诗词中找到属于自己的那几首“知己”&#xff1f;现在&#xff0c;借助人工智能与知识图谱&#xff0c;古典诗词不再是玄之又玄的文本&#xff0c;而是变成了让你“个性化定制”的文化体验&#xff01;我们带来的这款基于知识图谱的诗词推荐系统&a…

我准备写一份Stable Diffusion入门指南-part1

我准备写个SD自学指南&#xff0c;当然也是第一次写&#xff0c;可能有点凌乱&#xff0c;后续我会持续更新不断优化&#xff0c;我是生产队的驴&#xff0c;欢迎监督。 Stable Diffusion WebUI 入门指南 Stable Diffusion WebUI 是一款基于 Stable Diffusion 模型的用户界面…

SIP 业务举例之 Transfer - Unattended(无人值守呼叫转移)

目录 1. Transfer - Unattended 简介 2. IP Telephony 特性 3. RFC5359 的 Transfer - Unattended 信令流程 无人值守呼叫转移 隐式订阅 Bob 通知 Alice 呼叫转移完成 - NOTIFY 隐含的订阅和显示的订阅 4. Transfer - Unattended 过程总结 博主wx:yuanlai45_csdn 博主…

重写 CSS Flexible Box

一、是什么? Flex 是 Flexible Box 的缩写, 意为 弹性布局, 用来为盒状模型提供更为灵活的布局能力, 它给 Flexbox 的 子元素 之间提供了强大的 空间分布(伸缩) 和 对齐 能力 二、基础概念 2.1 容器 采用 Flex 布局的元素 (设置了 display: flex | inline-flex 的元素) 称…

轻松上手 Disruptor:两个实例解析并发编程利器

Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列。很多知名开源项目里&#xff0c;比如 canal 、log4j2、 storm 都是用了 Disruptor 以提升系统性能 。 这篇文章&#xff0c;我们通过两个例子一步一个脚印帮助同学们入门 Disruptor 。 1 环形缓冲区 下图展示了 Di…

详解Oracle审计(一)

题记&#xff1a; 有段时间没写过oracle了&#xff0c;今天回归。 本文将详细介绍oracle的审计功能&#xff0c;基于11g版本&#xff0c;但对12c&#xff0c;19c也同样适用。 审计&#xff08;Audit&#xff09;用于监视用户所执行的数据库操作&#xff0c;并且 Oracle 会将审…

hadoop的yarn

1.分布式的资源调度-yarn(hadoop的一个组件) 资源服务器硬件资源&#xff0c;如&#xff1a;CPU,内存,硬盘,网络等 资源调度:管控服务器硬件资源&#xff0c;提供更好的利用率 分布式资源调度:管控整个分布式服务器集群的全部资源&#xff0c;整合进行统一调度 总结就是使用yar…

chatGpt4.0Plus,Claude3最新保姆级教程开通升级

如何使用 WildCard 服务注册 Claude3 随着 Claude3 的震撼发布&#xff0c;最强 AI 模型的桂冠已不再由 GPT-4 独揽。Claude3 推出了三个备受瞩目的模型&#xff1a;Claude 3 Haiku、Claude 3 Sonnet 以及 Claude 3 Opus&#xff0c;每个模型都展现了卓越的性能与特色。其中&a…

Blazor WebAssembly 项目部署时遇到 500.19错误

这个错误其实很普遍&#xff0c;在部署 asp.net core 的时候都能解决 无非是安装 这些, 尤其是下面那个 Hosting Bundle 但是遇到 Blazor WebAssembly 项目部署时还得多装一个 “重写模块” 下载地址&#xff0c;安装后重启网址 https://www.iis.net/downloads/microsoft/u…

【从零开始的LeetCode-算法】3185. 构成整天的下标对数目 II

给你一个整数数组 hours&#xff0c;表示以 小时 为单位的时间&#xff0c;返回一个整数&#xff0c;表示满足 i < j 且 hours[i] hours[j] 构成 整天 的下标对 i, j 的数目。 整天 定义为时间持续时间是 24 小时的 整数倍 。 例如&#xff0c;1 天是 24 小时&#xff0c…

使用Vue指令实现面板拉伸功能

目的&#xff1a;现在有一个PDF预览页面&#xff0c;左侧为PDF预览区域&#xff0c;右侧为可以进行AI功能的面板。现在想让AI面板通过拖动左边框实现面板拉伸。 实现效果如下面的视频&#xff1a; 关键点&#xff1a; 预览区是使用iframe渲染的&#xff0c;在拖动的过程中&…

软件测试学习笔记丨Selenium键盘鼠标事件ActionChains

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/22515 本文为霍格沃兹测试开发学社的学习经历分享&#xff0c;写出来分享给大家&#xff0c;希望有志同道合的小伙伴可以一起交流技术&#xff0c;一起进步~ 说明&#xff1a;本篇博客基于sel…