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语言简便,在课上也学到了很多,会自己编写一点简单的程序,如计算器、猜数、爬虫等,有多少精通不敢说,但也算是入门了吧。总的来说,这次课程很有意义,也学到了很多,没有选错。