贪吃蛇 python 标准模块实现

304 阅读8分钟
title: 贪吃蛇
date: 2023-04-18
updated:  2023-04-18
tags: 小游戏
categories: Python

要求

对象:

一条蛇、一个怪物和 一些食物,由一组介于 1 和 9 之间的数字表示,头和尾巴分别以红色和黑色显示 ,而怪物则由 紫色方块显示。 数字是蛇吃的食物

界面:

以下屏幕显示了蛇吃完所有食物后游戏的结局 包括完全伸展的尾巴;状态区域显示的是与怪物的接触次数 以及 以 秒为单位的总游戏时间

image-20230424193838387

画布:

上部状态区域 = 500 (宽) x 80

游戏状态 :

a. 显示蛇的运动(左、右、上、下、暂停),换句话说,最后一个 按下运动键(包括空格键),无论蛇是否在 运动或贝因G受阻。

b. 显示蛇与怪物的身体接触总数。 计数应 基于怪物计时器的运动。 每次重新定位怪物时,它 然后应该检查它是否与蛇的任何部分重叠。

c. 以 秒为单位跟踪经过的总游戏时间。 时间计数器尽快启动 因为游戏开始,只有在游戏结束时才会停止。 换句话说,计数器 当蛇被暂停时不会被阻止。

规则:

食物:

在随机位置显示运动区域内从 1 到 5 的 5 种食物。 这些 数字将始终保持可见,直到它们被蛇吞噬。 当 蛇头越过这些数字之一, 被划过的数字是 被视为已消耗,它将从游戏区域永久删除。 所以,任何 一种食物可以食用一次

一个单位长度,因此尾巴在 完全伸展时将由 5 个方形组成

怪物 :

a、一个固定大小的物体,被编程为 向蛇移动,试图做出 正面碰撞。

b. 启动时,将怪物放置在与蛇保持一定距离的随机位置。

c. 怪物应该以随机的速度移动

蛇:

在游戏开始时,尾巴的长度设置为 5。 一个正方形算作

按下空格蛇暂停,怪物不暂停

游戏内核

通过定时器运动

a. “计时器”是指特定事件以固定间隔发生的频率,在 在这种情况下,事件是蛇或怪物的运动。

b. 使用 单独的 计时器手动刷新蛇和怪物的移动 一. 关闭 内置的自动屏幕刷新

c. 设置适当的计时器速率,例如不超过 0.2 秒

模块

仅使用标准 python 模块

制作思路

界面:turtle

定时器:time

随机数:random

学习路线

界面

使用turtle,找看看turtle的刷新机制

划分游戏区域、游戏状态、边缘

turtle 键盘监听

对象与动作构建

创建蛇、怪物、食物类

turtle用到的方法

Python中的turtle.onkey()函数|极客教程 (geek-docs.com)

turtle .ontimer()

import turtle
import time
import random

global pre_direction,snake,snake_hide,monster,head,food,pen,pen1,num_array,food_num,wn,contact,delay,num_str,count,pre_x,pre_y,starttime ,endtime, last_length,time_eated,time_win
## 怪物
monster = turtle.Turtle()
monster.shape("square")
monster.color("purple")
monster.penup()
monster.goto(200, 200)
monster.direction = "Stop"
pre_direction = "Stop"
monster.speed(1)








##b标题画笔
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("black")
pen.penup()
pen.hideturtle()  # 隐藏笔迹
pen.goto(0, 210)
pen.write("Score : 0  High Score : 0", align="center",
               font=("candara", 24, "bold"))
#画布画笔
pen1 = turtle.Turtle()
pen1.speed(0)
pen1.shape("square")
pen1.color("black")
pen1.penup()
pen1.hideturtle()  # 隐藏笔迹
pen1.goto(-250, 210)
pen1.pendown()
pen1.forward(500)
pen1.right(90)
pen1.forward(500)
pen1.right(90)
pen1.forward(500)
pen1.right(90)
pen1.forward(580)
pen1.right(90)
pen1.forward(500)
pen1.right(90)
pen1.forward(580)



