课程:《Python程序设计》
班级:2241
姓名:段浩楠
学号:20224102
实验教师:王志强
实验日期:2023年5月20日
必修/选修: 专选课
一.实验内容
利用python语言,编写小游戏,贪吃蛇
二.实验过程
1、下载安装pygame
打开命令行工具,对于windows系统:输入pip install pygame
即可成功安装
2.主体代码
"""贪吃蛇"""
import random
import sys
import time
import copy
import pygame
from pygame.locals import *
from collections import deque
SCREEN_WIDTH = 800 # 屏幕宽度
SCREEN_HEIGHT = 480 # 屏幕高度
SIZE = 20 # 小方格大小
LINE_WIDTH = 3 # 网格线宽度
# 游戏区域的坐标范围
SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)
# 食物的分值及颜色
# FOOD_STYLE_LIST = [(10, (255, 100, 100)), (20, (100, 255, 100)), (30, (100, 100, 255))]
FOOD_STYLE_LIST = [(10, (255, 0, 0)), (20, (0, 255, 0)), (30, (0, 0, 255)), (100, (255, 255, 0))]
# 幸运食物出现概率(蛇身减一,速度不增加)
FOOD_LUCK=(0,7)
# LIGHT = (100, 100, 100)
DARK = (200, 200, 200) # 蛇的颜色
BLACK = (0, 0, 0) # 网格线颜色
RED = (200, 30, 30) # 红色,GAME OVER 的字体颜色
BGCOLOR = (40, 40, 60) # 背景色
def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
imgText = font.render(text, True, fcolor)
screen.blit(imgText, (x, y))
# 初始化蛇
def init_snake():
snake = deque()
snake.append((2, SCOPE_Y[0]))
# snake.append((1, SCOPE_Y[0]+1)), snake.append((1, SCOPE_Y[0])), snake.append((1, SCOPE_Y[0]+2))
snake.append((1, SCOPE_Y[0]))
snake.append((0, SCOPE_Y[0]))
return snake
def create_food(snake):
food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
while (food_x, food_y) in snake:
# 如果食物出现在蛇身上,则重来
food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
return food_x, food_y
def get_food_style():
if random.randint(FOOD_LUCK[0],FOOD_LUCK[1])==FOOD_LUCK[1]:
return FOOD_STYLE_LIST[3]
else:
return FOOD_STYLE_LIST[random.randint(0, 2)]
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) #pygame创建窗口
pygame.display.set_caption('贪吃蛇') #窗口名称
font1 = pygame.font.SysFont('SimHei', 16) # 得分的字体
font_ypos = 12 #位置
font2 = pygame.font.Font(None, 72) # GAME OVER 的字体
fwidth, fheight = font2.size('GAME OVER')
# 如果蛇正在向右移动,那么快速点击向下向左,由于程序刷新没那么快,向下事件会被向左覆盖掉,导致蛇后退,直接GAME OVER
# b 变量就是用于防止这种情况的发生
b = True
# 蛇
snake = init_snake()
# 食物
food = create_food(snake)
food_style = get_food_style()
# 方向
pos = (1, 0) #(左-1 右1,上-1 下1)
game_over = True
start = False # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER
score = 0 # 得分
orispeed =0.5 # 原始速度
speed = orispeed
luck_times=0
last_move_time = None
last_draw_time = None
pause = False # 暂停
BG_r = 40 #手动背景调整
BG_g = 40
BG_b = 60
BG_auto=True
REC_score=[]
REC_save=False
while True:
for event in pygame.event.get():
if event.type == QUIT: #关闭窗口事件直接退出
sys.exit()
elif event.type == KEYDOWN: #处理按键事件
if event.key == K_RETURN: #处理回车键事件
if game_over:
start = True #游戏开始
game_over = False
b = True
snake = init_snake()
food = create_food(snake)
food_style = get_food_style()
pos = (1, 0)
# 得分
score = 0
REC_save=True
REC_score.append(score)
last_move_time = time.time()
last_draw_time = last_move_time
luck_times = 0
elif event.key == K_SPACE: #处理空格键事件 暂停和继续
if not game_over:
pause = not pause
elif event.key in (K_w, K_UP):
# 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER
if b and not pos[1]:
pos = (0, -1)
b = False
elif event.key in (K_s, K_DOWN):
if b and not pos[1]:
pos = (0, 1)
b = False
elif event.key in (K_a, K_LEFT):
if b and not pos[0]:
pos = (-1, 0)
b = False
elif event.key in (K_d, K_RIGHT):
if b and not pos[0]:
pos = (1, 0)
b = False
elif event.key in (K_r,K_g,K_b): #背景色调整 L键控制开关(R,G,B)键控制3原色
if event.key==K_r:
BG_r=BG_r+5
if BG_r>=125:
BG_r=40
elif event.key==K_g:
BG_g=BG_g+5
if BG_g>=125:
BG_g=40
elif event.key==K_b:
BG_g=BG_b+5
if BG_b>=125:
BG_b=40
elif event.key==K_l:
BG_auto=not BG_auto
# 填充背景色
if BG_auto:
screen.fill(BGCOLOR)
else:
screen.fill((BG_r,BG_g,BG_b))
# 画网格线 竖线
for x in range(SIZE, SCREEN_WIDTH, SIZE):
pygame.draw.line(screen, BLACK, (x, SCOPE_Y[0] * SIZE), (x, SCREEN_HEIGHT), LINE_WIDTH)
# 画网格线 横线
for y in range(SCOPE_Y[0] * SIZE, SCREEN_HEIGHT, SIZE):
pygame.draw.line(screen, BLACK, (0, y), (SCREEN_WIDTH, y), LINE_WIDTH)
if not game_over:
curTime = time.time()
if curTime - last_move_time > speed: #控制移动速度speed值越小,刷新越快
if not pause:
b = True
last_move_time = curTime
next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1]) #按方向读取下一个前进位
if next_s == food:
# 吃到了食物
snake.appendleft(next_s)
score += food_style[0]
if REC_save: #记录得分
REC_score.pop()
REC_score.append(score)
if food_style[0] == FOOD_STYLE_LIST[3][0] and len(snake) > 3:
snake.pop()
snake.pop()
luck_times+=1
else:
speed = orispeed - 0.03 * (score // 100-luck_times)
food = create_food(snake)
food_style = get_food_style()
else:
if SCOPE_X[0] <= next_s[0] <= SCOPE_X[1] and SCOPE_Y[0] <= next_s[1] <= SCOPE_Y[1] \
and next_s not in snake: #判断下一步是否越界和碰到自己
snake.appendleft(next_s)
snake.pop() #没吃到食物,前进一步
else:
game_over = True
# 画食物
if not game_over:
# 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了
if food_style[0] == FOOD_STYLE_LIST[3][0]:
curTime = time.time()
if curTime-last_draw_time>0.01: #闪烁时间
pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)
last_draw_time=curTime
else:
pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)
# 画蛇
for s in snake:
pygame.draw.rect(screen, DARK, (s[0] * SIZE + LINE_WIDTH, s[1] * SIZE + LINE_WIDTH,
SIZE - LINE_WIDTH * 2, SIZE - LINE_WIDTH * 2), 0)
print_text(screen, font1, 30, font_ypos, f'速度: {score//100-luck_times}')
print_text(screen, font1, 630, font_ypos, f'得分: {score}')
if game_over:
if start:
print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)
TMP_score=copy.deepcopy(REC_score)
TMP_score.sort()
TMP_score.reverse()
if len(REC_score):
print_text(screen, font1, 230, font_ypos, f'最高得分: {TMP_score[0]}')
print_text(screen, font1, 430, font_ypos, f'当前排名: {TMP_score.index(REC_score[len(REC_score)-1])+1}')
else:
print_text(screen, font1, 230, font_ypos, f'最高得分: {score}')
print_text(screen, font1, 430, font_ypos, f'当前排名: {score}')
pygame.display.update()
if __name__ == '__main__':
main()
实验结果如下图:
二.实验过程
1. 设计游戏逻辑和界面
在编写代码之前,首先需要设计游戏的基本逻辑和界面布局。对于贪吃蛇游戏,你需要考虑以下几个方面:
- 游戏区域(棋盘)的大小和布局。
- 蛇的初始位置和移动规则。
- 食物的生成和蛇吃食物后的增长。
- 游戏结束条件,如蛇撞到自己或游戏边界。
- 用户界面,包括开始和结束按钮,分数显示等。
2. 创建游戏配置类
创建一个名为cfg
的配置类,包含游戏的一些配置信息,如屏幕大小、颜色、音乐路径等。
3. 创建游戏主函数
4. 创建游戏类和函数
创建游戏类和函数,如Snake
类和Apple
类,这些类定义了蛇和苹果的行为和绘制方法。
5. 主程序
最后,在主程序中创建cfg
实例,并调用main
函数开始游戏。
视频:
三.遇到的问题及解决方法
1.游戏界面无法正常显示:因为Pygame库没有正确安装或者Pygame的版本不兼容。
- 解决方法:使用
pip install pygame
安装Pygame
四.心得体会
学习编程确实需要时间和实践,每次解决问题或者实现一个新功能都像是打开了一个新世界的大门。从对Python的初步了解,包括其面向对象和面向过程的特点,到开发环境的熟悉,再到编写简单游戏如猜拳、数字运算和贪吃蛇等,数据类型、序列、字典、列表、元组、切片、网络编程Socket等等实践练习不仅积累了编程知识,还锻炼了逻辑思维和问题解决能力。其中我掌握比较深刻的内容是实验课程中服务器和客户端的网络代码编写以及猜拳小游戏的编写。
在学习过程中,王老师的专业指导和CSDN社区的帮助对我的至关重要。代码编写、错误避免、调试技巧以及有效沟通的能力,都是编程实践中不可或缺的技能。通过多次实验,我也明白,理论与实践相结合的学习方式是最有效的。
在未来的学习和工作中,我将继续深入学习Python及其相关技术,进一步提升自己的编程水平,提升解决问题的能力,增强数理基础能力。