python编程实现贪吃蛇游戏

话不多说,详细的思路都在思维导图与代码注释里面了,很详细, 使用模块有pygame,sys, os, random
安装pygame: pip install pygame
在这里插入图片描述

详细代码如下:

# -*- coding: utf-8 -*-
import pygame
from pygame.locals import *
from sys import exit
from os import environ
from random import randrange

class GreedySnakeGame:
    def __init__(self):
        pygame.init()                                           # 初始化pygame库
        environ['SDL_VIDEO_CENTERED'] = '1'                     # 设置窗口居中显示
        size = width, height = 840, 580                         # 定义窗口大小
        self.window = pygame.display.set_mode(size)             # 显示窗口(实例变量)
        pygame.display.set_caption("贪吃蛇 V1")                  # 设置窗口标题
        self.speed = pygame.time.Clock()                        # 定义变量方便控制游戏进行速度(实例变量)
        self.game_speed = 2                                     # 定义游戏初始的详细速度(实例变量)
        self.score = 0                                          # 定义游戏初始分数(实例变量)
        self.difficulty = 0                                     # 定义游戏初始难度等级(实例变量)
        self.black = pygame.Color(0, 0, 0)                      # 定义颜色变量:黑色(实例变量)
        self.white = pygame.Color(255, 255, 255, 255)           # 定义颜色变量:白色(实例变量)
        self.red = pygame.Color(255, 0, 0)                      # 定义颜色变量:红色(实例变量)
        self.grey = pygame.Color(150, 150, 150)                 # 定义颜色变量:灰色(实例变量)
        self.blue = pygame.Color(0, 0, 255)                     # 定义颜色变量:蓝色(实例变量)
        self.cyan_blue = pygame.Color(0, 128, 128)              # 定义颜色变量:青色(实例变量)
        self.green = pygame.Color(0, 100, 0)                    # 定义颜色变量:绿色(实例变量)
        self.basic_font = pygame.font.SysFont('arial', 100)     # 定义游戏界面使用的字体1(实例变量)
        self.basic_font1 = pygame.font.SysFont('arial', 35)     # 定义游戏界面使用的字体2(实例变量)
        self.stop = False                                       # 定义控制游戏暂停的变量(实例变量)

    def games_start(self):                                      # 游戏开始
        snake_head = [60, 100]                                  # 初始化贪吃蛇头部位置
        snake_body = [[60, 100], [40, 100], [20, 100]]          # 初始化贪吃蛇身体的长度(这里以20*20为一个小格子)
        direction = "right"                                     # 初始化贪吃蛇前进方向
        food = [300, 300]                                       # 初始化食物的位置
        food_flag = 1                                           # 初始化食物的标记,1表示还没有被吃掉

        '''进入游戏主循环'''
        while True:
            for event in pygame.event.get():                    # 遍历所有的事件
                if event.type == QUIT:                          # 如果单击关闭窗口,则退出
                    pygame.quit()
                    exit(0)
                if event.type == KEYDOWN:                       # 表示按下键盘的事件(按下键盘时),pygame.KEYUP表示释放键盘时
                    if (event.key == K_UP or event.key == K_w) and direction != 'down': # 贪吃蛇原本的方向是向下,直接方向转为向上不合理,所以这里把DOWN排除, event.key表示获取的按键, K_UP表示向上箭头,可以查看中文文档
                        direction = 'up'
                    if (event.key == K_DOWN or event.key == K_s) and direction != 'up':
                        direction = 'down'
                    if (event.key == K_LEFT or event.key == K_a) and direction != 'right':
                        direction = 'left'
                    if (event.key == K_RIGHT or event.key == K_d) and direction != 'left':
                        direction = 'right'
                    if event.key == K_ESCAPE:   # 按ESC键退出游戏
                        pygame.quit()
                        exit(0)
                    if event.key == K_SPACE:    # 按空格键则暂停
                        self.stop = True
                        while self.stop:
                            for event in pygame.event.get():
                                if event.type == QUIT:
                                    pygame.quit()
                                    exit(0)
                                if event.type == KEYDOWN:
                                    if event.key == K_SPACE:	# 再次按下空格键结束暂停状态
                                        self.stop = False

            '''根据键盘输入的方向,改变贪吃蛇的头部,进行转弯操作,这里不可以用elif,会报错'''
            if direction == 'left':
                snake_head[0] -= 20
            if direction == 'right':
                snake_head[0] += 20
            if direction == 'up':
                snake_head[1] -= 20
            if direction == 'down':
                snake_head[1] += 20

            snake_body.insert(0, list(snake_head))                                  # 将蛇的头部当前的位置加入到贪吃蛇身体的列表中,插在第一个位置

            # 判断食物是否被吃掉
            if snake_head[0] == food[0] and snake_head[1] == food[1]:
                food_flag = 0
            else:
                snake_body.pop()                                                    # 如果没有吃掉食物, 贪吃蛇加入了一个蛇头,就是去掉一个蛇尾,这样贪吃蛇肉眼看起来是在前进

            if food_flag == 0:                                                      # 如果食物被吃掉了,则生成新的食物,# 随机生成食物的坐标x, y
                food_list = []
                for weight_element in range(0, 620, 20):
                    for height_element in range(0, 560, 20):
                        food_list.append([weight_element, height_element])
                for coordinate in snake_body:
                    if coordinate in food_list:
                        food_list.remove(coordinate)                                # 移除身体的坐标,保证生成的食物不会出现在蛇的身体上
                food = food_list[randrange(0, len(food_list))]
                food_flag = 1                                                       # 生成食物之后需要重置食物标记

            '''这里需要每一次循环都要重新填充窗口颜色,因为下面的各个填充区域填充颜色之后会改变窗口原本的颜色,如果不重新填充颜色,则贪吃蛇移动之后的地方颜色不会自动重置'''
            self.window.fill(self.cyan_blue)                                        # 填充窗口背景颜色
            pygame.draw.rect(self.window, self.grey, Rect(640, 0, 200, 580))        # 绘制分数,游戏难度显示区域

            self.draw_snake(snake_body)                                             # 画出贪吃蛇
            self.draw_food(food)                                                    # 画出食物
            current_score = len(snake_body) - 3                                     # 获取当前得分,需要减去原来的长度
            self.display_score(current_score)                                       # 显示当前分数
            if current_score - self.score == 5:                                     # 这部分只要是控制游戏速度和游戏难度等级
                self.score = current_score                                          # 将当前分数复制给score,方便下次计算
                self.game_speed += 0.1                                              # 游戏速度增加0.1,假设原来每秒移动3,则现在每秒移动3.1
                self.game_speed = round(self.game_speed, 1)                         # 保证浮点数只保留一位小数
                self.difficulty += 1

            self.display_game_speed(self.game_speed)                                # 显示游戏详细速度
            self.display_difficulty(self.difficulty)                                # 显示游戏难度等级
            self.display_about()                                                    # 显示游戏说明

            pygame.display.flip()                                                   # 刷新pygame显示层
            self.speed.tick(self.game_speed)                                        # 游戏帧数,控制游戏速度

            '''判断游戏结束'''
            # 碰触边界
            if snake_head[0] < 0 or snake_head[0] > 620:                            # 方块宽度长宽都是20,横坐标为520的时候,就已经触碰边界了,超过520说明撞墙了
                self.display_game_over()
            if snake_head[1] < 0 or snake_head[1] > 560:
                self.display_game_over()
            # 碰触自己
            for element in snake_body[1:]:                                          # 第一个是头,不可能头咬头,所以先排除
                if snake_head[0] == element[0] and snake_head[1] == element[1]:     # 坐标相同说明咬到身体了
                    self.display_game_over()

    def draw_snake(self, snake_body):                                                           # 画蛇的方法
        for element in snake_body:                                                              # 遍历蛇的身体的坐标,依次打印出来
            if element[0] < 640:                                                                # 限制横坐标必须小于640,不限制当蛇头撞墙时会穿过一个坐标长度,不合理
                pygame.draw.rect(self.window, self.black, Rect(element[0], element[1], 20, 20)) # 20, 20表示的是矩形的宽和高

    def draw_food(self, food):                                                                  # 打印出食物的方法
        pygame.draw.rect(self.window, self.red, Rect(food[0], food[1], 20, 20))                 # 打印食物

    def display_score(self, score):                                                             # 打印出当前得分的方法
        score_title = self.basic_font1.render(" score:", True, self.green)                      # 绘制文本“分数”两个字
        score_title_rect = score_title.get_rect()                                               # 获取矩形区域
        score_title_rect.midtop = (700, 30)                                                     # 设置文本位置
        self.window.blit(score_title, score_title_rect)                                         # 绑定设置到窗口

        score_text = self.basic_font1.render('%s' % (score), True, self.red)                    # 绘制具体分数
        score_text_rect = score_text.get_rect()                                                 # 获取矩形区域
        score_text_rect.midtop = (760, 30)                                                      # 设置分数位置
        self.window.blit(score_text, score_text_rect)                                           # 绑定设置到窗口

    def display_game_speed(self, game_speed):                                                   # 显示游戏速度的方法
        detailed_speed_title = self.basic_font1.render("speed:", True, self.green)
        detailed_speed_rect = detailed_speed_title.get_rect()
        detailed_speed_rect.midtop = (700, 70)
        self.window.blit(detailed_speed_title, detailed_speed_rect)

        game_speed_text = self.basic_font1.render('%s' % (game_speed), True, self.red)
        game_speed_rect = game_speed_text.get_rect()
        game_speed_rect.midtop = (760, 70)
        self.window.blit(game_speed_text, game_speed_rect)

    def display_difficulty(self, difficulty):                                                   # 显示游戏难度级别的方法
        difficulty_title = self.basic_font1.render("level:", True, self.green)
        difficulty_title_rect = difficulty_title.get_rect()
        difficulty_title_rect.midtop = (710, 110)
        self.window.blit(difficulty_title, difficulty_title_rect)

        difficulty_text = self.basic_font1.render('%s' % (difficulty), True, self.red)
        difficulty_text_rect = difficulty_text.get_rect()
        difficulty_text_rect.midtop = (760, 110)
        self.window.blit(difficulty_text, difficulty_text_rect)

    def display_about(self):                                                                    # 显示游戏相关信息的方法
        #rule_stop = self.basic_font1.render("stop: space", True, self.green)
        #rule_stop_rect = rule_stop.get_rect()
        #rule_stop_rect.midtop = (720, 200)
        #self.window.blit(rule_stop, rule_stop_rect)

        about = self.basic_font1.render("Author: WYP", True, self.green)
        about_rect = about.get_rect()
        about_rect.midtop = (730, 230)
        self.window.blit(about, about_rect)

    def display_game_over(self):                                                                # 游戏结束的处理方法
        game_over_text = self.basic_font.render('Game Over!', True, self.grey)
        game_over_rect = game_over_text.get_rect()
        game_over_rect.midtop = (330, 230)
        self.window.blit(game_over_text, game_over_rect)

        tips1 = self.basic_font1.render('Tips1: Press Tab to restart', True, self.blue)         # 提示1:Game Overy后按Tab键重新开始游戏
        tips1_rect = tips1.get_rect()
        tips1_rect.midtop = (320, 80)
        self.window.blit(tips1, tips1_rect)

        tips2 = self.basic_font1.render('Tips2: Click X or press Esc to exit', True, self.blue) # 提示2:
        tips2_rect = tips2.get_rect()
        tips2_rect.midtop = (320, 130)
        self.window.blit(tips2, tips2_rect)

        pygame.display.flip()                   # 刷新Pygame的显示层
        while True:
            for event in pygame.event.get():    # 遍历所有事件
                if event.type == QUIT:          # 点击X关闭窗口,退出游戏
                    pygame.quit()
                    exit(0)
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:   # 按ESC键退出游戏
                        pygame.quit()
                        exit(0)
                    if event.key == K_TAB:      # 按Tab键重新开始游戏
                        self.game_speed = 2     # 还原游戏的速度,不能为0,0是极速,一瞬间撞墙
                        self.difficulty = 0     # 还原游戏的难度等级
                        self.games_start()

if __name__ == '__main__':
    GreedySnakeGame().games_start()


程序运行效果:
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44901564/article/details/111590955