基于Pygame的贪吃蛇python小游戏实现

基于Pygame的贪吃蛇python小游戏实现

0.前言

许多程序员入门的第一个项目都会选择贪吃蛇。用贪吃蛇来练手比较合适。因为贪吃蛇的算法并不难,但绝对够有启发作用,也比较经典。相对来说它很容易就能实现。对于新手来说,拿贪吃蛇来作为练习是很有必要的。

各个语言都会有许多共性,但实现的算法基本都差不多。这里就用Python为例,分析一下算法实现,并附上相应代码。不足之处还请指正。

1.分类

python是一门面向对象的程序语言,我们在编写一个项目时要首先根据需要对其进行分类,模块化处理。

分析得到,需要定义Snake类、Food类、Game类,分别代表蛇、食物、游戏规则。然后对类定义成员方法,比如Snake类需要进行拐弯、增加、减少等操作。

Food类
//Author:xiaobei

import random

class Food(object):
    def __init__(self,r_pos,color,state):
        self.r_pos = r_pos
        self.color = color
        self.state = state
    def update(self,snake,sound_effect):
        if self.r_pos in snake.body:
            self.state = 1
        else:
            self.state = 0
        if self.state == 1:
            self.r_pos = [random.randrange(30,720,30),random.randrange(30,540,30)]
            self.color = random.choice([(255,255,0),(255,0,255),(0,255,255)])
            snake.length+=1
            sound_effect.play()
Snake类
//Author:xiaobei

class Snake(object):
    def __init__(self,length,body,direction,direction_change,head_pos,end):
        self.length = length
        self.body = body
        self.direction = "RIGHT"
        self.direction_change = "RIGHT"
        self.head_pos = head_pos
        self.end = False

#控制蛇的爬行
    def move(self):
        if self.length > len(self.body):
            self.body.append([0,0])
        for i in range(self.length-1,0,-1):
            self.body[i][0] = self.body[i-1][0]     #这里多重列表互相赋值不能整体,因为最外层代表首地址,即首元素,因此要分开赋值
            self.body[i][1] = self.body[i-1][1]
        if self.direction == "LEFT" :
            self.body[0][0]-=30
        elif self.direction == "RIGHT":
            self.body[0][0]+=30
        elif self.direction == "UP":
            self.body[0][1]-=30
        else:
            if self.direction == "DOWN":
                self.body[0][1]+=30

#控制不让贪吃蛇溢出
        if self.head_pos[0]>850:

            self.end = True
        elif self.head_pos[1] > 650:

            self.end = True
        elif self.head_pos[0] < -30:

            self.end = True
        else:
            if self.head_pos[1]<-30:
                self.end = True


    def turn(self):
        if self.direction_change == "LEFT" and self.direction != "RIGHT":
            self.direction = self.direction_change
        elif self.direction_change == "RIGHT" and self.direction != "LEFT":
            self.direction = self.direction_change
        elif self.direction_change == "UP" and self.direction != "DOWN":
            self.direction = self.direction_change
        else :
            if self.direction_change == "DOWN" and self.direction != "UP":
                self.direction = self.direction_change

这里偷了一个懒,没有定义Game类,我把游戏规则掺进了主程序main()中。

2.主要算法

(1)控制贪吃蛇拐弯

用pygame产生一个界面,我们把这个界面当做一个坐标网格,蛇身是一个坐标列表。用蛇头坐标作为蛇的行进方向,控制蛇身整体的方向。难点在于如何使蛇身在转弯的时候,使蛇身每一部分逐个而不是整体转向呢?

for i in range(self.length-1,0,-1):
            self.body[i][0] = self.body[i-1][0]     #这里多重列表互相赋值不能整体,因为最外层代表首地址,即首元素,因此要分开赋值
            self.body[i][1] = self.body[i-1][1]

这里我们采用一个循环,从尾部开始,只有蛇头在变动,后面的所有部分都在被蛇头牵连着动。假设有n个结点,nn-1 = nn,……,n2 = n1 .依次移动,形成一个拐弯效果。

(2)食物的刷新

