Python programming to realize the snake game

Not much to say, the detailed ideas are in the mind map and code comments, very detailed, the modules used are pygame, sys, os, random to
install pygame: pip install pygame
Insert picture description here

The detailed code is as follows:

# -*- 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()


Program running effect:
Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_44901564/article/details/111590955
Recommended