• python贪吃蛇


    代码地址如下:
    http://www.demodashi.com/demo/13335.html

    一、先展示python贪吃蛇效果

    python snake

    二、操作说明

    按键 功能
    UP 向上移动
    DOWN 向下移动
    LEFT 向左移动
    RIGHT 向右移动
    空格 暂停/继续
    F1 加速
    F2 减速
    F3 开启/关闭无敌模式
    ESC 退出游戏

    三、游戏说明

    本教程使用python实现了一个简易的贪吃蛇游戏,为了让更多人能体会到python给我们带来的方便和乐趣,本教程源代码包含了详细的注释,同时也采用了更简单和易于理解的方式来实现贪吃蛇游戏.
    游戏开始时,会生成 一个 位置随机长度为5的蛇 (蛇头红色,蛇身绿色),一个 位置随机的食物 (红色),和一堵 位置随机的长度最大为5的墙 (黑色).
    游戏运行过程中,可以通过 方向键 控制蛇移动来吃掉食物,每吃掉一个食物蛇身长度加1,每吃掉 10 个食物游戏速度加快一个等级,并且增加一堵位置随机长度最大为5的墙,以增加游戏难度.
    蛇移动过程中咬到自身或撞到墙就会死亡,游戏自动退出.当然,也可以开启 无敌模式 ,让小蛇尽情的畅游.

    四、源码详解

    本游戏的源码共分为三个模块: game模块 , window模块 , snake模块.

    1、window模块

    本模块用于实现游戏界面的绘制和窗口事件的检测.
    本模块提供了 clear(清屏) , update(刷新) , rect(画矩形) , circle(画圆) , event(事件检测) 等接口.
    本模块的功能主要使用pygame模块实现,是对pygame的进一步封装.

    clear

    用指定颜色填充背景,并且绘制游戏地图方格,游戏地图是一个由横向40个方格,纵向20个方格组成的方阵

    '''
    用背景色填充屏幕(清屏)
    '''
    def clear(self):
        color = self._color_sub(self.COLOR_WHITE, self.gw_bgcol)
        self._game_window.fill(self.gw_bgcol)
        for x in range(self.maxx()+1):
            pygame.draw.line(self._game_window, color, (x*self.pnt_size, 0), (x*self.pnt_size, self.gw_height), 1)
        for y in range(self.maxy()+1):
            pygame.draw.line(self._game_window, color, (0, y * self.pnt_size), (self.gw_width, y*self.pnt_size), 1)
    

    update

    pygame的update,刷新屏幕

    '''
    刷新屏幕
    '''
    def update(self):
        pygame.display.update()
    

    rect

    往地图上的指定位置的小方格中画一个矩形,这里使用的坐标不是屏幕坐标,而是小方格在地图中的坐标( _rect是对pygame的draw.rect的封装,使用的是屏幕坐标 )

    '''
    在屏幕指定位置画一个正方形(相对坐标)
    
    Parameters
    :param x: 正方形左上角的x坐标
    :param y: 正方形左上角的y坐标
    :param color: 圆形填充颜色
    '''
    def rect(self, x, y, *color):
        pntcol = self.pnt_col
        if len(color) != 0:
            pntcol = color[0]
        if x < 0 or x > self.maxx() or y < 0 or y > self.maxy():
            return
        self._rect(x*self.pnt_size, y*self.pnt_size, pntcol)
    

    circle

    往地图上的指定位置的小方格中画一个圆形,这里使用的坐标不是屏幕坐标,而是小方格在地图中的坐标( _circle是对pygame的draw.circle的封装,使用的是屏幕坐标 )

    '''
    在屏幕指定位置画一个圆形(相对坐标)
    
    Parameters
    :param x: 圆形外接正方形左上角的x坐标
    :param y: 圆形外接正方形左上角的y坐标
    :param color: 圆形填充颜色
    '''
    def circle(self, x, y, *color):
        pntcol = self.pnt_col
        if len(color) != 0:
            pntcol = color[0]
        if x < 0 or x > self.maxx() or y < 0 or y > self.maxy():
            return
        x = x*self.pnt_size
        y = y*self.pnt_size
        self._circle(x, y, x+self.pnt_size, y+self.pnt_size, pntcol)
    

    event

    检按键按下的事件,是对pygame的event的封装,把按键按下的状态封装成事件

    '''
    屏幕事件
    '''
    def event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return self.EVENT_QUIT
            elif event.type == pygame.KEYDOWN:  # KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    return self.EVENT_KLEFT
                elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    return self.EVENT_KRIGHT
                elif event.key == pygame.K_UP or event.key == pygame.K_w:
                    return self.EVENT_KUP
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    return self.EVENT_KDOWN
                elif event.key == pygame.K_SPACE:
                    return self.EVENT_STOP
                elif event.key == pygame.K_F1:
                    return self.EVENT_ADD
                elif event.key == pygame.K_F2:
                    return self.EVENT_SUB
                elif event.key == pygame.K_ESCAPE:
                    return self.EVENT_QUIT
                elif event.key == pygame.K_F3:
                    return self.EVENT_KING
        return self.EVENT_NONE
    

    2、snake模块

    本模块使用最简单的方法实现了贪吃蛇原理, 包含贪吃蛇的初始化,贪吃蛇的移动和碰撞检测,食物的生成,强的生成,贪吃蛇地图,贪吃蛇的绘制等.

    __init__

    贪吃蛇模块的初始化,创建了用于保存贪吃蛇蛇身,贪吃蛇地图的 list ,以及其他要用到的变量.

    def __init__(self, s_len=5, s_width=40, s_height=20):  # (640/20 - 1, 480/20 -1)
        self.s_width = s_width
        self.s_height = s_height
        self.s_life = self.SNAKE_LIFE
        self._dir = self.DIR_RIGHT
    
        self.s_king = False # 无敌模式
    
        self.s_list = [] # 保存贪吃蛇蛇身坐标(s_list[0]保存食物,s_list[1]保存蛇头,其他保存蛇身)
        self.s_wall = [] # 保存墙的坐标
        self._create_wall() # 创建一堵墙, 强的位置随机, 方向随机, 长度最大为5
        self.s_map = self._map_create(self.BODY_NONE) # 保存贪吃蛇地图,所有的游戏元素都要填充到地图中,然后统一绘制到屏幕上
    
        # create a food, food = list[0]
        _s_food = self._create_body() # 创建一个随机的坐标,标记为食物
        self.s_list.append(_s_food)
        # creat a head, head = list[1]
        self._s_head = self._create_body() # 创建一个随机的坐标,标记为蛇头
        self.s_list.append(self._s_head)
    
        # create body and add body to list
        for _ in range(s_len-1): # 蛇身的坐标通过蛇头的坐标和蛇的方向计算得来
            self._s_head = (self._s_head[0]-1, self._s_head[1])
            self.s_list.append(self._s_head)
        # print(self.s_list)
    
        self.s_score = 0  # len(self.s_list) # 游戏得分,吃一个食物得一分
    

    drawshow

    draw用于把所有的游戏元素:食物,蛇头,蛇身,墙按照其坐标填充到地图中, 地图是一个二维的 list, 形如 s_map[x][y]
    show用于把贪吃蛇地图绘制到屏幕上,并刷新屏幕,这样贪吃蛇就显示出来了.show需要使用一个window对象来进行屏幕操作

    '''
    绘制食物和蛇(把地图绘制到屏幕上)
    
    :param pen: window对象
    '''
    def show(self, pen):
        pen.clear()
        self.draw()
        for x in range(self.s_width):
            for y in range(self.s_height):
                if self.s_map[x][y] != self.BODY_NONE:
                    if self.s_map[x][y] == self.BODY_FOOD:
                        pen.circle(x, y, pen.COLOR_BLUE)  # draw food
                    if self.s_map[x][y] == self.BODY_HEAD:
                        pen.rect(x, y, pen.COLOR_RED)  # draw head
                    if self.s_map[x][y] == self.BODY_SNAKE:
                        pen.rect(x, y, pen.COLOR_GREEN)  # draw snake
                    if self.s_map[x][y] == self.BODY_WALL:
                        pen.rect(x, y, pen.COLOR_BLACK)  # draw snake
        pen.update()
    
    '''
    把蛇和食物放在地图中
    '''
    def draw(self):
        x = 0
        y = 0
        self._map_init(self.s_map, self.BODY_NONE)
        if len(self.s_list) != 0:
            x = self.s_list[0][0]
            y = self.s_list[0][1]
            if x >= 0 and x < self.s_width and y >= 0 and y < self.s_height:
                self.s_map[x][y] = self.BODY_FOOD  # draw food
    
            x = self.s_list[1][0]
            y = self.s_list[1][1]
            if x >= 0 and x < self.s_width and y >= 0 and y < self.s_height:
                self.s_map[x][y] = self.BODY_HEAD  # draw head
    
            for s in range(2, len(self.s_list)):  # draw snake
                x = self.s_list[s][0]
                y = self.s_list[s][1]
                if x >= 0 and x < self.s_width and y >= 0 and y < self.s_height:
                    self.s_map[x][y] = self.BODY_SNAKE
        if len(self.s_wall) != 0:
            for w in self.s_wall:
                x = w[0]
                y = w[1]
                if x >= 0 and x < self.s_width and y >= 0 and y < self.s_height:
                    self.s_map[x][y] = self.BODY_WALL
    

    move

    用于贪吃蛇的移动,移动过程中会进行碰撞检测,如果撞到食物,则吃掉食物并产生一个新的食物,同时蛇身长度增加,游戏得分增加.如果撞到自己,或撞到墙,则蛇死亡. 没调用一个move,贪吃蛇移动一步,一般把move和show放到一个单独的线程中不断运行.

    '''
    移动蛇
    
    :param dir: 蛇移动方向
    '''
    def move(self, dir=DIR_RIGHT):
    
        if self._check_dir(self._dir, dir):
            self._dir = dir
    
        head = self.s_list[1]  # save head
        last = self.s_list[-1]  # save tail
        # move the snake body fowward(copy list[n-1] to list[n])
        for idx in range(len(self.s_list)-1, 1, -1):
            self.s_list[idx] = self.s_list[idx-1]
    
        head_t = self._add_xy(head, self._dir)  # new head
    
        # check snake head(cross wall)
        if head_t[0] < 0:
            head_t[0] = self.s_width - 1
        elif head_t[0] > self.s_width - 1:
            head_t[0] = 0
    
        if head_t[1] < 0:
            head_t[1] = self.s_height - 1
        elif head_t[1] > self.s_height - 1:
            head_t[1] = 0
    
        chk, bd = self._check_body(head_t)  # check the head
        # if bd != self.BODY_NONE:
        #    print(chk, bd)
        if chk == True and bd != self.BODY_NONE:
            if bd == self.BODY_HEAD or bd == self.BODY_SNAKE or bd == self.BODY_WALL:  # eat yourself or wall
                if self.s_king != True:  # 无敌模式
                    self.s_life = self.SNAKE_DIE  # die
                    return self.s_life
            else:  # eat food
                self.s_list.append(last)  # body growth
                self.s_score = self.s_score + 1  # add score
                if self.s_score % 10 == 0:  # 每吃10个食物增加一面墙
                    self._create_wall()
                food = self._create_body()  # create food
                if food == None:  # no space to create food
                    self.s_life = self.SNAKE_WIN
                    return self.s_life
                self.s_list[0] = food
    
        self.s_list[1] = head_t  # update head
    
        if len(self.s_list) == ((self.s_width * self.s_height)):
            self.s_life = self.SNAKE_WIN
        return self.s_life
    

    3、game模块

    该模块创建一个window对象和一个snake对象, 然后在一个新线程中执行snake模块的move和show函数,实现贪吃蛇的不断移动和绘制.在主线程中,不断检测窗口事件,根据窗口事件类型改变蛇的状态.

    game_run

    用于在子线程中运行的线程函数

    '''
    贪吃蛇运行线程
    '''
    def game_run(snake):
        global dir
        global stop
        global speed
        delay = 1.5
        while True:
            if stop != True:
                life = snake.move(dir)
                if life != snake.SNAKE_LIFE:
                    break  # die, exit
            snake.show(window)
            delay = 1 - speed * 0.05
            if delay < 0.05:
                delay = 0.05
            time.sleep(delay)
    

    main

    贪吃蛇游戏主函数

    if __name__ == "__main__":
        snake, window = game_init()
        # 创建新线程,在新线程中允许和绘制贪吃蛇
        gt = threading.Thread(target=game_run, args=(snake,))
        gt.start()
    
        # 主线程用于检测按键事件
        while True:
            event = window.event()
            if event != window.EVENT_NONE:
                if event == window.EVENT_QUIT:  # ESC退出
                    window.quit()
                elif event == window.EVENT_KUP or 
                        event == window.EVENT_KDOWN or 
                        event == window.EVENT_KLEFT or 
                        event == window.EVENT_KRIGHT:  # 方向键控制贪吃蛇移动
                    dir = event
                elif event == window.EVENT_STOP:#空格键暂停和继续
                    if stop == False:
                        stop = True
                    else:
                        stop = False
                    #print(dir, snake.s_life)
                elif event == window.EVENT_ADD:  # F1速度加
                    speed = speed + 1
                elif event == window.EVENT_SUB:  # F2速度减
                    speed = speed - 1
                elif event == window.EVENT_KING:  # F3无敌模式
                    if snake.s_king == True:
                        snake.s_king = False
                    else:
                        snake.s_king = True
            if snake.s_life != snake.SNAKE_LIFE: # 如果贪吃蛇死亡则退出游戏
                window.quit()
            if score != snake.s_score: # 每得10分速度增加一个等级
                score = snake.s_score
                if(score % 10 == 0):
                    speed = speed + 1
    

    五、程序运行截图



    六、项目内文件截图

    项目内文件截图

    python贪吃蛇

    代码地址如下:
    http://www.demodashi.com/demo/13335.html

    注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

  • 相关阅读:
    微信小程序 API 界面 (2)
    微信小程序 API 界面(1)
    微信小程序 API 路由
    微信小程序 API 基础
    微信小程序image组件
    navigator组件(相当于a标签)
    functional-page-navigator 组件
    node.js配置环境变量
    animate(动画)框架 和 swiper (轮播)框架 的使用
    SwipeRefreshLayout的使用,下拉刷新
  • 原文地址:https://www.cnblogs.com/demodashi/p/9443021.html
Copyright © 2020-2023  润新知