#主窗体
starttime = time.time()
endtime = time.time()
count = 3
stop_flag = 0
contact = 5
delay = 0.1
high_contact = 0
# x = 0
# y = 0
wn = turtle.Screen()  ##画笔对象
wn = turtle.Screen()
wn.title("Snake Game")
wn.bgcolor("white")
# the width and height can be put as user's choice
wn.setup(width=580, height=660)
wn.tracer(0)




##蛇
def group():
    if head.direction != "down":
        head.direction = "up"


def godown():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count
    if head.direction != "up":
        head.direction = "down"


def goleft():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count
    if head.direction != "right":
        head.direction = "left"


def goright():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count
    if head.direction != "left":
        head.direction = "right"


def stop():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count,pre_direction

    # print(pre_direction)
    if head.direction != "stop":
        pre_direction = head.direction
        head.direction = "stop"
        return
    if head.direction == "stop":
        head.direction = pre_direction
        print("之前动作",pre_direction)
        print("尝试恢复",head.direction)
        return


# 食物
def del_num():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count
    ##关键代码,解决无法删除列表中某个值的问题
    if len(num_array) > 0:
        for i in reversed(range(len(num_array))):
            if num_array[i] == num_str:
                del num_array[i]
                # print(num_array[i])
def move():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count
    if head.direction == "up":
        y = head.ycor()
        head.sety(y + 20)
    if head.direction == "down":
            y = head.ycor()
            head.sety(y - 20)
    if head.direction == "left":
            x = head.xcor()
            head.setx(x - 20)
    if head.direction == "right":
            x = head.xcor()
            head.setx(x + 20)
#设置监听
wn.listen()
wn.onkeypress(group, "w") # if food_num == 0:
wn.onkeypress(stop," ")
wn.onkeypress(godown, "s")
wn.onkeypress(goleft, "a")
wn.onkeypress(goright, "d")


def staus_upgrade():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count,starttime ,endtime
    pen.clear()
    endtime = time.time()
    time_c = int(endtime - starttime)
    # print(time_c)
    pen.write("Contact: {} Time: {} Motion {} ".format(
        contact, time_c, head.direction), align="center", font=("candara", 18, "bold"))

def food_born():
    global food_num,foods,num_array,num_str,foods,num_array1,num_food
    food_x_array = []
    for i in range(0,food_num,1):
        food_x_array.append(random.randrange(-200,200))
    food_y_array = []
    for i in range(0,food_num,1):
        food_y_array.append(random.randrange(-270,200))
    #随机加载 1~ 5个食物

    foods= []
    for i in range(0,food_num,1):
        print("food_num", food_num, "num_array", num_array)
        food = turtle.Turtle()
        food.speed(0)
        food.shape("square")
        food.color("black")
        food.penup()
        food.hideturtle()  # 隐藏海龟
        food.goto(food_x_array[i], food_y_array[i])
        # num_str = random.choice(num_array)
        num_str =str(num_array[i])
        up_or_down = random.choice([0,1])
        if food_num == 1:
            up_or_down= 0
        print("up_or_down",up_or_down)
        if up_or_down == 0:
            print("food_generated",num_str)
            food.write(num_str, align="center",
                       font=("candara", 24, "bold"))
        else:
            pass
        foods.append(food)
        # time.sleep(0.05)
