python实现贪吃蛇小游戏

运行效果

在这里插入图片描述

1.开发环境

win10操作系统,pycharm 社区版 、anaconda3、pygame库

2.数据结构

列表list

3. 设计思路

对于贪吃蛇小游戏,首先简化成控制一个蛇头在地图中上下左右的移动,如下图所示,在此基础上再做以下的问题分析
图3.1

3.1 贪吃蛇移动问题

由于贪吃蛇是不断朝着一个方向移动的,所以当蛇身具有多段,蛇头的位置将会是蛇头后的下一个位置,即蛇身会始终跟着蛇头的方向走,于是可以定义一个列表,列表中存蛇从蛇头到蛇尾每一个身段的坐标,这样在绘制的时候只需要迭代该列表,于是就解决了贪吃蛇移动的问题。

3.2 贪吃蛇吃食物问题

在蛇吃食物的判定中,只需要判断蛇头和食物是否重合,即判断x和y坐标是否完全相同,原理是蛇身始终跟着蛇头走,若蛇头没有吃食物,蛇身是不可能碰到食物的。

3.3 贪吃蛇加长身段问题

由于蛇是不断移动的,在判定吃到食物后,首先记录蛇尾的坐标,接着将蛇整体移动到下一个位置,之后在蛇尾新加一个坐标列表[x,y]存之前的蛇尾坐标,实际上就是在列表中新加一个存储x和y值的列表,最后则实现了贪吃蛇吃到食物后加长身段。

3.4 游戏结束判定

游戏结束条件有三种:

  1. 蛇越界 -> 游戏失败
  2. 蛇通过吃食物达到指定长度 -> 游戏胜利
  3. 蛇吃到自己 -> 游戏失败

3.5 积分统计问题

这个参考 3.2 的部分,在判定吃到食物后,使得存储分数的变量+1即可

4. 代码分析

4.1 全局变量说明

import pygame as pg, sys, random    #将pygame库 命名为pg 简化代码
WIDTH = 800                     #int型 游戏窗口宽度
HEIGHT = 600                    #int型 游戏窗口高度
TITLE = 'Greedy Snake Game'     #String型 游戏的标题
pg.init();                      #pygame 库的初始化 具体实现细节可暂时忽略
screen = pg.display.set_mode((WIDTH,HEIGHT))        #Surface型 定义新的窗口 存到screen中
screen.fill([255,255,255])      #用白色填充窗口
# 之后会使用到的颜色, 三个参数分别为RGB的参数
RED = (255,0,0)         #红色,蛇头
BLUE = (70,130,180)     #蓝色,用来提示信息
PINK = (255,192,203)    #粉色,蛇身
ORANGE = (255,165,0)    #橘黄色,食物
BLACK = (0,0,0)         #黑色,游戏边界
SCORE = int(0)          #记录分数
GameState = 'run'       #记录游戏状态、分别有run、over、lose、finish、分别表示游戏正在进行、游戏结束、游戏失败、请求退出游戏

4.2 定义贪吃蛇的类Snake

在变量名前加两个下划线表示为私有成员变量,但依然可以通过对象名. _ 类名 _ xxx 这种特殊方式来访问,这里为了体现类的三大特性之一封装。

4.2.1 变量记录表

变量名称 类型 作用说明
__len int 记录蛇的身长(包括蛇头蛇尾)
__speed int 记录蛇的移动速度
__point list 记录蛇身的坐标(x, y) ,便于绘制图形
__direction string 记录蛇目前的运动方向 分别有left、right、up、down
__beforeDirection string 记录蛇之前的运动方向, 默认和上面的参数一致
getLonger bool 判断是否需要加长,为True则需要加长

4.2.3 方法记录表

