一、游戏介绍

贪吃蛇是个非常简单的游戏,适合练手。先来看一下我的游戏截图:

玩法介绍:
回车键:开始游戏
空格键:暂停 / 继续
↑↓←→方向键 或 WSAD 键:控制移动方向。

食物分红、绿、蓝三种,分别对应 10 分、20 分、30 分,每吃一个食物增加对应分值,每增加 100 分速度加快一级,没有设置关卡,我玩到 1100 分,速度太快了,然后就 GAME OVER 了。

二、游戏分析

贪吃蛇这个游戏很简单,屏幕上随机出现一个点,表示“食物”,上下左右控制“蛇”的移动,吃到“食物”以后“蛇”的身体加长,“蛇”碰到边框或自己的身体,则游戏结束。

我们先来分析一下,要写出这个游戏来需要注意哪些点。

1、蛇怎么表示

我们可以将整个游戏区域划分成一个个的小格子,由一组连在一起的小格子组成“蛇”,我们可以用不同的颜色来表示,如上图中,我以深色表示背景,浅色表示“蛇”。

我们可以用坐标来表示每一个小方格,X 轴和 Y 轴的范围都是可以设定好的。用一个列表来存放“蛇身”的坐标,那么一条“蛇”就出来了,最后只要显示的时候以不同的颜色表示即可。

2、蛇怎么移动?

第一反应就是像蚯蚓蠕动一样,每一个小方块向前移动一格,但这样实现起来很麻烦。一开始就是被这里卡住了。

想象一下我们玩过的贪吃蛇,每次“蛇”的移动感觉上是整体往前移动了一格,排除掉脑子中“蛇”的“动作”,细想移动前和移动后“蛇”的位置变化,其实除了头尾,其他部分根本就没有变。那就简单了,将下一格的坐标添加到列表开头,并移除列表的最后一个元素,就相当于蛇向前移动了一格。

3、如何判定游戏结束?

“蛇”移动超出了游戏区的范围或者碰到了自己就算输了,轴坐标的范围是事先定好的,超出范围很容易判断。那么如何判断碰到自己呢?

如果脑子里想的是“蛇”动的画面,那真的比较难了,但是放到代码中,我们的“蛇”是一个列表,那么只要判断下一格的坐标是否已经包含在“蛇”的列表中岂不就可以了?

理清了这些问题,我们就可以开始编码了。

三、代码展示

由于程序中要频繁的对“蛇”进行头尾的添加和删除操作,为了性能更好那么一点,我们用 deque 代替列表。

首先需要初始化“蛇”,“蛇”的初始长度为 3,位置位于左上角。

# 游戏区域的坐标范围
SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1) snake = deque()
def _init_snake():
    snake.clear()
    snake.append((2, scope_y[0]))
    snake.append((1, scope_y[0]))
    snake.append((0, scope_y[0]))

创建“食物”,在屏幕内随机选取一个点作为“食物”,但是要保证“食物”不在“蛇”身上。

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

“蛇”的移动可以有 4 个方向,用一个元组来表示移动的方向,每次按下方向键,给赋对应的值

# 方向
pos = (1, 0) for event in pygame.event.get():
    if event.type == QUIT:
        sys.exit()
    elif event.type == KEYDOWN:
        if event.key in (K_w, K_UP):
            # 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER
            if pos[1]:
                pos = (0, -1)
        elif event.key in (K_s, K_DOWN):
            if pos[1]:
                pos = (0, 1)
        elif event.key in (K_a, K_LEFT):
            if pos[0]:
                pos = (-1, 0)
        elif event.key in (K_d, K_RIGHT):
            if pos[0]:
                pos = (1, 0)

而“蛇”的移动就可以表示为:

next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
if next_s == food:
    # 吃到了食物
    snake.appendleft(next_s)
    food = create_food(snake)
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

扫码关注我的个人公众号,后台回复【贪吃蛇】,获取源码。