食物刷新位置是在,蛇吃到食物之后才激发。所以重点在于如何判断是否吃到食物。这里有一个易错点:容易使食物坐标和蛇头的坐标永不吻合的的情况。这是因为蛇的坐标间隔以及食物刷新间隔位置,不是以同一递增/递减公差q进行的。

def update(self,snake,sound_effect):
    if self.r_pos in snake.body:
        self.state = 1
    else:
        self.state = 0
    if self.state == 1:
        self.r_pos = [random.randrange(30,720,30),random.randrange(30,540,30)]
        self.color = random.choice([(255,255,0),(255,0,255),(0,255,255)])
        snake.length+=1
        sound_effect.play()

在此基础上,当蛇头坐标与食物坐标吻合,便激发食物刷新位置。

(3)游戏结束条件

游戏结束条件无非两种:一是蛇头与自身重合,二十蛇头触到边界。这两种方法同样是通过坐标判断来实的。

if snake.head_pos in snake.body[1:] or snake.end:
    screen.blit(text2Image,(200,200))
    pygame.mixer.music.stop()
    sound_end.play()
    pygame.display.update()
    time.sleep(5)
    pygame.quit()
    sys.exit()

3.界面实现与主函数

界面实现依靠pygame第三方库来执行,pygame库的安装可以用pip命令行来实现,在控制台进行。

pip install -U pygame

参数-U是安装game为最新版。

pygame的使用请参考《Python 游戏开发—Pygame 快速入门》

主要代码如下:

//Author:xiaobei

import pygame
import os
import sys
import time
import random
from pygame.locals import *
from Snake import Snake
from Food import Food

pygame.init()

#混音器初始化
pygame.mixer.init()

#加载音效
sound_effect = pygame.mixer.Sound("C:\\Windows\\media\\Windows Proximity Notification.wav")
sound_end = pygame.mixer.Sound("C:\\Windows\\media\\Ring07.wav")
pygame.mixer.music.load("C:\\Windows\\media\\flourish.mid")
pygame.mixer.music.set_volume(0.5)
sound_effect.set_volume(1)
pygame.mixer.music.play(-1) #-1控制无限循环

#设置游戏时钟
clock = pygame.time.Clock()

#设置主窗体相对位置、大小,标题、背景颜色
os.environ["SDL_VIDEO_WINDOW_POS"] = "%d,%d"%(50,50)
screen = pygame.display.set_mode((820,620))
screen.fill([255,235,100])
pygame.display.set_caption("贪吃蛇小游戏")

#设置文本
pygame.font.init
text1 = pygame.font.Font(None,35)
text1Image = text1.render("SCORE:",True,[100,125,255])
text2 = pygame.font.Font(None,120)
text2Image = text2.render("Gameover",True,[100,125,255])
text3 = pygame.font.Font(None,35)
text4 = pygame.font.Font(None,35)
screen.blit(text1Image,(5,5))



#创建贪吃蛇对象、食物等对象
snake = Snake(length = 3,body = [[120,90],[90,90],[60,90]],direction = "RIGHT",direction_change ="RIGHT", head_pos = [120,100],end = False)
food = Food(r_pos = [120,420],color = (100,255,100),state = 0)


score = 0

#进入循环
while True:
#设置帧率刷新速度
    clock.tick(5)

#设置窗口便于刷新
    screen = pygame.display.set_mode((820,620))
    screen.fill([255,235,100])

#绘制文本“分数”
    score = len(snake.body)-3
    screen.blit(text1Image,(5,5))
    text3Image = text3.render("{}".format(score),True,[100,125,255])
    screen.blit(text3Image,(120,5))

#绘制文本“时间”
    text4Image = text4.render("time: {} seconds".format(int(time.clock())),True,[100,125,255])
    screen.blit(text4Image,(200,5))

#绘制蛇身、食物
    food_circle = pygame.draw.rect(screen,food.color,(food.r_pos[0],food.r_pos[1],28,28),0)
    for i in range(snake.length):
        snake_rent = pygame.draw.rect(screen,(120,255,205),(snake.body[i][0],snake.body[i][1],28,28),0)



#设置退出条件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

