20213408 实验四《Python综合实践》实验报告

20213408 《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 2134
姓名: 冯旷霖
学号:20213408
实验教师:王志强
实验日期:2022年5月19日
必修/选修: 公选课

1.实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。在考虑难度和实际情况后,决定选择用Python做一个贪吃蛇小游戏。

2.实验过程及结果

(1)从网上下载了Pycharm。

(2)从知乎上学习用Python编写贪吃蛇小游戏。

(3)完成代码的编写并运行。

(4)在华为云服务器上运行。

代码

import random

import pygame

SCREEN_SIZE = [1000, 800]
WHITE = (255, 255, 255)

CELL_RADIUS = 10
SNAKE_COLOR = (0, 0, 0)

FOOD_COLOR = (0, 100, 0)
FOOD_RADIUS = 10

UPDATE = pygame.USEREVENT + 1
FOOD = pygame.USEREVENT + 2

LIGHT_GREY = (100, 100, 100)
MESSAGE_POSITION = (300, 350)


def init_game():
    pygame.init()
    pygame.display.set_caption("Snake 贪吃蛇")
    pygame.time.set_timer(UPDATE, 250)
    pygame.time.set_timer(FOOD, 1500)


class Game:
    def __init__(self):
        self.running = True
        self.screen = pygame.display.set_mode(SCREEN_SIZE)
        self.snake = Snake()
        self.food = None
        self.message = None


class Cell:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def to_tuple(self):
        return self.x , self.y

    def copy(self):
        return Cell(self.x, self.y)

    def update(self, direction):
        if direction == "U":
            self.y -= CELL_RADIUS * 2
        elif direction == "D":
            self.y += CELL_RADIUS * 2
        elif direction == "L":
            self.x -= CELL_RADIUS * 2
        elif direction == "R":
            self.x += CELL_RADIUS * 2


