ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python讲座2—贪吃蛇

2022-05-19 23:31:37  阅读:202  来源: 互联网

标签:head snakes python WIDTH 讲座 pg 贪吃蛇 score BLOCK


这次讲座讲了一下用pygame库写贪吃蛇的小游戏:

总览

首先贴出全部代码:


# 导入所需的模块
import enum
import sys
import pygame as pg
import random

WIDTH, HEIGHT = 400, 400
ROW_NUM = 20  # 行数
COL_NUM = 20  # 列数
BLOCK_WIDTH, BLOCK_HEIGHT = WIDTH / COL_NUM, HEIGHT / ROW_NUM

# R(Red) G(Green) B(Blue)
BODY_COLOR = (0, 255, 0)
HEAD_COLOR = (255, 0, 0)
FOOD_COLOR = (0, 0, 255)

# 使用pg之前必须初始化
pg.init()

# 设置主屏窗口
screen = pg.display.set_mode((WIDTH, HEIGHT))

# 设置窗口的标题,即游戏名称
pg.display.set_caption('贪吃蛇')


class Direction(enum.Enum):
    Left = 0
    Up = 1
    Right = 3
    Down = 2


class GameState(enum.Enum):
    Die = 0
    Playing = 1
    Preparing = 2


# 初始化这条蛇
snakes = []
blocks = []
direction: Direction = Direction.Up
game_state: GameState = GameState.Playing
difficulty = 3
food = (10*BLOCK_WIDTH, 10*BLOCK_HEIGHT)
score = 0
max_score = 0


def init():
    snakes.clear()
    snakes.append((5*BLOCK_WIDTH, 5*BLOCK_HEIGHT))
    snakes.append((5*BLOCK_WIDTH, 6*BLOCK_HEIGHT))
    snakes.append((5*BLOCK_WIDTH, 7*BLOCK_HEIGHT))
    global direction, game_state, difficulty, score, max_score
    direction = Direction.Up
    game_state = GameState.Playing
    difficulty = 3
    generate_food()
    score = 0


def set_direction(d: Direction):
    global direction
    if(d.value + direction.value == 3):
        return
    direction = d


def generate_food():
    global food
    while True:
        x = random.randint(0, COL_NUM-1) * BLOCK_WIDTH
        y = random.randint(0, ROW_NUM-1) * BLOCK_HEIGHT
        if (x, y) not in snakes and (x, y) not in blocks:
            food = (x, y)
            break


def move():
    global game_state
    cur_head: tuple[int, int] = snakes[0]
    match direction:
        case Direction.Left:
            snakes.insert(0, (cur_head[0]-BLOCK_WIDTH, cur_head[1]))
        case Direction.Right:
            snakes.insert(0, (cur_head[0]+BLOCK_WIDTH, cur_head[1]))
        case Direction.Down:
            snakes.insert(0, (cur_head[0], cur_head[1]+BLOCK_HEIGHT))
        case Direction.Up:
            snakes.insert(0, (cur_head[0], cur_head[1]-BLOCK_HEIGHT))
    if (head := snakes[0]) != food:
        if head in snakes[1:] or head[0] < 0 or head[0] >= WIDTH or head[1] < 0 or head[1] >= HEIGHT:
            game_state = GameState.Die
        else:
            snakes.pop()
    else:
        global difficulty, score, max_score
        difficulty *= 1.0
        score += 100
        generate_food()


def draw_text(s: str, center, font_size=50, font_color=(255, 0, 0), back_color=(255, 255, 255)):
    f = pg.font.Font('C:/Windows/Fonts/simhei.ttf', font_size)
    # 生成文本信息,第一个参数文本内容;第二个参数,字体是否平滑;
    # 第三个参数,RGB模式的字体颜色;第四个参数,RGB模式字体背景颜色;
    text = f.render(s, True, font_color, back_color)
    # 获得显示对象的rect区域坐标
    textRect = text.get_rect()
    # 设置显示对象居中
    textRect.center = center
    # 将准备好的文本信息,绘制到主屏幕 Screen 上。
    screen.blit(text, textRect)