#获取键盘事件
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                snake.direction_change = "LEFT"
            elif event.key == pygame.K_RIGHT:
                snake.direction_change = "RIGHT"
            elif event.key == pygame.K_UP:
                snake.direction_change = "UP"
            else:
                if event.key == pygame.K_DOWN:
                    snake.direction_change = "DOWN"


#控制蛇的转向
    snake.head_pos = snake.body[0]
    food.update(snake,sound_effect)
    snake.move()
    snake.turn()

#游戏结束
    if snake.head_pos in snake.body[1:] or snake.end:
        screen.blit(text2Image,(200,200))
        pygame.mixer.music.stop()
        sound_end.play()
        pygame.display.update()
        time.sleep(5)
        pygame.quit()
        sys.exit()
#刷新界面
    pygame.display.update()

4.说明

我把每个类模块独立为单个文件,把它们放在同一项目文件夹下,然后在主程序中调用它们,主程序也是一个文件,直接运行主文件即可运行程序。(不好意思,这里又偷了一个懒,嘿嘿!)

运行界面如下:运行效果界面
主程序中有背景音乐和音效的绝对路径引用,读者可自行忽略删改。恭喜,到这里一个贪吃蛇小程序大功告成!

不当之处,还望指正,谢谢。

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
好的,我可以给你介绍一个基于Pygame小游戏——贪吃蛇。 首先,你需要安装Pygame库。可以通过pip命令来安装: ``` pip install pygame ``` 接下来,我们开始编写代码: ```python import pygame import random # 初始化pygame pygame.init() # 设置游戏窗口大小和标题 width, height = 640, 480 screen = pygame.display.set_mode((width, height)) pygame.display.set_caption('贪吃蛇') # 定义颜色 black = (0, 0, 0) white = (255, 255, 255) red = (255, 0, 0) # 定义蛇的初始位置、大小和速度 snake_x, snake_y = width / 2, height / 2 snake_size = 10 snake_speed = 5 # 定义蛇的移动方向 snake_direction = 'right' # 定义食物的初始位置和大小 food_x, food_y = random.randint(0, width - snake_size), random.randint(0, height - snake_size) food_size = 10 # 定义计分 score = 0 font = pygame.font.SysFont(None, 25) # 游戏主循环 while True: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() # 处理键盘事件 if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: snake_direction = 'left' elif event.key == pygame.K_RIGHT: snake_direction = 'right' elif event.key == pygame.K_UP: snake_direction = 'up' elif event.key == pygame.K_DOWN: snake_direction = 'down' # 移动蛇 if snake_direction == 'right': snake_x += snake_speed elif snake_direction == 'left': snake_x -= snake_speed elif snake_direction == 'up': snake_y -= snake_speed elif snake_direction == 'down': snake_y += snake_speed # 判断蛇是否撞墙 if snake_x < 0 or snake_x > width - snake_size or snake_y < 0 or snake_y > height - snake_size: pygame.quit() quit() # 判断蛇是否吃到食物 if snake_x <= food_x < snake_x + snake_size and snake_y <= food_y < snake_y + snake_size: food_x, food_y = random.randint(0, width - snake_size), random.randint(0, height - snake_size) score += 1 # 绘制游戏画面 screen.fill(white) pygame.draw.rect(screen, red, [food_x, food_y, food_size, food_size]) pygame.draw.rect(screen, black, [snake_x, snake_y, snake_size, snake_size]) # 绘制计分 text = font.render('Score: ' + str(score), True, black) screen.blit(text, [0, 0]) # 更新游戏画面 pygame.display.update() ``` 这个贪吃蛇游戏比较简单,主要包括以下几个部分: 1. 初始化pygame,设置游戏窗口大小和标题,定义颜色等。 2. 定义蛇的初始位置、大小和速度,以及食物的初始位置和大小。 3. 在游戏主循环里处理事件,包括处理键盘事件、移动蛇、判断蛇是否撞墙或吃到食物等。 4. 绘制游戏画面,包括绘制食物和蛇,以及绘制计分。 5. 更新游戏画面。 你可以根据自己的需求和兴趣,修改代码并添加更多的游戏元素,例如增加障碍物、增加多个食物、增加多条蛇等。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值