def If_Over():
    global foods
    global collision_flag,time_eated, time_win, monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count, starttime, endtime,last_length
    if food_num == 0:
        # food.clear()
        print("here")
        time_win = time.time()
        print(int(time_win - time_eated))
        if int(time_win - time_eated) > 2:
            for index in range(0,len(foods),1):
                foods[index].clear()
                time.sleep(0.2)
                kill_food()
                foods= []
            time.sleep(1)
            head.goto(1000, 1000)
            head.direction = "stop"
            head.clear()
            for segment in segments:
                segment.goto(1000, 1000)
            segments.clear()
            contact = 5
            delay = 0.1
            # pen1.pen.clear()
            pen.write("Contact: {} Time: {} Motion {} ".format(0, 0, 0), align="center", font=("Arial", 24, "bold"))
            init()
    if  collision_flag or head.xcor() > 250 or head.xcor() < -250 or head.ycor() > 210 or head.ycor() < -290:
        # food.clear()
        kill_food()
        time.sleep(1)
        head.goto(1000, 1000)
        head.direction = "stop"
        head.clear()
        monster.goto(200,200)
        for segment in segments:
            segment.goto(1000, 1000)
        segments.clear()
        contact = 5
        delay = 0.1
        # pen1.pen.clear()
        pen.write("Contact: {} Time: {} Motion {} ".format(0, 0, 0), align="center",font=("Arial", 24, "bold"))
        init()

def kill_food():
    global food_num,foods
    # for i in range(0,food_num):
    #     foods[i].clear()
    if len(foods)>0 :
         for i in range(0,len(foods)):
            foods[i].goto(3000,3000)
            foods[i].clear()
    foods = []

def food_eated():
    global snake_hide,monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count, last_length,time_eated
    global foods,food_x_array,food_y_array,num_array1
    for index in reversed(range(0,len(foods))):
        # print("index--------------------------",index)
        if head.distance(foods[index]) < 20:
            if food_num > 0:
                food_num -= 1
            # print("food_num",food_num)
            # print("index......",index,"num_aray1",num_array1)
            foods[index].clear()
            time.sleep(0.1)
            kill_food()
            # del foods[index]
            time_eated = time.time()
            if int(num_array[index]) > 0:
                snake_hide += int(num_array[index])
                for i in range(int(num_array[index])):
                    new_segment = turtle.Turtle()
                    new_segment.speed(0)
                    new_segment.shape("square")
                    # new_segment.color(
                    #     "black")  # tail colour
                    new_segment.color("black")
                    new_segment.penup()
                    new_segment.setx(1000)
                    new_segment.sety(1000)
                    # new_segment.goto(x, y)
                    segments.append(new_segment)
                print("len seg", len(segments))
                contact += int(num_array[index])
                print("clear", num_array[index])
                del num_array[index]
            # num_str ='0'
            if food_num > 0:
                food_born()
            print("food_num ", food_num)
            # del_num()
            # if food_num > 0:
            #     foods[index].write(num_str, align="center",
            #                font=("candara", 20, "bold"))
            delay -= 0.001
            staus_upgrade()

def seg_move():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count,pre_x,pre_y
    ##身体第一块跑向头
    if head.direction != "stop":
        if len(segments) > 0:
            # pre_seg = turtle.Turtle()
            # pre_seg.shape("square")
            # # new_segment.color(
            # #     "black")  # tail colour
            # pre_seg.color(random.choice(["green", "red", "blue", "black", "yellow", "pink"]))
            # pre_seg.penup()
            pre_x = segments[0].xcor()
            pre_y = segments[0].ycor()
            # pre_seg.goto(x, y)
            x = head.xcor()
            y = head.ycor()
            segments[0].goto(x, y)
        for index in range(len(segments) - 1, 0, -1):
            # for index in range(0,len(segments)-1, 1)
            if index == 1:
                segments[1].goto(pre_x, pre_y)
                return
            x = segments[index - 1].xcor()
            y = segments[index - 1].ycor()
            segments[index].goto(x, y)

