20231425 李泽儒 《Python程序设计》实验四实验报告

20231425 李泽儒《Python程序设计》实验四实验报告

课程:《Python程序设计》
班级: 2314
姓名: 李泽儒
学号:20231425
实验教师:王志强
实验日期:2023年5月26日
必修/选修: 公选课

1.实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
我的实验内容:贪吃蛇小游戏

 这个贪吃蛇游戏的 Python 代码,使用了 Turtle 库实现。玩家通过键盘上下左右键控制蛇的移动方向,吃到食物后蛇身长度增加,每次移动时蛇头按照当前方向前进一格,蛇身跟随移动。当蛇头碰到边界或撞到自己的身体时,游戏结束并重新开始。

2. 实验过程及结果

主要函数

        ① reset():初始化游戏,包括重置蛇的位置和方向,生成初始食物位置,并调用 move_snake() 函数开始游戏循环。

        ② move_snake():处理蛇的移动逻辑,首先计算出蛇头的新位置,如果撞到自己的身体则调用 reset() 函数重新开始游戏,否则将新位置添加到蛇身列表中,如果没有吃到食物则弹出蛇尾,然后更新蛇的位置,并在画布上绘制蛇的每个部分。

        ③ food_collision():判断蛇是否碰到了食物,如果是则更新食物位置。

        ④ get_random_food_position():生成随机的食物位置。

        ⑤ get_distance():计算两个点之间的距离。

        ⑥ go_up()、go_right()、go_down() 和 go_left() 分别对应键盘上的上、右、下、左四个方向键

3.代码解释

1.导入需要用到的库 

 
import turtle
import random

2.定义游戏窗口的

长度、宽度、食物、蛇的大小以及初始速度。定义一个字典 offsets来存储每个方向对应的坐标偏移量。

w = 500
h = 500
food_size = 10
delay = 100
offsets = {
    "up": (0, 20),
    "down": (0, -20),
    "left": (-20, 0),
    "right": (20, 0)
}

 3. 定义全局变量:蛇的位置、移动方向、食物的位置和画笔。

snake = [[0, 0], [0, 20], [0, 40], [0, 60], [0, 80]]
snake_dir = "up"
food_position = get_random_food_position()
pen = turtle.Turtle("square")

 4. 定义函数 reset(),用于初始化游戏,包括重置蛇的位置和方向,生成初始食物位置,并调用 move_snake() 函数开始游戏循环。

def reset():
    global snake, snake_dir, food_position, pen
 
    snake = [[0, 0], [0, 20], [0, 40], [0, 60], [0, 80]]
    snake_dir = "up"
    food_position = get_random_food_position()
    food.goto(food_position)
    move_snake()

5. 定义函数 get_random_food_position(),用来生成随机的食物位置。

def get_random_food_position():
    x = random.randint(- w / 2 + food_size, w / 2 - food_size)
    y = random.randint(- h / 2 + food_size, h / 2 - food_size)
    return (x, y)

6. 定义函数 get_distance(),用于计算两个点之间的距离。

def get_distance(pos1, pos2):
    x1, y1 = pos1
    x2, y2 = pos2
    distance = ((y2 - y1) ** 2 + (x2 - x1) ** 2) ** 0.5
    return distance

7.定义函数 food_collision(),判断蛇是否吃到了食物,如果是则更新食物位置 。

def food_collision():
    global food_position
    if get_distance(snake[-1], food_position) < 20:
        food_position = get_random_food_position()
        food.goto(food_position)
        return True
    return False

8.定义函数 move_snake(),处理蛇的移动逻辑,计算出蛇头的新位置,如果撞到身体,则调用 reset() 函数重新开始游戏,否则将新位置添加到蛇身列表中,如果没有吃到食物则弹出蛇尾,然后更新蛇的位置,并在画布上绘制蛇的每个部分。

def move_snake():
    global snake_dir
    new_head = snake[-1].copy()
    new_head[0] = snake[-1][0] + offsets[snake_dir][0]
    new_head[1] = snake[-1][1] + offsets[snake_dir][1]
    if new_head in snake[:-1]:
        reset()
    else:
        snake.append(new_head)
        if not food_collision():
            snake.pop(0)
        if snake[-1][0] > w / 2:
            snake[-1][0] -= w
        elif snake[-1][0] < - w / 2:
            snake[-1][0] += w
        elif snake[-1][1] > h / 2:
            snake[-1][1] -= h
        elif snake[-1][1] < -h / 2:
            snake[-1][1] += h
        pen.clearstamps()
        for segment in snake:
            pen.goto(segment[0], segment[1])
            pen.stamp()
        screen.update()
        turtle.ontimer(move_snake, delay)

  9. 定义控制蛇移动方向的四个函数,分别对应键盘上的上、右、下、左四个方向键。