init()
clock = pg.time.Clock()
# 固定代码段,实现点击"X"号退出界面的功能,几乎所有的pg都会使用该段代码
while True:
    clock.tick(2 * difficulty)
    # 循环获取事件,监听事件状态
    for event in pg.event.get():
        # 判断用户是否点了"X"关闭按钮,并执行if代码段
        match event.type:
            case pg.QUIT:
                pg.quit()
                sys.exit()
            case pg.MOUSEBUTTONDOWN:
                #print("click")
                if game_state == GameState.Die:
                    game_state = GameState.Playing
                    init()
            case pg.KEYDOWN:
                match event.key:
                    case pg.K_LEFT:
                        set_direction(Direction.Left)
                    case pg.K_RIGHT:
                        set_direction(Direction.Right)
                    case pg.K_UP:
                        set_direction(Direction.Up)
                    case pg.K_DOWN:
                        set_direction(Direction.Down)
                    case pg.K_0:
                         if game_state == GameState.Die:
                           game_state = GameState.Playing
                           init()

    move()
    screen.fill((255, 255, 255))
    if game_state == GameState.Playing:
        for i, block in enumerate(snakes):
            if i == 0:
                pg.draw.rect(screen, HEAD_COLOR,
                             (block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
            else:
                pg.draw.rect(screen, BODY_COLOR,
                             (block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
        pg.draw.rect(screen, FOOD_COLOR,
                     (food[0], food[1], BLOCK_WIDTH, BLOCK_HEIGHT))
        if score >= max_score:
            max_score = score
            draw_text(f"最高分数:{max_score}!", (60, 100), 18, (255, 0, 0))
        else:
            draw_text(f"最高分数:{max_score}", (60, 100), 18, (0, 0, 0))
        draw_text(f"分数:{score}", (60, 50), 18, (0, 0, 0))
    else:
        draw_text("你输了!", (200, 200))

    pg.display.flip()  # 更新屏幕内容

模块导入:

把需要用的库都引用一下,一般有这几个:

import enum
import sys
import pygame as pg
import random

import ... as ...就是将库重命名了一下

设置一些常数

WIDTH, HEIGHT = 400, 400
ROW_NUM = 20  # 行数
COL_NUM = 20  # 列数
BLOCK_WIDTH, BLOCK_HEIGHT = WIDTH / COL_NUM, HEIGHT / ROW_NUM

# R(Red) G(Green) B(Blue)
BODY_COLOR = (0, 255, 0)
HEAD_COLOR = (255, 0, 0)
FOOD_COLOR = (0, 0, 255)

使用了RGB颜色

初始化窗口:

# 使用pg之前必须初始化
pg.init()

# 设置主屏窗口
screen = pg.display.set_mode((WIDTH, HEIGHT))

# 设置窗口的标题,即游戏名称
pg.display.set_caption('贪吃蛇')


class Direction(enum.Enum):
    Left = 0
    Up = 1
    Right = 3
    Down = 2


class GameState(enum.Enum):
    Die = 0
    Playing = 1
    Preparing = 2

创建的两个类Direction和GameState继承了enum库,enum就是一个枚举,意思是这个类里面只存在Class里面枚举的键值对,其他都会报错,用于加强鲁棒性。

初始化参数:

snakes = []
blocks = []
direction: Direction = Direction.Up
game_state: GameState = GameState.Playing
difficulty = 3
food = (10*BLOCK_WIDTH, 10*BLOCK_HEIGHT)
score = 0
max_score = 0

这里采用元组的形式来建立蛇

定义主要函数:

初始化函数

def init():
    snakes.clear()
    snakes.append((5*BLOCK_WIDTH, 5*BLOCK_HEIGHT))
    snakes.append((5*BLOCK_WIDTH, 6*BLOCK_HEIGHT))
    snakes.append((5*BLOCK_WIDTH, 7*BLOCK_HEIGHT))
    global direction, game_state, difficulty, score, max_score
    direction = Direction.Up
    game_state = GameState.Playing
    difficulty = 3
    generate_food()
    score = 0

global + 变量名:将变量声明为全局变量,
在函数里面如果不加global,就像c语言中的形参一样,对于变量本身没有影响。
初始时蛇长定为3

定向函数:

def set_direction(d: Direction):
    global direction
    if(d.value + direction.value == 3):
        return
    direction = d

d.value + direction.value != 3是为了保证转向后不会向反方向走(其他方向都有可能)

产生食物:

def generate_food():
    global food
    while True:
        x = random.randint(0, COL_NUM-1) * BLOCK_WIDTH
        y = random.randint(0, ROW_NUM-1) * BLOCK_HEIGHT
        if (x, y) not in snakes and (x, y) not in blocks:
            food = (x, y)
            break

食物随机产生,但不能生成在蛇身上和墙上。

蛇的抽抽:

def move():
    global game_state
    cur_head: tuple[int, int] = snakes[0]
    match direction:
        case Direction.Left:
            snakes.insert(0, (cur_head[0]-BLOCK_WIDTH, cur_head[1]))
        case Direction.Right:
            snakes.insert(0, (cur_head[0]+BLOCK_WIDTH, cur_head[1]))
        case Direction.Down:
            snakes.insert(0, (cur_head[0], cur_head[1]+BLOCK_HEIGHT))
        case Direction.Up:
            snakes.insert(0, (cur_head[0], cur_head[1]-BLOCK_HEIGHT))
    if (head := snakes[0]) != food:
        if head in snakes[1:] or head[0] < 0 or head[0] >= WIDTH or head[1] < 0 or head[1] >= HEIGHT:
            game_state = GameState.Die
        else:
            snakes.pop()
    else:
        global difficulty, score, max_score
        difficulty *= 1.0
        score += 100
        generate_food()

产生文本:

def draw_text(s: str, center, font_size=50, font_color=(255, 0, 0), back_color=(255, 255, 255)):
    f = pg.font.Font('C:/Windows/Fonts/simhei.ttf', font_size)
    # 生成文本信息,第一个参数文本内容;第二个参数,字体是否平滑;
    # 第三个参数,RGB模式的字体颜色;第四个参数,RGB模式字体背景颜色;
    text = f.render(s, True, font_color, back_color)
    # 获得显示对象的rect区域坐标
    textRect = text.get_rect()
    # 设置显示对象居中
    textRect.center = center
    # 将准备好的文本信息,绘制到主屏幕 Screen 上。
    screen.blit(text, textRect)

设置font对象,渲染font对象,设置文本位置。

主循环:

init()
clock = pg.time.Clock()
# 固定代码段,实现点击"X"号退出界面的功能,几乎所有的pg都会使用该段代码
while True:
    clock.tick(2 * difficulty)
    # 循环获取事件,监听事件状态
    for event in pg.event.get():
        # 判断用户是否点了"X"关闭按钮,并执行if代码段
        match event.type:
            case pg.QUIT:
                pg.quit()
                sys.exit()
            case pg.MOUSEBUTTONDOWN:
                #print("click")
                if game_state == GameState.Die:
                    game_state = GameState.Playing
                    init()
            case pg.KEYDOWN:
                match event.key:
                    case pg.K_LEFT:
                        set_direction(Direction.Left)
                    case pg.K_RIGHT:
                        set_direction(Direction.Right)
                    case pg.K_UP:
                        set_direction(Direction.Up)
                    case pg.K_DOWN:
                        set_direction(Direction.Down)
                    case pg.K_0:
                         if game_state == GameState.Die:
                           game_state = GameState.Playing
                           init()

    move()
    screen.fill((255, 255, 255))
    if game_state == GameState.Playing:
        for i, block in enumerate(snakes):
            if i == 0:
                pg.draw.rect(screen, HEAD_COLOR,
                             (block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
            else:
                pg.draw.rect(screen, BODY_COLOR,
                             (block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
        pg.draw.rect(screen, FOOD_COLOR,
                     (food[0], food[1], BLOCK_WIDTH, BLOCK_HEIGHT))
        if score >= max_score:
            max_score = score
            draw_text(f"最高分数:{max_score}!", (60, 100), 18, (255, 0, 0))
        else:
            draw_text(f"最高分数:{max_score}", (60, 100), 18, (0, 0, 0))
        draw_text(f"分数:{score}", (60, 50), 18, (0, 0, 0))
    else:
        draw_text("你输了!", (200, 200))

    pg.display.flip()  # 更新屏幕内容

标签:head,snakes,python,WIDTH,讲座,pg,贪吃蛇,score,BLOCK
来源: https://www.cnblogs.com/misasteria/p/16290637.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有