def chase():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count
    x = head.xcor()
    y = head.ycor()
    x1 = monster.xcor()
    y1 = monster.ycor()
    # if abs(y1-y) > abs(x1-x):
    #     if y1 < y:
    #         monster1.monster.sety(y1 + 20)
    #     else:
    #         .sety(y1 - 20)
    # else:
    #     if x1 < x:
    #         .setx(x1 + 20)
    #     else:
    #         .setx(x1 - 20)
    # wn.tracer(n=5, delay=0)
    if abs(y1 - y) > abs(x1 - x):
        if y1 < y:
            monster.seth(90)
            monster.forward(20)
        else:
            monster.seth(270)
            monster.forward(20)
    else:
        if x1 < x:
            monster.seth(0)
            monster.forward(20)
        else:
            monster.seth(180)
            monster.forward(20)

def if_chased():
    global snake,collision_flag,segments,head,monster
    # seg = segments
    # seg.append(head)
    for index in range(0,len(snake),1):
        if snake[index].distance(monster) <20:
            time.sleep(1)
            head.goto(0, 0)
            head.direction = "stop"
            print("here..........qqqq.....................")
            colors = random.choice(['red', 'blue', 'green'])
            shapes = random.choice(['square', 'circle'])
            for segment in segments:
                segment.goto(1000, 1000)
            segment.clear()
            collision_flag = 1

def if_head_runto_body():
    global collision_flag,segments
    for segment in segments:
        if segment.distance(head) < 20 and snake_hide == 0:
            time.sleep(1)
            head.goto(0, 0)
            head.direction = "stop"
            print("here...............................")
            colors = random.choice(['red', 'blue', 'green'])
            shapes = random.choice(['square', 'circle'])
            for segment in segments:
                segment.goto(1000, 1000)
            segment.clear()
            collision_flag = 1
            contact = 0
            delay = 0.1

def init():
    global monster, head, food, pen, pen1, num_array, food_num, wn, contact, delay, num_str, count, starttime , endtime
    global segments,snake_hide,collision_flag,food_x_array ,food_y_array ,foods,num_array1,count2
    # 初始化
    count2 = 10
    contact = 5
    collision_flag = 0
    starttime = time.time()
    endtime = time.time()
    segments = []
    # food.clear()
    # num_array = ['1', '2', '3', '4', '5']
    # food_num = 5

    # 蛇
    head = turtle.Turtle()
    head.shape("square")
    head.color("red")
    head.penup()
    head.goto(0, 0)
    head.direction = "stop"
    pre_direction = "stop"
    segments = []

    # 食物
    num_array = ['1', '2', '3', '4', '5']
    num_array1 = ['1', '2', '3', '4', '5']
    food_num = 5
    food_born()
    snake_hide = 5
    for i in range(5):
        new_segment = turtle.Turtle()
        new_segment.speed(0)
        new_segment.shape("square")
        # new_segment.color(
        #     "black")  # tail colour
        new_segment.color("black")
        new_segment.penup()
        new_segment.setx(1000)
        new_segment.sety(1000)
        # new_segment.goto(x, y)
        segments.append(new_segment)

def Game_Start():
    global count2,snake,snake_hide,monster,head,food,pen,pen1,num_array,food_num,wn,contact,delay,num_str,count,last_length,segments
    ## 蛇走n步 ,怪物走 1 步
    wn.update()
    # food.write(num_str, align="center",
    #            font=("candara", 24, "bold"))
    count -= 1
    if count == 0:
        count = random.choice([ 2, 3, 4])
        chase()
    count2 -= 1
    if count2 == 0 :
        count2 = 50
        kill_food()
        food_born()

    ##游戏结束
    food_eated()
    snake = []
    snake.append(head)
    for i in range(0,len(segments),1):
        snake.append(segments[i])
    If_Over()
    # len(segments)
    seg_move()

    move()
    if snake_hide > 0 and head.direction != "stop":
        snake_hide -= 1
        time.sleep(0.05)
    # print("hide'''''",snake_hide)
    # Checking for head collisions with body segments
    if_head_runto_body()
    if_chased()
    staus_upgrade()
    wn.ontimer(Game_Start, 100)

init()
seg_move()
Game_Start()
wn.mainloop()
# if __name__ == "main":
#      Game_Start()
#      wn.mainloop()