初学者学习使用pygame制作贪吃蛇的研发记录

        由于我们学校的工作室要求在寒假必须完成一个项目,出于想摆烂的心态我们选择了用pygame完成贪吃蛇小游戏,这是个很有意思的过程,我决定将它记录下来。

        一开始我没有使用过pygame这个库,于是在pygame的官方文档中流离了一段时间之后决定还是直接开抄吧,于是打开了网页开始搜索贪吃蛇的制作过程,先是在国内搜索了一番,发现了很多有意思的也有很多很详细的,但是发现一旦实际运行起来总会报错,而看着一大堆的内容我还是选择放弃,找点国外的借鉴一下,于是我找到了这个网站:Snake Game in Python | Snake Game Program using Pygame | Edureka

        这个网站上有很详细的解读,是分每一个部分进行解释一步步的得到一个结果,相比于其他的,这个的流畅度以及美观程度我都更加喜欢,下面是这个的代码:

import pygame
import time
import random
 
pygame.init()
 
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
 
dis_width = 600
dis_height = 400
 
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Snake Game by Edureka')
 
clock = pygame.time.Clock()
 
snake_block = 10
snake_speed = 15
 
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
 
 
def Your_score(score):
    value = score_font.render("Your Score: " + str(score), True, yellow)
    dis.blit(value, [0, 0])
 
 
 
def our_snake(snake_block, snake_list):
    for x in snake_list:
        pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
 
 
def message(msg, color):
    mesg = font_style.render(msg, True, color)
    dis.blit(mesg, [dis_width / 6, dis_height / 3])
 
 