def go_up():
    global snake_dir
    if snake_dir != "down":
        snake_dir = "up"
 
def go_right():
    global snake_dir
    if snake_dir != "left":
        snake_dir = "right"
 
def go_down():
    global snake_dir
    if snake_dir != "up":
        snake_dir = "down"
 
def go_left():
    global snake_dir
    if snake_dir != "right":
        snake_dir = "left"

 10. 初始化游戏窗口、画笔和食物,设置背景颜色和画笔形状。通过键盘输入调用控制蛇移动方向的函数。最后调用 reset() 函数开始游戏。

screen = turtle.Screen()
screen.setup(w, h)
screen.title("Snake")
screen.bgcolor("blue")
screen.setup(500, 500)
screen.tracer(0)
 
food = turtle.Turtle()
food.shape("square")
food.color("yellow")
food.shapesize(food_size / 20)
food.penup()
 
screen.listen()
screen.onkey(go_up, "Up")
screen.onkey(go_right, "Right")
screen.onkey(go_down, "Down")
screen.onkey(go_left, "Left")
 
reset()
 
turtle.done()
 源代码
import turtle
 
import random
 
w = 500
 
h = 500
 
food_size = 10
 
delay = 100
 
offsets = {
 
    "up": (0, 20),
 
    "down": (0, -20),
 
    "left": (-20, 0),
 
    "right": (20, 0)
 
}
 
 
def reset():
    global snake, snake_dir, food_position, pen
 
    snake = [[0, 0], [0, 20], [0, 40], [0, 60], [0, 80]]
 
    snake_dir = "up"
 
    food_position = get_random_food_position()
 
    food.goto(food_position)
 
    move_snake()
 
 
def move_snake():
    global snake_dir
 
    new_head = snake[-1].copy()
 
    new_head[0] = snake[-1][0] + offsets[snake_dir][0]
 
    new_head[1] = snake[-1][1] + offsets[snake_dir][1]
 
    if new_head in snake[:-1]:
 
        reset()
 
    else:
 
        snake.append(new_head)
 
        if not food_collision():
            snake.pop(0)
 
        if snake[-1][0] > w / 2:
 
            snake[-1][0] -= w
 
        elif snake[-1][0] < - w / 2:
 
            snake[-1][0] += w
 
        elif snake[-1][1] > h / 2:
 
            snake[-1][1] -= h
 
        elif snake[-1][1] < -h / 2:
 
            snake[-1][1] += h
 
        pen.clearstamps()
 
        for segment in snake:
            pen.goto(segment[0], segment[1])
 
            pen.stamp()
 
        screen.update()
 
        turtle.ontimer(move_snake, delay)
 
 
def food_collision():
    global food_position
 
    if get_distance(snake[-1], food_position) < 20:
        food_position = get_random_food_position()
 
        food.goto(food_position)
 
        return True
 
    return False
 
 
def get_random_food_position():
    x = random.randint(- w / 2 + food_size, w / 2 - food_size)
 
    y = random.randint(- h / 2 + food_size, h / 2 - food_size)
 
    return (x, y)
 
 
def get_distance(pos1, pos2):
    x1, y1 = pos1
 
    x2, y2 = pos2
 
    distance = ((y2 - y1) ** 2 + (x2 - x1) ** 2) ** 0.5
 
    return distance
 
 
def go_up():
    global snake_dir
 
    if snake_dir != "down":
        snake_dir = "up"
 
 
def go_right():
    global snake_dir
 
    if snake_dir != "left":
        snake_dir = "right"
 
 
def go_down():
    global snake_dir
 
    if snake_dir != "up":
        snake_dir = "down"
 
 
def go_left():
    global snake_dir
 
    if snake_dir != "right":
        snake_dir = "left"
 
 
screen = turtle.Screen()
 
screen.setup(w, h)
 
screen.title("Snake")
 
screen.bgcolor("blue")
 
screen.setup(500, 500)
 
screen.tracer(0)
 
pen = turtle.Turtle("square")
 