方法名 传入参数 返回类型 作用说明
__ init __ len Snake 构造函数,在创建对象的时候会自动调用,根据蛇长len创建类Snake的对象
getPoint None list 返回存储蛇身坐标的列表__point
getDic None string 返回蛇的当前运动方向
getPreDic None string 返回蛇的之前运动方向
getLen None int 返回蛇的当前身长__len
getHeadXY None list 返回蛇头的坐标信息[x,y]
getTailXY None list 返回蛇尾的坐标信息[x,y]
getSpeed None int 返回蛇的移动速度
setXY index, X, Y None 设置蛇身索引为index的(默认0为蛇头) 的坐标为[X,Y]
setDicAndPreDic dic None 同时更新蛇的之前运动方向和 当前运动方向
setDic dic None 只设置蛇的当前运动方向
setLonger x, y None 将坐标[x,y]加入到蛇尾,并更新__len蛇长的值

4.2.4 类Snake的代码

class Snake(object):
    __len = 1                          #身长,默认为1
    __speed = 10                       #移动速度默认为10
    __point = [[WIDTH / 2,HEIGHT / 2]] #存储蛇身的坐标,默认只有蛇头在中间位置
    __direction = 'left'               #蛇的运动方向,默认朝左
    __beforeDirection = 'left'         #记录蛇之前的方向, 默认朝左
    getLonger = False                  #标记是否需要变长,即是否吃到食物
    def __init__(self,len):            #初始化
        self.__point.clear()           #考虑到重新开始,所以首先清除蛇身坐标
        self.__point.append([WIDTH / 2, HEIGHT / 2])    # 加蛇头坐标在屏幕中间
        self.__len = len               #更新蛇身长度
        for i in range(len - 1):       #遍历创建除蛇头外蛇身的坐标,默认在上一个基础下 x坐标加一,即实现贪吃蛇默认水平在屏幕中间
            p = self.__point[i]
            self.__point.append([p[0] + 20, p[1]])
    def getPoint(self):
        return self.__point
    def getDic(self):
        return self.__direction
    def getPreDic(self):
        return self.__beforeDirection
    def setXY(self, index, X,Y):
        point = self.__point[index]
        point[0], point[1] = X, Y
    def setDicAndPreDic(self, dic):
        self.__beforeDirection = self.__direction
        self.__direction = dic
    def setDic(self, dic):
        self.__direction = dic
    def getLen(self):
        return self.__len
    def getHeadXY(self):
        return self.__point[0]
    def getTailXY(self):
        return self.__point[self.__len - 1]
    def setLonger(self, x, y):
        self.__point.append([x,y])
        self.__len += 1
    def getSpeed(self):
        return self.__speed

通过Snake类的代码可以看出,缺少了绘制蛇身的代码,为了更加清晰地编写程序,绘制贪吃蛇的代码会放在另外的函数当中。

4.3 定义食物的类Food

4.3.1 变量记录表

变量名称 类型 作用说明
_X int 存储食物的X坐标
_Y int 存储食物的Y坐标

4.3.2 方法记录表

方法名 传入参数 返回类型 作用说明
__ init __ None Food 构造函数,在创建对象的时候会自动调用,默认随机设置食物位置
isOK snake bool 判断食物当前坐标与类Snake的对象snake的坐标是否冲突
setRandomFood snake None 随机设置食物的位置,保证最终食物的位置与蛇身不冲突
draw snake None 在食物位置与蛇头位置不冲突的前提下绘制食物

4.3.3 类Food的代码

class Food:
    _X , _Y = 0, 0              #记录食物的坐标
    def __init__(self):
        self._X, self._Y = random.randint(2, WIDTH / 25) * 20, random.randint(2, HEIGHT / 25) * 20 #创建对象时自动产生坐标
    def isOK(self,snake):                       #判断食物当前坐标是否合法
        flag = True  # 默认合法,接下来遍历蛇的坐标判断是否合法
        for point in snake.getPoint():
            if point[0] == self._X and point[1] == self._Y:
                flag = False
        return flag

    def setRandomFood(self, snake):
        while self.isOK(snake) == False:
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值