Python:游戏:贪吃蛇原理及代码实现的更多相关文章

  1. 【python】10分钟教你用python打造贪吃蛇超详细教程

    10分钟教你用python打造贪吃蛇超详细教程 在家闲着没妹子约, 刚好最近又学了一下python,听说pygame挺好玩的.今天就在家研究一下, 弄了个贪吃蛇出来.希望大家喜欢. 先看程序效果: 0 ...

  2. 如何用python制作贪吃蛇以及AI版贪吃蛇

    用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...

  3. Unity3D_(游戏)贪吃蛇

    Unity制作贪吃蛇小游戏 玩家通过“WASD”控制小蛇上下左右移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自己身体游戏结束 可通 ...

  4. 一步步教你怎么用python写贪吃蛇游戏

    目录 0 引言 1 环境 2 需求分析 3 代码实现 4 后记 0 引言 前几天,星球有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Pytho ...

  5. python【控制台】小游戏--贪吃蛇

    传统贪吃蛇相信大家都玩过,也是一款很老很经典的游戏,今天我们用python控制台实现 项目有很多bug没有解决,因为本人一时兴起写的一个小游戏,所以只是实现可玩部分功能,并没有花较多的时间和精力去维护 ...

  6. 用Python实现童年小游戏贪吃蛇

    贪吃蛇作为一款经典小游戏,早在 1976 年就面世了,我最早接触它还是在家长的诺基亚手机中.

  7. 以前写的canvas 小游戏 贪吃蛇代码

    效果如图,完成了贪吃蛇的基本的功能 代码地址 :https://github.com/my-new-git-hub/canvasSnake.git 预览地址:https://www.kzc275.to ...

  8. 贪吃蛇的java代码分析(二)

    代码剖析 贪吃蛇是一款十分经典的小游戏,对初入coding的朋友来说,拿贪吃蛇这样一个案例来练手十分合适,并不高的难度和成功后的成就感都是学习所必须的.下面我将依照我当时的思路,来逐步分析实现的整个过 ...

  9. 多线程的Python 教程--“贪吃蛇”

    本指南的里代码可以在这里下载:  threadworms.py ,或者从  GitHub.代码需要  Python 3 或 Python 2 ,同时也需要安装  Pygame . 点击查看大版本图片 ...

随机推荐

  1. codeForces 472D 最小生成树

    题目大意:给出一个图中点的两两距离,问是否是一棵树,若是,求出平均边权最大的点 prim最小生成树,若原图是树,则最小生成树的距离就是原距离.否则不是. 搞出来树了,第二问随便dfs就好了. #inc ...

  2. BZOJ_3438_小M的作物_最小割

    BZOJ_3438_小M的作物_最小割 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物) ...

  3. AngularJs parent index

    AngualrJs ng-repeat使用 $parent.$index 当时用ng-repeat的时候在其子原属中可以使用$parent.$index获取父级下标,当没有没有多一级的ng-if,一般 ...

  4. Applet 应用程序进行数字签名,对系统文件进行读写操作

    转:http://www.iteye.com/topic/154531 最近在研究applet,打算使用applet来开发一个上传文件上传控件,之前因为一直觉得applet的沙箱控制导致applet不 ...

  5. 使用Mybatis实现动态SQL(一)

    使用Mybatis实现动态SQL 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 写在前面:        *本章节适合有Mybatis基础者观看* 前置讲解 我现在写一个查询全部的 ...

  6. 死磕 java集合之PriorityBlockingQueue源码分析

    问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...

  7. .netcore2.1在控制器中和类中,获取appsettings中值的方法

    一般我们在开发项目中,都会从配置文件中获取数据库连接信息.自定义参数配置信息等. 在.netcore中在控制器和自定义类中,获取配置文件中参数方式如下: appsettings.json { &quo ...

  8. 你用.NET开发APP时,在云平台打包APP要填个“包名”的含义

    ios 在ios平台,包名有它专有的名词:bundle ID.bundle ID可以翻译成包ID,也可以叫APP ID或者应用ID,他是每一个ios应用的全球唯一标识,只要bundle id不变,无论 ...

  9. PoolEntry 参数讲解

    public abstract class PoolEntry<T, C> { private final String id; private final T route; //路由 p ...

  10. MVC、MVP、MVVM 模式对比

    MVC.MVP和MVVM这些开发模式为了分离视图(View)和模型(Model)而提出来的,直白说就是为了前后端分离. 1. MVC(Model View Controller)模式 MVC是比较直观 ...