pen.penup()
 
food = turtle.Turtle()
 
food.shape("square")
 
food.color("yellow")
 
food.shapesize(food_size / 20)
 
food.penup()
 
screen.listen()
 
screen.onkey(go_up, "Up")
 
screen.onkey(go_right, "Right")
 
screen.onkey(go_down, "Down")
 
screen.onkey(go_left, "Left")
 
reset()
 
turtle.done()

 4.代码运行过程视频及截图

 

Recording 2024-05-29 210438

5.遇到的问题及解决过程

1.变量作用域混淆:不清楚全局变量和局部变量的作用域及区别。在函数内部使用全局变量时,需要使用global关键字声明变量为全局变量。

def reset():
    global snake, snake_dir, food_position, pen
    # 其它代码......

2.边界处理错误:忽略蛇和食物在屏幕范围内的判断,导致游戏出现异常。需要确保蛇和食物在屏幕范围内移动,可以在移动蛇和生成食物的函数中做一些边界判断,确保它们不会超出屏幕范围。

if snake[0].xcor() > 290 or snake[0].xcor() < -290 or snake[0].ycor() > 290 or snake[0].ycor() < -290:
    game_over()

3.蛇吃到食物后的处理:在蛇头吃到食物时,需要更新蛇的长度并生成新的食物。确保在更新蛇长度时,正确地添加新的蛇身块,并更新蛇的长度。在生成新的食物时,确保新的食物位置不与蛇身重叠。

# 在蛇吃到食物的处理函数中
def food_collision():
    global food_position
    if snake[0].distance(food_position) < 20:
        # 更新蛇的长度
        new_segment = turtle.Turtle()
        new_segment.speed(0)
        new_segment.shape("square")
        new_segment.color("grey")
        new_segment.penup()
        snake.append(new_segment)
        
        # 生成新的食物
        food_position = (random.randint(-290, 290), random.randint(-290, 290))
        food.goto(food_position)

4.处理按键事件时的方向冲突:在处理按键事件时,需要避免用户输入方向与当前行进方向相反,否则会导致蛇立即反转方向而撞到自己。可以添加一些判断逻辑来避免这种情况。

# 在处理按键事件的函数中
def go_up():
    if snake_dir != "down":
        snake_dir = "up"
 

6. 课程总结及感想

在python公选课中,王老师的认真教学和耐心指导,以及诙谐轻松的授课方式,让我学到了很多python的基础知识,给我留下来深刻的印象。例如:

  1. 基础知识学习: Python 的基本语法、数据类型、条件语句、循环等基础知识。
  2. 函数和模块:函数的定义和调用,以及模块的导入和使用。
  3. 面向对象编程:面向对象编程的概念,掌握了类、对象、继承、多态等相关知识。
  4. 异常处理:了解了异常处理机制,学会使用 try...except 来捕获和处理异常。
  5. 文件操作:学习了如何打开、读取、写入和关闭文件,以及文件操作的各种方法。

 学习了 Python,让我感受到了编程的乐趣和挑战。一开始,我对编程的理解停留在抽象的代码和逻辑上,但通过学习 Python,我深刻体会到编程可以是如此的具象而生动。

在课堂上,我享受着不断解决问题的成就感,一行行的代码仿佛是我的思维延伸出的触手,慢慢地构建出了一个个实用而美妙的功能。在遇到错误和异常的时候,我学会了深呼吸、耐心排查,最终一一解决问题,这种成就感是无法言表的。

更让我着迷的是 Python 的简洁和强大。它的语法简单明了,让我不再畏惧冗长的代码,而是享受着一种近乎自然的表达。同时,Python 丰富的库和模块为我打开了新世界的大门,我可以轻松地处理数据、绘制图表,甚至进行网络请求,让我感受到了自己变得更加强大。

学习 Python 还带给我更多的思考。编程不仅仅是为了完成任务,更像是一种创造和思考的过程。不断追求更加优雅、高效的代码,思考如何更好地解决问题,这些都让我有了更深入的思考和锻炼。

总的来说,学习 Python 让我找到了与代码交融的幸福感。它不再是冰冷的工具,而是一种充满情感和创造力的媒介,让我能够将自己的想法、理解以及灵感转化为实实在在的东西。通过python,我们可以实现许多难以实现的功能,极大地提高了我们的工作效率,就像我们公选课的口号:

人生苦短,我用python!

  • 49
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值