【python】贪吃蛇小游戏模拟解析

本文介绍了使用Python的pygame模块实现贪吃蛇小游戏的过程,包括游戏规则、前期准备和代码实现。玩家控制单一方向移动的蛇,通过吃食物增长长度,触碰墙壁或自身身体则游戏结束。文章详细讲解了main函数、窗口划分、游戏开始和结束屏幕的编写,以及游戏循环中的逻辑判断和画面刷新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.引言

我们python的基本知识已经学习得差不多了,老师说其实python强大的地方除了它的简便和灵活外,还有很多的模块供以使用。通过了解,我对python中的pygame模块产生了好奇心。接下来就是利用这个模块,对经典小游戏贪吃蛇进行解析和实现。

2.前期准备

游戏规则:游戏中,玩家将化作一条单一方向移动的蛇,通过控制上下左右四个方向,获取随机出现的食物,增长自身长度,如果在游戏过程中,触碰四周墙壁或者嘴巴与自己的身体有接触,则游戏结束。
关键词:
(1) 单一方向移动。
(2) 方向控制。
(3) 食物随机出现。
(4) 吃掉食物增长蛇的长度。
(5) 死亡(游戏结束)条件。
除此之外我们还需要对游戏环境,游戏窗口以及对其操作,游戏画面设计等进行编写实现。

3.代码实现

(1) 先编写main函数大概构造出代码纲领。

def main():
    global FPSCLOCK, DISPLAYSURF, BASICFONT

    #初始化
    pygame.init()
    #时钟
    FPSCLOCK = pygame.time.Clock()
    #显示窗口大小
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
    #字体
    BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
    #窗口名字
    pygame.display.set_caption('Snake')

    showStartScreen()
    while True:
        runGame()
        showGameOverScreen()

在此设置了一些比如时钟、游戏窗口大小、窗口名字等基本信息,还编写了在游戏程序的运行经过——简单开场之后进入循环,循环游戏主体以及游戏结束收场。
接下来完善showStartScreen()、runGame()和showGameOverScreen()三个游戏运行过程函数的内容。

(2) 为了方便规划设计与画图,把窗口划分成相对于像素来说更大的单位。

#窗口大小
WINDOWWIDTH = 640
WINDOWHEIGHT = 480
#基本单位
CELLSIZE = 20
CELLWIDTH = int(WINDOWWIDTH / CELLSIZE)
CELLHEIGHT = int(WINDOWHEIGHT / CELLSIZE)

(3) 对showStartScreen()与showGameOverScreen()的编写(他们是一样的设计元素):

应该实现的功能:
(1)开场有游戏的标题snake,结束有游戏的状态gameover。
(2)有操作提示语句
(3)完成操作之后进入游戏
在这里插入图片描述图1 showStartScreen()函数效果图

实现功能(1)需要包括如下类型的代码:

title = pygame.font.Font('freesansbold.ttf', 150)           #字体
gameSurf = title.render('Snake', True, WHITE)               #内容
gameRect = gameSurf.get_rect()
gameRect.midtop = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2 - 100) #位置
DISPLAYSURF.blit(gameSurf, gameRect)

实现功能(2)也是如此,但是因为这个’Press a key to play.'提示语句也需要出现在结束的页面,所以写了个函数。代码如下:

def drawPressKeyMsg():
    pressKeySurf = BASICFONT.render('Press a key to play.', True, WHITE)
    pressKeyRect = pressKeySurf.get_rect()
    pressKeyRect.topleft = (WINDOWWIDTH - 200, WINDOWHEIGHT - 30)
    DISPLAYSURF.blit(pressKeySurf, pressKeyRect)

功能(3)即实现对窗口的关闭和键盘输入任意一个非退出的按键进入游戏主体。代码如下:

def checkForKeyPress():
    if len(pygame.event.get(QUIT)) > 0:
        pygame.quit()
        sys.exit()

    keyUpEvents = pygame.event.get(KEYUP)
    if len(keyUpEvents) == 0:
        return None
    if keyUpEvents[0].key == K_ESCAPE:
        pygame.quit()
        sys.exit()
    return keyUpEvents[0].key

(4) 对runGame()的编写:

在这个环节,我们需要一条蛇和一个苹果。随机出现。哈的的度度和法法,以及苹果随机出现一个。
在这个游戏的主体部分,我们需要随机出现一个食物和一条长度为3的蛇,蛇需要一直在一个方向移动。
代码如下:

#随机生成蛇的位置(有范围:防止开场撞墙死亡)
snakex = random.randrange(5, CELLWIDTH - 6)
snakey = random.randrange(5, CELLHEIGHT - 6)
#蛇的长度
snake = [{'x': snakex,     'y': snakey},
         {'x': snakex - 1, 'y': snakey},
         {'x': snakex - 2, 'y': snakey}]
#蛇的方向
direction = 'right'
#随机生成食物的位置
food={'x': random.randint(0, CELLWIDTH - 1), 'y': random.randint(0, CELLHEIGHT - 1)}

接下来进行游戏的主循环部分:

① 外部输入——退出游戏和按键部分
for event in pygame.event.get():
    # 如果单击关闭窗口,则退出
    if event.type == pygame.QUIT:
        sys.exit()
    elif event.type == KEYDOWN:
        # 判断键盘事件,用w,s,a,d或者上下左右键来表示上下左右,esc按键退出
        if event.key == K_RIGHT or event.key == ord('d')and not direction == 'left':
            direction = "right"
        if event.key == K_LEFT or event.key == ord('a')and not direction == 'right':
            direction = "left"
        if event.key == K_UP or event.key == ord('w')and not direction == 'down':
            direction = "up"
        if event.key == K_DOWN or event.key == ord('s')and not direction == 'up':
            direction = "down"
        if event.key == K_ESCAPE:
            pygame.event.post(pygame.event.Event(QUIT))
② 详细逻辑

按键使得蛇的方向改变,路径改变的时候如果蛇头与食物的坐标相同,则判断为贪吃蛇吃掉了食物。吃了一个食物的蛇,蛇身增长一个单位;没有吃到食物的蛇,蛇身的长度不变。
通过时间的流逝,对蛇进行新增一个蛇头的操作,接着判断是否吃了食物。如果没有吃到食物,对刚刚新增蛇头的蛇进行去除蛇尾一个单位的操作;如果吃到了食物,则保持不变。
在这里插入图片描述

图2 贪吃蛇移动与吃食物时身体变化解析
尝试写出如下代码:

#蛇的移动:时间流逝使得新增了一个蛇头位置,整条蛇身+1,后面根据判断是否吃了食物进行-1
if direction == 'up':
    newHead = {'x': snake[0]['x'], 'y': snake[0]['y'] - 1}
elif direction == 'down':
    newHead = {'x': snake[0]['x'], 'y': snake[0]['y'] + 1}
elif direction == 'left':
    newHead = {'x': snake[0]['x'] - 1, 'y': snake[0]['y']}
elif direction == 'right':
    newHead = {'x': snake[0]['x'] + 1, 'y': snake[0]['y']}
snake.insert(0, newHead)
#判断吃食物,根据上面的代码,蛇的移动蛇身+1,则在此环节如果吃了食物,保持不变,没吃即要-1
if snake[0]['x'] == food['x'] and snake[0]['y'] == food['y']:
    # 随机生成新的苹果
    food={'x': random.randint(0, CELLWIDTH - 1), 'y': random.randint(0, CELLHEIGHT - 1)}
else:
    # 尾巴-1个格子
    del snake[-1]
③ 判断游戏结束——撞到墙或者蛇吃到了自己的身体。
#游戏被动结束情况
if snake[0]['x'] == -1 or snake[0]['x'] == CELLWIDTH or\
   snake[0]['y'] == -1 or snake[0]['y'] == CELLHEIGHT:
    return #进入游戏结束画面,原因:蛇撞到墙
for snakeBody in snake[1:]:
    if snakeBody['x'] == snake[0]['x'] and snakeBody['y'] == snake[0]['y']:
        return #进入游戏结束画面,原因:蛇吃到自己
④ 显示画面
#基本显示
DISPLAYSURF.fill(BLACK)
#食物
pygame.draw.rect(DISPLAYSURF, RED, pygame.Rect(food['x'] * CELLSIZE, food['y'] * CELLSIZE, CELLSIZE, CELLSIZE))
#蛇
for each in snake:
    x = each['x'] * CELLSIZE
    y = each['y'] * CELLSIZE
    pygame.draw.rect(DISPLAYSURF, GREEN, pygame.Rect(x, y, CELLSIZE, CELLSIZE))
⑤ 刷新
#刷新
pygame.display.update()
FPSCLOCK.tick(15)

代码下载地址:

见博客评论区博主留言

参考文献:

[1]https://www.jianshu.com/p/8ddeb797d1be
[2]https://inventwithpython.com/wormy.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值