def gameLoop():
    game_over = False
    game_close = False
 
    x1 = dis_width / 2
    y1 = dis_height / 2
 
    x1_change = 0
    y1_change = 0
 
    snake_List = []
    Length_of_snake = 1
 
    foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
    foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
 
    while not game_over:
 
        while game_close == True:
            dis.fill(blue)
            message("You Lost! Press C-Play Again or Q-Quit", red)
            Your_score(Length_of_snake - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        gameLoop()
 
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = snake_block
                    x1_change = 0
 
        if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
            game_close = True
        x1 += x1_change
        y1 += y1_change
        dis.fill(blue)
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_List.append(snake_Head)
        if len(snake_List) > Length_of_snake:
            del snake_List[0]
 
        for x in snake_List[:-1]:
            if x == snake_Head:
                game_close = True
 
        our_snake(snake_block, snake_List)
        Your_score(Length_of_snake - 1)
 
        pygame.display.update()
 
        if x1 == foodx and y1 == foody:
            foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
            foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
            Length_of_snake += 1
 
        clock.tick(snake_speed)
 
    pygame.quit()
    quit()
 
 
gameLoop()

 这个代码一运行就可以成功,得出的效果是这样的

在终端安装了pygame这个库之后就可以运行,而实际使用后可以知道这个程序有几个很明显的bug,即如下的几个:

        1.中文无法在窗口中显示,这个比较容易解决,后面会详细解说

        2.蛇的生存范围并不是框内,需要绘制一个框使得用户了解生存范围

        3.食物有可能会长在蛇的身上

        4.最难搞的也是这个,当长度为2时,蛇回咬,也就是自己咬自己系统是不会判断为游戏结束             的

        先解决第一个bug,在观察后可以发现这个字体就是"Your Score"很明显不是普通的字体,在搜索后得到的解决方法是,设置中文的字体,再调用显示字体的函数即可在窗口显示字体,下面是解决方案的代码:

#字体参数设置
font_style = pygame.font.SysFont(['华文宋体', "bahnschrift"], 25)
score_font = pygame.font.SysFont('华文宋体', 35)
lost_style = pygame.font.SysFont('华文宋体', 50)

a = pygame.font.get_fonts()

#速度输出函数
def Your_speed(speed):
    s = score_font.render("你的速度:{}".format(speed),True,blue)
    dis.blit(s,[400,0])
    pygame.display.update()

        接下来是第二个bug,我们发现在代码中判断死亡的两个判断语句,其中下面的这个是判断是否出界挂掉的语句(并非网站上的代码,这个是我的成果里面的代码,只需要看判断的条件即可 ):

        if snake.x1 > dis_width-70 or snake.x1 < 60 or snake.y1 > dis_height-60 or snake.y1 < 70:
            pygame.mixer.Sound.play(end_music)
            eat=0
            game_close = True

这个是我们需要调整的主要位置,那么如何在界面中显示一个框呢?在搜索后可以发现在pygame中存在一个这样的函数:

pygame.draw.rect(dis, black, [x, y, block, block],width)

        第一个参数dis,是需要显示的屏幕,第二参数是颜色,需要注意的是这个参数需要载入的不是像black这样的,而是使用RGB格式命名的颜色,在总代码的开头就有这个东西,需要的可以看,最后的则是坐标,前两个为这个矩形的开始的坐标,就是左上角的点的位置,后面两个则是这个矩形覆盖的范围,这里的block是蛇的大小,第四个参数则是框的线的宽度,如果是要填充整个矩形的话不输入即可。在经过了极其痛苦的调参后终于得到比较正确的内容:

#框
pygame.draw.rect(dis, (0, 0, 0), [50,60,600,400],1)

效果如图所示:

        这个是最终的效果,这里只需要注意框即可,事实上这个bug到这里并没有完全的解决,在实际运行时会有蛇出框了仍然没有判定,而在缩短后则会出现在最顶层的一两行的位置转弯就会死亡,因此调整了很长一段时间,我想出的方法并没有解决这个问题,而是掩盖了这个问题,把这个问题在绘制蛇的部分解决了,下面是绘制蛇的部分的代码,由于本人也不是很了解为什么这样就解决了这里只放上代码:

def our_snake(self,game_close,x1,y1,block,snake_list):
    if(game_close==False):
        if(60<=y1<=460):
            pygame.draw.rect(dis, red, [x1, y1, block, block])
            for x in snake_list[1:]:
                pygame.draw.rect(dis, black, [x[0], x[1], block, block])
            pygame.display.update()

        在解决了这个bug后我们再解决第三个bug,事实上这个bug反而更容易解决,只需要判断是不是在身上,在就再生成直到没有重复,问题在食物的显示上,修改后的代码如下:

    def __init__(self,snake_block,snake,List):
        same=False
        self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
        self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
        for i in snake.List:
            if i==[self.foodx,self.foody]:
                same=True
        self.type=random.randint(0,3)
        self.Head=[self.foodx,self.foody,self.type]
        while same:
            self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
            self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0    
            for i in snake.List:
                if i==[self.foodx,self.foody]:
                    same=True

        self.block = snake_block

        由于最后写的是类的,而函数的我也没有保存下来,这个代码里面那个while same那段就是解决食物出现在蛇的身上的问题。

         解决了这个bug后解决最后的一个bug,长度为2时可以回头咬的问题,这个是bug的位置:

        for x in snake.List[:-1]:
            if x == snake.Head:
                pygame.mixer.Sound.play(end_music)            
                game_close = True
                eat=1

        代码很简单,问题就在snake.List[:-1]身上,这个逻辑我尝试了很多方式去修改,结果依然是以失败告终,而我的方法依然是没有解决这个问题,而是掩盖了这个问题,其实有其他的做法比如在一开始就设置蛇的长度为3之类的就可以解决这个问题,也有直接限死,不允许回头,但是我想用自己的方法解决,解决方法也是在蛇的那里,也就是第二个bug的解决方案的代码上:

    def our_snake(self,game_close,x1,y1,block,snake_list):
        if(game_close==False):
            if(60<=y1<=460):
                pygame.draw.rect(dis, red, [x1, y1, block, block])
                for x in snake_list[1:]:
                    pygame.draw.rect(dis, black, [x[0], x[1], block, block])
                pygame.display.update()

        这样调整后即可得到这样的结果,一开始的时候蛇的头是红色的:

        在食用了第一个食物后蛇的颜色则会变成正常的黑色:
 

        此时如果再食用一个食物,此时的长度就会变为2,而实际上它的长度是3,此时就可以跳过那个两个的bug,自己吃自己的时候就会判断死亡。

        除了这三个bug之外,我对这个游戏加了一个小机制,就是吃了食物之后会加速,实现也是很简单,而这个也是这个程序的一个很大的缺陷,就是使用帧率来显示蛇的速度,修改后的代码如下:

clock.tick(snake.speed+1.5*snake.length)

         这个就没什么好解释的吧,刚刚笔者找到了之前的函数版贪吃蛇的代码,在解决了上述的bug后得出的结果总代码如下:

import pygame
import time
import random
import sys
#初始化pygame
pygame.init()

#颜色参数
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
ching = (0, 128, 128)
 
#屏幕大小参数
dis_width = 700
dis_height = 500


#屏幕大小设置
dis = pygame.display.set_mode((dis_width, dis_height))
#(全屏)dis = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.display.set_caption('贪吃蛇小游戏')
pygame.display.set_palette

#帧数设置
clock = pygame.time.Clock()

#字体参数设置
font_style = pygame.font.SysFont(['华文宋体', "bahnschrift"], 25)
score_font = pygame.font.SysFont('华文宋体', 35)
lost_style = pygame.font.SysFont('华文宋体', 50)

a = pygame.font.get_fonts()

#得分输出函数
def Your_score(score):
    value = score_font.render("你的分数:" + str(score), True, blue)
    dis.blit(value, [0, 0])
    pygame.display.update()

#蛇的大小和速度参数
snake_block = 10
snake_speed = 15


#绘制蛇函数       
def our_snake(game_close,x1,y1,snake_block, snake_list):
    if(game_close==False):
        if(60<=y1<=460):
            pygame.draw.rect(dis, red, [x1, y1, snake_block, snake_block])
            for x in snake_list[1:]:
                pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
            pygame.display.update()

#消息输出函数
def message(msg, color, ft, pos):
    mesg = ft.render(msg, True, color)
    dis.blit(mesg, pos)

#主体函数
def gameLoop():

    game_over = False
    game_close = False
 
    #蛇的起始位置
    x1 = 80
    y1 = 80
 
    x1_change = 0
    y1_change = 0
 
    snake_List = []
    Length_of_snake = 1
    
    #食物出现的位置(10,60是框的位置)
    foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
    foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
 
    while not game_over:


    
        #挂掉之后
        while game_close == True:
            dis.fill(white)
            message("失败", red, lost_style, [dis_width / 2 - 50, dis_height / 3 - 25])
            message("接下来请按C键重新开始或者Q键退出游戏。", red, font_style, [dis_width / 2 - 9*25, dis_height / 3 + 25 + 1*25])
            if(eat==0):
                message("死因:创墙!",red, font_style, [280, dis_height / 3 - 50])
            if(eat==1):
                message("死因:自己咬自己!",red,font_style,[250, dis_height / 3 - 50])
            Your_score(Length_of_snake - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        gameLoop()

        #移动(如果w,a,s,d之类的chang就对应相应的值,移动长度为snake_block,即为蛇的大小)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = snake_block
                    x1_change = 0
 
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    game_over = True
                    game_close = False
                if event.key == pygame.K_c:
                    gameLoop()        
        #死亡条件
        if x1 > dis_width-70 or x1 < 60 or y1 > dis_height-60 or y1 < 70:
            eat=0
            game_close = True

            

        #if x1>dis_width-50 or x1<50 or y1 >= dis_height+50 or y1 < 70:
            #game_close=True
        
        #更新蛇头的位置
        x1 += x1_change
        y1 += y1_change
        
        #设置颜色
        dis.fill(white)
        
        #显示食物
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
        
        #框
        pygame.draw.rect(dis, (0, 0, 0), [50,60,600,400],1)
        
        #把蛇头的坐标加入至列表中
        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_List.append(snake_Head)
        print("Head:({},{})".format(x1,y1))
        
        if len(snake_List) > Length_of_snake:
            del snake_List[0]
            print("已删除")
 
        #对于蛇的每个点若与蛇头重复则寄,除头外(有第二个的bug)
        for x in snake_List[:-1]:
            if x == snake_Head:
                game_close = True
                eat=1

                


 
        our_snake(game_close,x1,y1,snake_block, snake_List)
        Your_score(Length_of_snake - 1)
 
        pygame.display.update()
 
        if x1 == foodx and y1 == foody:
            foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
            foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
            Length_of_snake += 1
        
        #用帧率设置蛇的移动速度(目前倍速为2.5长度加原有速度)
        clock.tick(snake_speed+2.5*Length_of_snake)
 
    pygame.display.quit()

#开始运行
gameLoop()

        这个是函数版的,而在仔细看了项目的文档后才发现是需要用类的版本,修改难度也不大,下面的这个则是用类来实现的代码:

#基本内容
import pygame
import random
#初始化pygame
pygame.init()

#颜色参数
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
ching = (0, 128, 128)
 
#屏幕大小参数
dis_width = 700
dis_height = 500


#屏幕大小设置
dis = pygame.display.set_mode((dis_width, dis_height))
#(全屏)dis = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.display.set_caption('贪吃蛇小游戏')
pygame.display.set_palette

#帧数设置
clock = pygame.time.Clock()

#字体参数设置
font_style = pygame.font.SysFont(['华文宋体', "bahnschrift"], 25)
score_font = pygame.font.SysFont('华文宋体', 35)
lost_style = pygame.font.SysFont('华文宋体', 50)

a = pygame.font.get_fonts()

#得分输出函数
def Your_score(score):
    value = score_font.render("你的分数:" + str(score), True, blue)
    dis.blit(value, [0, 0])
    pygame.display.update()

#消息输出函数
def message(msg, color, ft, pos):
    mesg = ft.render(msg, True, color)
    dis.blit(mesg, pos)


class Snake:
   
    def __init__(self,x1,y1):
        self.x1=x1
        self.y1=y1
        self.block=10
        self.speed=15 
        self.length=1
        self.List=[]
        self.Head=[]
    def our_snake(self,game_close,x1,y1,block,snake_list):
        if(game_close==False):
            if(60<=y1<=460):
                pygame.draw.rect(dis, red, [x1, y1, block, block])
                for x in snake_list[1:]:
                    pygame.draw.rect(dis, black, [x[0], x[1], block, block])
                pygame.display.update()

class Food:
    def __init__(self,snake_block):
        self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
        self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
        self.block = snake_block
        print("调用构造函数")

    def appear(self):
        pygame.draw.rect(dis, green, [self.foodx,self.foody, self.block, self.block])
        print("已调用,坐标({},{})".format(self.foodx,self.foody))

def gameLoop():

    x1_change=0
    y1_change=0

    game_over = False
    game_close = False

    snake=Snake(80,80)
    food=Food(snake.block)

    while not game_over:

        while game_close==True:
            dis.fill(white)
            message("失败", red, lost_style, [dis_width / 2 - 50, dis_height / 3 - 25])
            message("接下来请按C键重新开始或者Q键退出游戏。", red, font_style, [dis_width / 2 - 9*25, dis_height / 3 + 25 + 1*25])
            if(eat==0):
                message("死因:创墙!",red, font_style, [280, dis_height / 3 - 50])
            if(eat==1):
                message("死因:自己咬自己!",red,font_style,[250, dis_height / 3 - 50])
            Your_score(snake.length - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        gameLoop()
        
        #移动(如果w,a,s,d之类的chang就对应相应的值,移动长度为snake.block,即为蛇的大小)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -snake.block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = snake.block
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -snake.block
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = snake.block
                    x1_change = 0       

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    game_over = True
                    game_close = False
                if event.key == pygame.K_c:
                    gameLoop()      

        if snake.x1 > dis_width-70 or snake.x1 < 60 or snake.y1 > dis_height-60 or snake.y1 < 70:
            eat=0
            game_close = True

        snake.x1 += x1_change
        snake.y1 += y1_change

        #设置颜色
        dis.fill(white)
        
        food.appear()

        #框
        pygame.draw.rect(dis, (0, 0, 0), [50,60,600,400],1)

        snake.Head=[]
        snake.Head.append(snake.x1)
        snake.Head.append(snake.y1)
        snake.List.append(snake.Head)
        print("Head:({},{})".format(snake.x1,snake.y1))

        if len(snake.List) > snake.length:
            del snake.List[0]
            print("已删除")

        print("snake_List:{}".format(snake.List))

        #对于蛇的每个点若与蛇头重复则寄,除头外(有第二个的bug)
        for x in snake.List[:-1]:
            if x == snake.Head:
                game_close = True
                eat=1
        
        snake.our_snake(game_close,snake.x1,snake.y1,snake.block,snake.List)
        Your_score(snake.length-1)

        pygame.display.update()

        if snake.x1 == food.foodx and snake.y1 == food.foody:
            food.__init__(snake.block)
            food.appear()
            snake.length+=1
            print(snake.length)
        
        clock.tick(snake.speed+2.5*snake.length)

    pygame.display.quit()


gameLoop()
                


    

        这个也没什么难度就不再赘述了,下面说一下进一步的改进,即在游戏的开始前让用户输入想要的难度。而实现这个需求的方法也有很多,而我个人喜欢用PySimpleGui来实现,由于之前尝试过使用PySimGui,比较熟悉,有兴趣的可以看看我之前发的名为工具箱的博客。

        具体逻辑也很容易,只需要获取用户需要的难度,再把他们需要的难度即数值代入到速度,即帧率的部分,然后再在主函数gameLoop执行之调用即可,具体代码如下:

hard=1.5

def start():
    sg.theme("SandyBeach")
    layout=[[sg.Text("难度设置为(建议为由1到5):",font=("微软雅黑",12)),sg.InputText(key="hard",size=(10,1)),sg.Button("确定")]]
    window=sg.Window("选择难度",layout,font=("微软雅黑",15),default_element_size=(500,100))
    while True:
        event,values=window.read()
        if event in ("确定"):
            hard=eval(values["hard"])
            print(hard)
            break
    window.close()
    return hard
...
...
def gameLoop():
    snake=Snake(80,80)
    food=Food(snake.block,snake)

    hard=start()

    while not game_over:
       ...
       clock.tick(snake.speed+hard*snake.length)

 效果如下图所示:

        这个做法的问题也很明显,就是太丑了,这个框和后面的有很突兀的感觉,这个后面也会改,而我在这个版本还进行了一些小的修改,就是加入了音乐,让它在吃食物和挂掉的时候会播放音乐,这个也很容易实现,只需要在判断为死的同时播放音乐,具体实现如下代码所示:

pygame.mixer.init()
#音乐
eat_music=pygame.mixer.Sound("eat.wav")
end_music=pygame.mixer.Sound("end.wav")
....
....
        if snake.x1 == food.foodx and snake.y1 == food.foody:
            pygame.mixer.Sound.play(eat_music)
            food.__init__(snake.block,snake)
            food.appear()
            snake.length+=1
        for x in snake.List[:-1]:
            if x == snake.Head:
                pygame.mixer.Sound.play(end_music)            
                game_close = True
                eat=1
        if snake.x1 > dis_width-70 or snake.x1 < 60 or snake.y1 > dis_height-60 or snake.y1 < 70:
            pygame.mixer.Sound.play(end_music)
            eat=0
            game_close = True

下面是这个版本的完整代码:

#基本内容
import pygame
import random
import PySimpleGUI as sg
#初始化pygame
pygame.init()
pygame.mixer.init()

#颜色参数
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
ching = (0, 128, 128)
 
#屏幕大小参数
dis_width = 700
dis_height = 500

#音乐
eat_music=pygame.mixer.Sound("eat.wav")
end_music=pygame.mixer.Sound("end.wav")


#屏幕大小设置
dis = pygame.display.set_mode((dis_width, dis_height))
#(全屏)dis = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.display.set_caption('贪吃蛇小游戏')
pygame.display.set_palette

#帧数设置
clock = pygame.time.Clock()

#字体参数设置
font_style = pygame.font.SysFont(['华文宋体', "bahnschrift"], 25)
score_font = pygame.font.SysFont('华文宋体', 35)
lost_style = pygame.font.SysFont('华文宋体', 50)

a = pygame.font.get_fonts()

#得分输出函数
def Your_score(score):
    value = score_font.render("你的分数:" + str(score), True, blue)
    dis.blit(value, [0, 0])
    pygame.display.update()

#消息输出函数
def message(msg, color, ft, pos):
    mesg = ft.render(msg, True, color)
    dis.blit(mesg, pos)

hard=1.5

def start():
    sg.theme("SandyBeach")
    layout=[[sg.Text("难度设置为(建议为由1到5):",font=("微软雅黑",12)),sg.InputText(key="hard",size=(10,1)),sg.Button("确定")]]
    window=sg.Window("选择难度",layout,font=("微软雅黑",15),default_element_size=(500,100))
    while True:
        event,values=window.read()
        if event in ("确定"):
            hard=eval(values["hard"])
            print(hard)
            break
    window.close()
    return hard


class Snake:
   
    def __init__(self,x1,y1):
        self.x1=x1
        self.y1=y1
        self.block=10
        self.speed=15 
        self.length=1
        self.List=[]
        self.Head=[]
    def our_snake(self,game_close,x1,y1,block,snake_list):
        if(game_close==False):
            if(60<=y1<=460):
                pygame.draw.rect(dis, red, [x1, y1, block, block])
                for x in snake_list[1:]:
                    pygame.draw.rect(dis, black, [x[0], x[1], block, block])
                pygame.display.update()

class Food:
    def __init__(self,snake_block,snake):
        same=False
        self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
        self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
        for i in snake.List:
            if i==[self.foodx,self.foody]:
                same=True
        while same:
            self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
            self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0    
            for i in snake.List:
                if i==[self.foodx,self.foody]:
                    same=True

        self.block = snake_block

    def appear(self):
        pygame.draw.rect(dis, green, [self.foodx,self.foody, self.block, self.block])

def gameLoop():

    x1_change=0
    y1_change=0

    game_over = False
    game_close = False

    snake=Snake(80,80)
    food=Food(snake.block,snake)

    hard=start()

    while not game_over:

        while game_close==True:
            dis.fill(white)
            message("失败", red, lost_style, [dis_width / 2 - 50, dis_height / 3 - 25])
            message("接下来请按C键重新开始或者Q键退出游戏。", red, font_style, [dis_width / 2 - 9*25, dis_height / 3 + 25 + 1*25])
            if(eat==0):
                message("死因:创墙!",red, font_style, [280, dis_height / 3 - 50])
            if(eat==1):
                message("死因:自己咬自己!",red,font_style,[250, dis_height / 3 - 50])
            Your_score(snake.length - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        gameLoop()
        
        #移动(如果w,a,s,d之类的chang就对应相应的值,移动长度为snake.block,即为蛇的大小)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -snake.block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = snake.block
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -snake.block
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = snake.block
                    x1_change = 0       

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    game_over = True
                    game_close = False
                if event.key == pygame.K_c:
                    gameLoop()      

        if snake.x1 > dis_width-70 or snake.x1 < 60 or snake.y1 > dis_height-60 or snake.y1 < 70:
            pygame.mixer.Sound.play(end_music)
            eat=0
            game_close = True

        snake.x1 += x1_change
        snake.y1 += y1_change

        #设置颜色
        dis.fill(white)
        
        food.appear()

        #框
        pygame.draw.rect(dis, (0, 0, 0), [50,60,600,400],1)

        snake.Head=[]
        snake.Head.append(snake.x1)
        snake.Head.append(snake.y1)
        snake.List.append(snake.Head)

        if len(snake.List) > snake.length:
            del snake.List[0]


        #对于蛇的每个点若与蛇头重复则寄,除头外(有第二个的bug)
        for x in snake.List[:-1]:
            if x == snake.Head:
                pygame.mixer.Sound.play(end_music)            
                game_close = True
                eat=1
        
        snake.our_snake(game_close,snake.x1,snake.y1,snake.block,snake.List)
        Your_score(snake.length-1)

        pygame.display.update()

        if snake.x1 == food.foodx and snake.y1 == food.foody:
            pygame.mixer.Sound.play(eat_music)
            food.__init__(snake.block,snake)
            food.appear()
            snake.length+=1

        clock.tick(snake.speed+hard*snake.length)

    pygame.display.quit()


gameLoop()
                


    

 音效可以去各大平台下载。

下面的是最终的版本的改进:

1.把整个开始的界面覆盖了后面的蛇的部分

2.搞出了四个类型的食物,每种食物有不同的效果

3.吃食物不再生成食物,取而代之的是每一段时间生成一个食物

(由于写了这么多有点累了,想偷懒,就少解释了些,见谅啊)

第一个的解决方案就是放大放大再放大,最后的代码如下:

hard=1.5
bool=False
def start():
    sg.theme("SystemDefault")
    layout=[[sg.Text("         贪吃蛇小游戏",font=("微软雅黑",50))],
            [sg.Text()],
            [sg.Text("               ",font=("微软雅黑",40)),sg.Button("开始游戏",font=("微软雅黑",40))],
            [sg.Text()],
            [sg.Text("                ",font=("微软雅黑",40)),sg.Button("  备注  ",font=("微软雅黑",40))],
            [sg.Text()],
            [sg.Text("                ",font=("微软雅黑",40)),sg.Button("  退出  ",font=("微软雅黑",40))]]
    window=sg.Window("开始",layout,size=(800,600))
    while True:
        event,values=window.read()
        if event in(None,"  退出  "):
            exit()
        if event in ("开始游戏"):
            bool=True
            break
        if event in ("  备注  "):
            sg.Print("游戏有四种颜色的食物,且每过一段时间会生成新的食物:")
            sg.Print("1.绿色:分数加1,无特殊变化")
            sg.Print("2.红色:分数加2,但长度加2")
            sg.Print("3.蓝色:分数加1,速度增加")
            sg.Print("4.黄色:分数加1,速度降低")
            sg.Print("基础操作:键盘的上下左右键控制运动")
    window.close()
    return bool

if(start()):
    gameLoop()

        与之前的不同的是,这个并不是返回数字,而是返回一个布尔值,为的是在执行了开头后再执行主函数,效果如图:

虽然还是丑,但是相比与之前的好了些。。。

         第二个改进也很简单,就是在food这个类里面加个叫type的属性就可以了,然后再random一下就完事了,唯一比较麻烦的是显示和吃的部分,其实调多几次就解决了,代码如下所示:

class Food:
    def __init__(self,snake_block,snake,List):
        same=False
        self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
        self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
        for i in snake.List:
            if i==[self.foodx,self.foody]:
                same=True
        self.type=random.randint(0,3)
        self.Head=[self.foodx,self.foody,self.type]
        while same:
            self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
            self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0    
            for i in snake.List:
                if i==[self.foodx,self.foody]:
                    same=True

        self.block = snake_block

    def appear(self,list):
        for i in list:
            if i[2]==0:
                pygame.draw.rect(dis, green, [i[0],i[1], self.block, self.block])
            if i[2]==1:
                pygame.draw.rect(dis, purple, [i[0],i[1], self.block, self.block])
            if i[2]==2:
                pygame.draw.rect(dis, blue, [i[0],i[1], self.block, self.block])
            if i[2]==3:
                pygame.draw.rect(dis, yellow, [i[0],i[1], self.block, self.block])

        大概是这样,我记得好像还有其他地方也要改才可以完成,但是我忘记了就这样先,反正后面会放出全部代码。

        最后一个改动(终于准备搞完了!!!!)其实是难度最大的改动,首先,这个程序我前面也提到过,这是个用帧率控制速度的程序,于是它并不是每秒钟刷新的次数都相同,这就导致了如果想要使用pygame里面的time模块控制的话会有很混乱的结果,所以需要做一下小的操作,pygame里面有一个用来记录运行时间的函数,也就是这个:

pygame.time.get_ticks()

         这个的输出是毫秒(好像是)1s=1000x? 大概是这样,然后我们在运行的时候让他输出一下可以发现它的数字很大,不方便观察,直接除个1000,输出结果如下:

1.077
1.08
1.118
1.154
1.192
1.23
1.267
1.305
1.342
1.38
1.417
1.454
1.491
1.529
1.566
1.603
1.64
1.677
1.715
1.753
1.79
1.827
1.865
1.902
1.939
1.977
2.014
2.051
2.089
2.127
2.164
2.201
2.238
2.276
2.313
2.35
2.387
2.424
2.461
2.498
2.536
2.573
2.611
2.647
2.684
2.723
2.76
2.797
2.834
2.871
2.909
2.947
2.984
3.022
3.058
3.095
3.133
3.17
3.208
3.244
3.281
3.319
3.355
3.392
3.43
3.466
3.503
3.904
3.905
3.943
3.98

        观察后发现大概是0.038到0.037,如果是速度比较正常的话,后面随着速度的变化是有波动的,但是由于这个是由帧率控制的,会很不稳定,所以如果是用每33次记录一次(就是1秒)还是会有时候出现,有时候不出现,有时候出现一大堆,于是我们不能有这个方法,那么应该怎么解决呢?

        我的方法是:取整,把每次记录到的时间储存到长度为2的列表,当前与后的差为1的时候就是大概的1秒,然而这个1秒并不是准确的,是有误差的,且相比与上一次的操作,这个很明显要稳定的多,那么怎么实现把这些时间存在一个长度为2的列表中呢?我的方法是如下的代码所示:

        num=[0,0]
        bo = False

        n=int(pygame.time.get_ticks()/1000)
        if len(num)==1:
            num[1]=n
            bo1=False

        else:
            if bo1 == True:
                num[1]=n
                bo1 = False
                bo0 = True
            elif bo0 == True:
                num[0]=n
                bo0 = False
                bo1 = True            

        if num[1]-num[0] >= 1:
            bo = True
    
        if(bo):
            food.__init__(snake.block,snake,list)
            food.appear(list)
            list.append(food.Head)

        这样就完成了所有的改进,而由于本人的私人原因我实在是不想再搞这个了,于是对这个游戏的优化就只做到这里,不再优化,下面是效果:

 

代码如下所示:

#基本内容
import pygame
import random
import PySimpleGUI as sg
import time
#初始化pygame
pygame.init()
pygame.mixer.init()

#颜色参数
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
ching = (0, 128, 128)
purple = (160, 32, 240)
#屏幕大小参数
dis_width = 700
dis_height = 500

#音乐
eat_music=pygame.mixer.Sound("eat.wav")
end_music=pygame.mixer.Sound("end.wav")


#屏幕大小设置
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇小游戏')
pygame.display.set_palette

#帧数设置
clock = pygame.time.Clock()

#字体参数设置
font_style = pygame.font.SysFont(['华文宋体', "bahnschrift"], 25)
score_font = pygame.font.SysFont('华文宋体', 35)
lost_style = pygame.font.SysFont('华文宋体', 50)

a = pygame.font.get_fonts()

#速度输出函数
def Your_speed(speed):
    s = score_font.render("你的速度:{}".format(speed),True,blue)
    dis.blit(s,[400,0])
    pygame.display.update()


#得分输出函数
def Your_score(score):
    value = score_font.render("你的分数:" + str(score), True, blue)
    dis.blit(value, [0, 0])
    pygame.display.update()

#消息输出函数
def message(msg, color, ft, pos):
    mesg = ft.render(msg, True, color)
    dis.blit(mesg, pos)

hard=1.5
bool=False
def start():
    sg.theme("SystemDefault")
    layout=[[sg.Text("         贪吃蛇小游戏",font=("微软雅黑",50))],
            [sg.Text()],
            [sg.Text("               ",font=("微软雅黑",40)),sg.Button("开始游戏",font=("微软雅黑",40))],
            [sg.Text()],
            [sg.Text("                ",font=("微软雅黑",40)),sg.Button("  备注  ",font=("微软雅黑",40))],
            [sg.Text()],
            [sg.Text("                ",font=("微软雅黑",40)),sg.Button("  退出  ",font=("微软雅黑",40))]]
    window=sg.Window("开始",layout,size=(800,600))
    while True:
        event,values=window.read()
        if event in(None,"  退出  "):
            exit()
        if event in ("开始游戏"):
            bool=True
            break
        if event in ("  备注  "):
            sg.Print("游戏有四种颜色的食物,且每过一段时间会生成新的食物:")
            sg.Print("1.绿色:分数加1,无特殊变化")
            sg.Print("2.红色:分数加2,但长度加2")
            sg.Print("3.蓝色:分数加1,速度增加")
            sg.Print("4.黄色:分数加1,速度降低")
            sg.Print("基础操作:键盘的上下左右键控制运动")
    window.close()
    return bool


class Snake:
   
    def __init__(self,x1,y1):
        self.x1=x1
        self.y1=y1
        self.block=10
        self.speed=25 
        self.length=1
        self.List=[]
        self.Head=[]
    def our_snake(self,game_close,x1,y1,block,snake_list):
        if(game_close==False):
            if(60<=y1<=460):
                pygame.draw.rect(dis, red, [x1, y1, block, block])
                for x in snake_list[1:]:
                    pygame.draw.rect(dis, black, [x[0], x[1], block, block])
                pygame.display.update()

class Food:
    def __init__(self,snake_block,snake,List):
        same=False
        self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
        self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
        for i in snake.List:
            if i==[self.foodx,self.foody]:
                same=True
        self.type=random.randint(0,3)
        self.Head=[self.foodx,self.foody,self.type]
        while same:
            self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
            self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0    
            for i in snake.List:
                if i==[self.foodx,self.foody]:
                    same=True

        self.block = snake_block

    def appear(self,list):
        for i in list:
            if i[2]==0:
                pygame.draw.rect(dis, green, [i[0],i[1], self.block, self.block])
            if i[2]==1:
                pygame.draw.rect(dis, purple, [i[0],i[1], self.block, self.block])
            if i[2]==2:
                pygame.draw.rect(dis, blue, [i[0],i[1], self.block, self.block])
            if i[2]==3:
                pygame.draw.rect(dis, yellow, [i[0],i[1], self.block, self.block])

def gameLoop():
    
    list=[]
    num=[0,0]
    count=0
    s=[25]

    x1_change=0
    y1_change=0

    game_over = False
    game_close = False

    snake=Snake(80,80)
    food=Food(snake.block,snake,list)
    list.append(food.Head)
    bo0 = True
    bo1 = True

    while not game_over:


        while game_close==True:
            dis.fill(white)
            message("失败", red, lost_style, [dis_width / 2 - 50, dis_height / 3 - 25])
            message("接下来请按C键重新开始或者Q键退出游戏。", red, font_style, [dis_width / 2 - 9*25, dis_height / 3 + 25 + 1*25])
            if(eat==0):
                message("死因:创墙!",red, font_style, [280, dis_height / 3 - 50])
            if(eat==1):
                message("死因:自己咬自己!",red,font_style,[250, dis_height / 3 - 50])
            if(eat==2):
                message("死因:太慢!",red, font_style, [280, dis_height / 3 - 50])                
            Your_score(snake.length - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        pygame.quit()
                        quit()
                    if event.key == pygame.K_c:
                        gameLoop()
        
        #移动(如果w,a,s,d之类的chang就对应相应的值,移动长度为snake.block,即为蛇的大小)
        if pygame.event.peek():
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    game_over = True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:                 
                        x1_change = -snake.block
                        y1_change = 0
                    elif event.key == pygame.K_RIGHT:
                        x1_change = snake.block
                        y1_change = 0
                    elif event.key == pygame.K_UP:
                        y1_change = -snake.block
                        x1_change = 0
                    elif event.key == pygame.K_DOWN:
                        y1_change = snake.block
                        x1_change = 0  
             
        
        bo = False

        n=int(pygame.time.get_ticks()/1000)
        if len(num)==1:
            num[1]=n
            bo1=False

        else:
            if bo1 == True:
                num[1]=n
                bo1 = False
                bo0 = True
            elif bo0 == True:
                num[0]=n
                bo0 = False
                bo1 = True            

        if num[1]-num[0] >= 1:
            bo = True
    
        if(bo):
            food.__init__(snake.block,snake,list)
            food.appear(list)
            list.append(food.Head)
             	

        if snake.x1 > dis_width-70 or snake.x1 < 60 or snake.y1 > dis_height-60 or snake.y1 < 70:
            pygame.mixer.Sound.play(end_music)
            eat=0
            game_close = True

        snake.x1 += x1_change
        snake.y1 += y1_change

        #设置颜色
        dis.fill(white)
        
        food.appear(list)

        #框
        pygame.draw.rect(dis, (0, 0, 0), [50,60,600,400],1)

        snake.Head=[]
        snake.Head.append(snake.x1)
        snake.Head.append(snake.y1)
        snake.List.append(snake.Head)

        if len(snake.List) > snake.length:
            del snake.List[0]


        #对于蛇的每个点若与蛇头重复则寄,除头外(有第二个的bug)
        for x in snake.List[:-1]:
            if x == snake.Head:
                pygame.mixer.Sound.play(end_music)            
                game_close = True
                eat=1

        
        snake.our_snake(game_close,snake.x1,snake.y1,snake.block,snake.List)
        Your_score(snake.length-1)
        Your_speed(s[count])

        pygame.display.update()

        for i in list:
            if snake.x1 == i[0] and snake.y1 == i[1]:
                list.remove([i[0],i[1],i[2]])
                pygame.mixer.Sound.play(eat_music)
                if food.type==0:
                    snake.length+=1
                if food.type==1:
                    snake.length+=2
                if food.type==2:
                    snake.speed+=2
                    snake.length+=1
                if food.type==3:
                    snake.speed-=3
                    snake.length+=1



        clock.tick(snake.speed+hard*snake.length)
        s.append(snake.speed+hard*snake.length)
        count+=1

    pygame.display.quit()

if(start()):
    gameLoop()
                


    

2023.1.28 修改了几个bug,修改了颜色,把黄色变为其他颜色,另外修正了食物的bug,外加最多只可以生成5个食物的限制,修改后代码如下:

#基本内容
import pygame
import random
import PySimpleGUI as sg
import time
#初始化pygame
pygame.init()
pygame.mixer.init()

#颜色参数
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
ching = (0, 128, 128)
purple = (160, 32, 240)
grey = (128,128,128)
orange = (255,153,51)
#屏幕大小参数
dis_width = 700
dis_height = 500

#音乐
eat_music=pygame.mixer.Sound("eat.wav")
end_music=pygame.mixer.Sound("end.wav")


#屏幕大小设置
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇小游戏')
pygame.display.set_palette

#帧数设置
clock = pygame.time.Clock()

#字体参数设置
font_style = pygame.font.SysFont(['华文宋体', "bahnschrift"], 25)
score_font = pygame.font.SysFont('华文宋体', 35)
lost_style = pygame.font.SysFont('华文宋体', 50)

a = pygame.font.get_fonts()

#速度输出函数
def Your_speed(speed):
    s = score_font.render("你的速度:{}".format(speed),True,red)
    dis.blit(s,[400,0])
    pygame.display.update()


#得分输出函数
def Your_score(score):
    value = score_font.render("你的分数:" + str(score), True, blue)
    dis.blit(value, [0, 0])
    pygame.display.update()

#消息输出函数
def message(msg, color, ft, pos):
    mesg = ft.render(msg, True, color)
    dis.blit(mesg, pos)

hard=1.5
bool=False
def start():
    sg.theme("SystemDefault")
    layout=[[sg.Text("         贪吃蛇小游戏",font=("微软雅黑",50))],
            [sg.Text()],
            [sg.Text("               ",font=("微软雅黑",40)),sg.Button("开始游戏",font=("微软雅黑",40))],
            [sg.Text()],
            [sg.Text("                ",font=("微软雅黑",40)),sg.Button("  备注  ",font=("微软雅黑",40))],
            [sg.Text()],
            [sg.Text("                ",font=("微软雅黑",40)),sg.Button("  退出  ",font=("微软雅黑",40))]]
    window=sg.Window("开始",layout,size=(800,600))
    while True:
        event,values=window.read()
        if event in(None,"  退出  "):
            exit()
        if event in ("开始游戏"):
            bool=True
            break
        if event in ("  备注  "):
            sg.Print("游戏有四种颜色的食物,且每过一段时间会生成新的食物:")
            sg.Print("1.绿色:分数加1,无特殊变化")
            sg.Print("2.紫色:分数加2,但长度加2")
            sg.Print("3.蓝色:分数加1,速度增加")
            sg.Print("4.橙色:分数加1,速度降低")
            sg.Print("基础操作:键盘的上下左右键控制运动")
    window.close()
    return bool


class Snake:
   
    def __init__(self,x1,y1):
        self.x1=x1
        self.y1=y1
        self.block=10
        self.speed=25 
        self.length=1
        self.List=[]
        self.Head=[]
    def our_snake(self,game_close,x1,y1,block,snake_list):
        if(game_close==False):
            if(60<=y1<=460):
                pygame.draw.rect(dis, black, [x1, y1, block, block])
                for x in snake_list[1:-1]:
                    pygame.draw.rect(dis, grey, [x[0], x[1], block, block])
                pygame.display.update()

class Food:
    def __init__(self,snake_block,snake,List):
        same=False
        self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
        self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0
        for i in snake.List:
            if i==[self.foodx,self.foody]:
                same=True
        self.type=random.randint(0,3)
        self.Head=[self.foodx,self.foody,self.type]
        while same:
            self.foodx = round(random.randrange(70, dis_width - snake_block-60) / 10.0) * 10.0
            self.foody = round(random.randrange(70, dis_height - snake_block-60) / 10.0) * 10.0    
            for i in snake.List:
                if i==[self.foodx,self.foody]:
                    same=True

        self.block = snake_block

    def appear(self,list):
        for i in list:
            if i[2]==0:
                pygame.draw.rect(dis, green, [i[0],i[1], self.block, self.block])
            if i[2]==1:
                pygame.draw.rect(dis, purple, [i[0],i[1], self.block, self.block])
            if i[2]==2:
                pygame.draw.rect(dis, blue, [i[0],i[1], self.block, self.block])
            if i[2]==3:
                pygame.draw.rect(dis, orange, [i[0],i[1], self.block, self.block])

def gameLoop():
    
    list=[]
    num=[0,0]
    count=0
    s=[25]

    x1_change=0
    y1_change=0

    game_over = False
    game_close = False

    snake=Snake(80,80)
    food=Food(snake.block,snake,list)
    list.append(food.Head)
    bo0 = True
    bo1 = True

    while not game_over:



        while game_close==True:
            dis.fill(white)
            message("失败", red, lost_style, [dis_width / 2 - 50, dis_height / 3 - 25])
            message("接下来请按C键重新开始或者Q键退出游戏。", red, font_style, [dis_width / 2 - 9*25, dis_height / 3 + 25 + 1*25])
            if(eat==0):
                message("死因:创墙!",red, font_style, [280, dis_height / 3 - 50])
            if(eat==1):
                message("死因:自己咬自己!",red,font_style,[250, dis_height / 3 - 50])
            if(eat==2):
                message("死因:太慢!",red, font_style, [280, dis_height / 3 - 50])                
            Your_score(snake.length - 1)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        pygame.quit()
                        quit()
                    if event.key == pygame.K_c:
                        gameLoop()
        
        #移动(如果w,a,s,d之类的chang就对应相应的值,移动长度为snake.block,即为蛇的大小)
        if pygame.event.peek():
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    game_over = True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:                 
                        x1_change = -snake.block
                        y1_change = 0
                    elif event.key == pygame.K_RIGHT:
                        x1_change = snake.block
                        y1_change = 0
                    elif event.key == pygame.K_UP:
                        y1_change = -snake.block
                        x1_change = 0
                    elif event.key == pygame.K_DOWN:
                        y1_change = snake.block
                        x1_change = 0  
        
        bo = False
        if len(list)<5:

            n=int(pygame.time.get_ticks()/1000)
            if len(num)==1:
                num[1]=n
                bo1=False

            else:
                if bo1 == True:
                    num[1]=n
                    bo1 = False
                    bo0 = True
                elif bo0 == True:
                    num[0]=n
                    bo0 = False
                    bo1 = True            

            if num[1]-num[0] >= 1:
                bo = True

            if(bo):
                food.__init__(snake.block,snake,list)
                food.appear(list)
                list.append(food.Head)
                

        if snake.x1 > dis_width-70 or snake.x1 < 60 or snake.y1 > dis_height-60 or snake.y1 < 70:
            pygame.mixer.Sound.play(end_music)
            eat=0
            game_close = True

        snake.x1 += x1_change
        snake.y1 += y1_change

        #设置颜色
        dis.fill(white)
        
        food.appear(list)

        #框
        pygame.draw.rect(dis, (0, 0, 0), [50,60,600,400],1)

        snake.Head=[]
        snake.Head.append(snake.x1)
        snake.Head.append(snake.y1)
        snake.List.append(snake.Head)

        if len(snake.List) > snake.length:
            del snake.List[0]


        #对于蛇的每个点若与蛇头重复则寄,除头外(有第二个的bug)
        for x in snake.List[:-1]:
            if x == snake.Head:
                pygame.mixer.Sound.play(end_music)            
                game_close = True
                eat=1

        
        snake.our_snake(game_close,snake.x1,snake.y1,snake.block,snake.List)
        Your_score(snake.length-1)
        Your_speed(s[count])

        pygame.display.update()

        for i in list:
            if snake.x1 == i[0] and snake.y1 == i[1]:
                list.remove([i[0],i[1],i[2]])
                pygame.mixer.Sound.play(eat_music)
                if i[2]==0:
                    snake.length+=1
                if i[2]==1:
                    snake.length+=2
                if i[2]==2:
                    snake.speed+=2
                    snake.length+=1
                if i[2]==3:
                    snake.speed-=3
                    snake.length+=1



        clock.tick(snake.speed+hard*snake.length)
        s.append(snake.speed+hard*snake.length)
        count+=1

    pygame.display.quit()

if(start()):
    gameLoop()
                


    

 

 写在最后:

        这个项目是一组人一起做的,但是这个代码是我自己搞的,我们小组做的是一个技术大哥用c++写了以后要我们用python改,本人是一个大二的学生,上大学前从来没接触过代码,所以实在是看不懂大哥写的东西,这个程序怎么说也是我花了时间和精力去做出来的,虽然无法作为项目成果上交我还是希望可以留下一点记录,留下我学习Python的记录。

        有bug或者别的是在所难免的,大家(如果有人看的话)如果发现什么问题或者想要交流的话我很欢迎大家指出一起交流,这个是我的个人邮箱,有需要可以联系我:okura_machi@126.com

        谢谢!


2023.1.31 10:27 更新:修改了时间的问题,使用time库即可解决且无需上述的麻烦的问题


        #add
        n=int(time.time())
        if len(numm)<1:
            numm.append(n)
        else:
            if(n-numm[len(numm)-1]>=2):
                numm.append(n)
                food.__init__(snake.block,snake,list)
                food.appear(list)
                list.append(food.Head)

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值