草庐IT

教你用322行Python代码编写贪吃蛇

AlexHu2022 2023-12-10 原文

目录

安装和导入 

规则

初始化

设定Surface,变量和显示数字的坐标 

函数

线程 

主要部分

总结

源码下载 


 贪吃蛇是一个很常见的小游戏,我们如何用Python去实现呢。


安装和导入 

pip install pygame
pip install keyboard
pip install pickledb

通过命令提示符安装所需模块。(以上非Python代码)

#导入
import pygame, keyboard, random, threading, time, pickledb

这个程序用到了pygame作为显示模块,keyboard捕获键盘操,pickledb记录最高纪录。


规则

#显示规则
print()
print('方向键控制方向')
print('\'esc\'退出')
print('\'alt\'暂停')
print('\'space\'继续')
print('每吃掉一个莓果,蛇身长长一格')
print('撞到蛇身或窗口边缘即为死亡')
print('死亡后\'esc\'退出,\'enter\'再来一局')

初始化

#初始化
pygame.init()

#设定窗口
screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption('Greedy Snake')

 执行以上代码就设定好了贪吃蛇的窗口。


设定Surface,变量和显示数字的坐标 

#设定蛇身
body = pygame.Surface((20, 20))
body.fill('yellow')

#设定莓果
berries = pygame.Surface((20, 20))
berries.fill('red')

#设定数字方块(用于显示数字)
block = pygame.Surface((4, 4))
#设定变量
T = 0
db = pickledb.load('Mark.db', False)
HI = db.get('HiMark')
B = False

函数

def keyname(key) :
    #键盘捕获
    global KEY
    KEY = key.name
keyboard.on_press(keyname)

用on_press绑定了keyname后,当键盘按下时会执行keyname函数。(key.name是按键的名称)

def snake() :
    #显示蛇身
    global path
    for xy in path :
        screen.blit(body, xy)

def food() :
    #显示食物
    global fx, fy
    screen.blit(berries, (fx, fy))

def eat() :
    #检测是否吃掉食物
    if (x, y) == (fx, fy) :
        return True
    else :
        return False

def crash() :
    #检测是否碰撞
    if path.count((x, y)) != 0 :
        return True
    elif x < 0 or x > 480 or y < 0 or y > 480 :
        return True
    else :
        return False

def count() :
    #计时线程函数
    global T
    while True :
        if B :
            time.sleep(1)
            T += 1

def timer() :
    #显示时间
    global T, number
    a = T // 100
    b = T % 100 // 10
    c = T % 10
    a = number[a]
    b = number[b]
    c = number[c]
    X, Y = 6, 10
    block.fill('white')
    for n in (a, b, c) :
        for xy in n :
            x = X + xy[0] * 4
            y = Y + xy[1] * 4
            screen.blit(block, (x, y))
        X += 32

def mark() :
    #显示分数
    global M, number
    a = M // 100
    b = M % 100 // 10
    c = M % 10
    a = number[a]
    b = number[b]
    c = number[c]
    X, Y = 395, 10
    block.fill('white')
    for n in (a, b, c) :
        for xy in n :
            x = X + xy[0] * 4
            y = Y + xy[1] * 4
            screen.blit(block, (x, y))
        X += 32

def hi() :
    #显示最高纪录
    global HI, number
    a = HI // 100
    b = HI % 100 // 10
    c = HI % 10
    a = number[a]
    b = number[b]
    c = number[c]
    X, Y = 263, 10
    block.fill('grey')
    for n in (a, b, c) :
        for xy in n :
            x = X + xy[0] * 4
            y = Y + xy[1] * 4
            screen.blit(block, (x, y))
        X += 32

线程 

#启动计时线程
time_count_thread = threading.Thread(target = count)
time_count_thread.start()

 线程可以在主线程的运行过程中运行,起到计时的作用。


主要部分

以下就是程序的主要部分,实现了对按键名称进行判断、蛇的移动、蛇吃掉食物后的生长和判断死亡。

while True :
    #变量初始化
    KEY = 'up'
    lKEY = KEY
    x, y = 240, 240
    path = []
    path.append((x, y))
    fx, fy = random.randrange(20, 460, 20), random.randrange(20, 460, 20)
    while path.count((fx, fy)) != 0 :
        fx, fy = random.randrange(20, 460, 20), random.randrange(20, 460, 20)
    T = 0
    M = 0
    B = True

    while True :
        time.sleep(0.1)

        #检测是否按下退出按钮
        for event in pygame.event.get() :
            if event.type == pygame.QUIT :
                pygame.quit()
                exit()
        
        #检测键盘按键
        if (KEY == 'up' and lKEY != 'down') or (KEY == 'w' and lKEY != 's') :
            y -= 20
            lKEY = KEY
        elif (KEY == 'down' and lKEY != 'up') or (KEY == 's' and lKEY != 'w')  :
            y += 20
            lKEY = KEY
        elif (KEY == 'left' and lKEY != 'right') or (KEY == 'a' and lKEY != 'd')  :
            x -= 20
            lKEY = KEY
        elif (KEY == 'right' and lKEY != 'left') or (KEY == 'd' and lKEY != 'a')  :
            x += 20
            lKEY = KEY
        elif KEY == 'alt' or KEY == 'right alt' :
            B = False
            while True :
                pygame.event.wait()
                if KEY == 'space' :
                    KEY = lKEY
                    B = True
                    break
                elif KEY == 'esc' :
                    pygame.quit()
                    if M > HI :
                        HI = M
                        db.set('HiMark', HI)
                        db.dump()
                    exit()
            continue
        elif KEY == 'esc' :
            pygame.quit()
            if M > HI :
                HI = M
                db.set('HiMark', HI)
                db.dump()
            exit()
        else :
            KEY = lKEY
            continue

        #检测是否碰撞或吃掉食物
        if crash() :
            break
        if eat() :
            M += 1
            fx, fy = random.randrange(20, 460, 20), random.randrange(20, 460, 20)
            while path.count((fx, fy)) != 0 :
                fx, fy = random.randrange(20, 460, 20), random.randrange(20, 460, 20)
        else :
            del path[0]
        
        #更新屏幕内容
        path.append((x, y))
        screen.fill('black')
        snake()
        food()
        timer()
        mark()
        hi()
        pygame.display.flip()

    #保存最高纪录
    if M > HI :
        HI = M
        db.set('HiMark', HI)
        db.dump()
    
    B = False

    #检测是否退出或再来一局
    while True :
        event = pygame.event.wait()
        if event.type == pygame.QUIT :
            pygame.quit()
            exit()
        elif KEY == 'esc' :
            pygame.quit()
            exit()
        elif KEY == 'return' or KEY == 'enter' :
            break

总结

如果你将以上所有的代码按顺序编写在一些,就可以运行完整的贪吃蛇了。这些代码都很简单,适合初学者学习。

希望这篇文章对您有帮助,感谢浏览。

源码下载 

GitHub源码

有关教你用322行Python代码编写贪吃蛇的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  8. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

随机推荐