class Snake:
    def __init__(self):
        cell_diameter = CELL_RADIUS * 2
        x = (SCREEN_SIZE[0] / cell_diameter // 2) * cell_diameter
        y = (SCREEN_SIZE[1] / cell_diameter // 2) * cell_diameter

        self.body = [Cell(x, y)]
        self.cell_size = CELL_RADIUS
        self.color = SNAKE_COLOR
        self.direction = "L"

    def update(self):
        head = self.body[0].copy()
        self.body.pop()
        head.update(self.direction)
        self.body.insert(0, head)

def is_snake_food_collide():
    head = game.snake.body[0].copy()
    head.update(game.snake.direction)
    return (game.food[0] - head.x) == 0 and (game.food[1] - head.y) == 0


def update():
    check_snake_direction()
    check_food()
    check_head_body_collision()
    check_out_boundary()
    check_win()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game.running = False
        if event.type == UPDATE:
            game.snake.update()
        if event.type == FOOD:
            generate_food()


def check_win():
    length = len(game.snake.body)
    cell_diameter = CELL_RADIUS * 2
    max_cell_x = SCREEN_SIZE[0] // cell_diameter
    max_cell_y = SCREEN_SIZE[1] // cell_diameter
    if length == max_cell_x * max_cell_y:
        game.running = False
        game.message = "You WIN the game. Should restart? y/n"


def check_out_boundary():
    cell_diameter = 2 * CELL_RADIUS
    out_boundary_x_cells = [cell for cell in game.snake.body
                            if cell.x < 2 * cell_diameter or cell.x > SCREEN_SIZE[0] - cell_diameter]
    out_boundary_y_cells = [cell for cell in game.snake.body
                            if cell.y < 2 * cell_diameter or cell.y > SCREEN_SIZE[1] - cell_diameter]
    if len(out_boundary_x_cells) > 0 or len(out_boundary_y_cells) > 0:
        game.running = False
        game.message = "Snake is out of boundary. Should restart? y/n"


def check_head_body_collision():
    head = game.snake.body[0]
    body = game.snake.body
    try:
        index = [cell.to_tuple() for cell in body[1:]].index(head.to_tuple())
    except ValueError:
        index = -1
    if len(game.snake.body) > 1 and index > -1:
        game.snake.body = game.snake.body[:index]


def check_food():
    if game.food is not None and is_snake_food_collide():
        cell = Cell(game.food[0], game.food[1])
        game.snake.body.insert(0, cell)
        game.food = None


def check_snake_direction():
    pressed_keys = pygame.key.get_pressed()
    if pressed_keys[pygame.K_UP] and not game.snake.direction == "D":
        game.snake.direction = "U"
    if pressed_keys[pygame.K_DOWN] and not game.snake.direction == "U":
        game.snake.direction = "D"
    if pressed_keys[pygame.K_LEFT] and not game.snake.direction == "R":
        game.snake.direction = "L"
    if pressed_keys[pygame.K_RIGHT] and not game.snake.direction == "L":
        game.snake.direction = "R"


def generate_food():
    while game.food is None:
        cell_diameter = CELL_RADIUS * 2
        rand_x = random.randint(1, (SCREEN_SIZE[0] // cell_diameter) - 1) * cell_diameter
        rand_y = random.randint(1, (SCREEN_SIZE[1] // cell_diameter) - 1) * cell_diameter
        if (rand_x, rand_y) not in [cell.to_tuple() for cell in game.snake.body]:
            game.food = (rand_x, rand_y)


def draw():
    global event, game
    game.screen.fill(WHITE)
    if game.running:
        draw_snake(game)
        draw_food(game)
    else:
        draw_restart(game)
    pygame.display.flip()


def draw_restart(game):
    font = pygame.font.Font(None, 30)
    restart_message = font.render(game.message, True, LIGHT_GREY)
    game.screen.blit(restart_message, MESSAGE_POSITION)


def draw_food(game):
    if game.food is not None:
        pygame.draw.circle(game.screen, FOOD_COLOR, game.food, FOOD_RADIUS)


def draw_snake(game):
    for cell in game.snake.body:
        pygame.draw.circle(game.screen, game.snake.color, cell.to_tuple(), game.snake.cell_size)


def check_restart():
    global event, game
    while not game.running:
        for event in pygame.event.get():
            if event.type == pygame.KEYUP and event.key == pygame.K_y:
                game.snake = Snake()
                game.running = True
            if event.type == pygame.KEYUP and event.key == pygame.K_n:
                return


if __name__ == '__main__':
    init_game()
    game = Game()
    while game.running:
        update()
        draw()
        check_restart()
    pygame.quit()

3.程序功能(在视频中有演示)

(1)用上下左右按键控制方向。

(2)蛇吃食物后长度增加。

(3)蛇到达一定长度后头撞自己的身体造成长度缩短。

(4)游戏结束的判定(碰到边界)。

(5)游戏结束后按y重新开始游戏。

(6)游戏结束后按n结束游戏。

(7)更改游戏参数值。

4.实验过程中遇到的问题和解决过程

  • 问题1:运行时出现了小数和整数不能比较。
  • 问题1解决方案:运算中用“//”替换“/”变成整除。
  • 问题2:Pycharm上运行不了Pygame。
  • 问题2解决方案:下载了Pygame的环境。

5.感想

这学期必修课的C语言课程和选修课的Python课程同时进行,学期刚开始时在两种编程语言都不是很熟悉的情况下容易混淆。但随着时间的推移,慢慢搞清楚了,不会再把两种语言混淆了。十几次课上下来,感觉Python总体来说要比C语言简便,在课上也学到了很多,会自己编写一点简单的程序,如计算器、猜数、爬虫等,有多少精通不敢说,但也算是入门了吧。总的来说,这次课程很有意义,也学到了很多,没有选错。

posted @ 2022-05-31 20:05    阅读(160)  评论(0编辑  收藏  举报