Tkinter和龟蛇游戏

时间:2020-01-31 13:13:24

标签: python tkinter turtle-graphics tkinter-canvas

我一直在尝试Tkinter的画布功能。我把乌龟放在画布上,试图做一个蛇游戏。我尝试运行代码,但遇到了一些问题:

  1. 按退出键退出时不打印分数

  2. 您只能拿起笔一次,不能放回或再放一次,

  3. 有时您不会在实际看到的屏幕上生成称为玩家的乌龟

  4. 当您触摸名为玩家的乌龟或移动名为玩家的乌龟时,名为t的乌龟不会增加得分。

可能还有其他问题,但这是我所知道的。

这是我的代码:

import tkinter as tk
import random
import turtle
import time
import sys

game = False
forward = False
left = False
right = False
backward = False
draw = True
score = 0

def spawn(e=None):
    t.penup()
    t.goto(0,0)
    player=turtle.RawTurtle(app)
    player.penup()
    player.shapesize(0.5,0.5)
    player.shape("square")
    player.color("black")
    xrand = random.randint(-100, 100)
    yrand = random.randint(-100, 100)
    player.goto(x=xrand,y=yrand)
    if t.distance(player) <15:
        x = random.randint(-100, -100)
        y = random.randint(-100, -100)
        player.goto(x,y)
        score = score+1

def systemap(e=None):
    app.place(x=100,y=-4)
    button.place(x=660,y=470)

def f(e=None):
    if game == False:
        t.setheading(90)
        t.forward(5)
    elif game == True:
        forward == True
        while forward == True:
            left == False
            right == False
            backward == False
            t.forward(5)
        if forward == False:
            t.setheading(90)
            t.forward(5)

def l(e=None):
    if game == False:
        t.setheading(180)
        t.forward(5)
    elif game == True:
        left == True
        while left == True:
            forward == False
            right == False
            backward == False
            t.forward(5)
        if left == False:
            t.setheading(180)
            t.forward(5)

def r(e=None):
    if game == False:
        t.setheading(0)
        t.forward(5)
    elif game == True:
        right == True
        while right == True:
            forward == False
            left == False
            backward == False
            t.forward(5)
        if right == False:
            t.setheading(0)
            t.forward(5)

def b(e=None):
    if game == False:
        t.setheading(270)
        t.forward(5)
    elif game == True:
        backward == True
        while backward == True:
            forward == False
            left == False
            right == False
            t.forward(5)
        if backward == False:
            t.setheading(270)
            t.forward(5)

def quit(e=None):
    if game == False:
        time.sleep(1)
        window.destroy()
        sys.exit()
    elif game == True:
        time.sleep(2)
        window.destroy()
        print("Score: ",score)
        sys.exit()

def pen(e=None):
    if draw == True:
        t.penup()
        draw == False
    if draw == False:
        t.pendown()
        draw == True

window = tk.Tk()
window.iconbitmap('py.ico')
window.title("Turtle Graphics")
window.geometry("750x500")
window.resizable(False, False)

button = tk.Button(window,
                   text="      Close      ",
                   font="Calibri",
                   borderwidth=0,
                   background="White",
                   command=quit)

app = tk.Canvas(master=window, width=500, height=500, bg="white")

t=turtle.RawTurtle(app)

window.bind("<Up>", f)
window.bind("<Left>", l)
window.bind("<Right>", r)
window.bind("<Down>", b)

window.bind("<w>", f)
window.bind("<a>", l)
window.bind("<d>", r)
window.bind("<s>", b)

window.bind("<p>", pen)

window.bind("<Escape>", quit)

window.bind("<g>", spawn)

systemap()

window.mainloop()

2 个答案:

答案 0 :(得分:0)

因此,这里需要进行一些更正。我认为您对某些事情有一些误解。

  1. 您需要在函数中定义global,这些函数包含全局名称空间中的变量或需要存在于全局名称空间中的变量。如果不这样做,则在尝试更新变量时会遇到类似local variable 'score' referenced before assignment之类的错误。

  2. ==仅是比较。您正在需要单个=的地方使用它。

  3. 您定义了一个名为quit的函数,这是一个内置方法。请注意不要覆盖内置方法。

  4. 您永远不会看到打印出来的分数,因为game始终为False。您的代码中没有任何内容将其更改为True。

  5. whilesleep()不应与tkinter在同一线程中使用。这将导致问题,因为这两种方法都会阻塞mainloop。一种解决方法是使用after()方法或线程。在这种情况下,我认为线程处理是多余的,after()在这里可能是更好的选择。

最后,我不确定您是否需要在其中添加game = True

这是您的代码整理了一下。我已经纠正了所列的大部分内容,但没有更多详细信息,我无法猜测其余的内容。

如果您有任何疑问,请告诉我:

import tkinter as tk
import random, turtle

game = False
forward = False
left = False
right = False
backward = False
draw = True
score = 0


def spawn(_=None):
    global score, forward, left, backward, player
    t.penup()
    t.goto(0, 0)
    player = turtle.RawTurtle(app)
    player.penup()
    player.shapesize(0.5, 0.5)
    player.shape("square")
    player.color("black")
    xrand = random.randint(-100, 100)
    yrand = random.randint(-100, 100)
    player.goto(x=xrand, y=yrand)
    if t.distance(player) < 15:
        x = random.randint(-100, -100)
        y = random.randint(-100, -100)
        player.goto(x, y)
        score = score + 1


def systemap(_=None):
    app.place(x=100, y=-4)
    button.place(x=660, y=470)


def f(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(90)
        t.forward(5)
    else:
        forward = True
        while forward:
            left = False
            right = False
            backward = False
            t.forward(5)
        if not forward:
            t.setheading(90)
            t.forward(5)


def l(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(180)
        t.forward(5)
    else:
        left = True
        while left:
            forward = False
            right = False
            backward = False
            t.forward(5)
        if not left:
            t.setheading(180)
            t.forward(5)


def r(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(0)
        t.forward(5)
    else:
        right = True
        while right:
            forward = False
            left = False
            backward = False
            t.forward(5)
        if not right:
            t.setheading(0)
            t.forward(5)


def b(_=None):
    global forward, left, right, backward
    if not game:
        t.setheading(270)
        t.forward(5)
    else:
        backward = True
        while backward:
            forward = False
            left = False
            right = False
            t.forward(5)
        if not backward:
            t.setheading(270)
            t.forward(5)


def quit_func(_=None):
    if not game:
        window.destroy()
    else:
        window.destroy()
        print("Score: ", score)


def pen(_=None):
    global draw
    if draw:
        t.penup()
        draw = False
    else:
        t.pendown()
        draw = True


window = tk.Tk()
window.title("Turtle Graphics")
window.geometry("750x500")
window.resizable(False, False)
button = tk.Button(window, text="Close", font="Calibri", borderwidth=0, background="White", command=quit_func)
app = tk.Canvas(master=window, width=500, height=500, bg="white")
t = turtle.RawTurtle(app)

window.bind("<Up>", f)
window.bind("<Left>", l)
window.bind("<Right>", r)
window.bind("<Down>", b)
window.bind("<w>", f)
window.bind("<a>", l)
window.bind("<d>", r)
window.bind("<s>", b)
window.bind("<p>", pen)
window.bind("<Escape>", quit_func)
window.bind("<g>", spawn)

systemap()
window.mainloop()

答案 1 :(得分:0)

我看到的主要问题是您希望乌龟与程序用户一起不断移动,只改变方向。我不相信您会像这样的无限循环获得这种效果:

    while right == True:
        forward == False
        left == False
        backward == False
        t.forward(5)

这依赖于某个外部事件来更改right的值,但并没有真正暂停让其他事件运行。 (加上===的错误使用。)

其他问题包括:

由于符号错误,玩家只能重定位一次,总是重定位到同一位置:

x = random.randint(-100, -100)
y = random.randint(-100, -100)

缺少必要的global语句以及===的滥用:

def pen(e=None):
    if draw == True:
        t.penup()
        draw == False
    if draw == False:
        t.pendown()
        draw == True

如果不测试这些基本功能中的某些功能,那么您应该从来没有像现在这样编码过。您编写的未经测试的代码越多,调试起来就越困难。

下面是我对您的代码的重做,实现了乌龟(蛇)的恒定运动。我还将一些与乌龟相关的代码从tkinter领域移到了乌龟方法中。我为示例简化了一些操作(例如,只有一组运动键,箭头。)但我相信它现在是一个非常基本但可玩的游戏:

import tkinter as tk
from turtle import TurtleScreen, RawTurtle
from random import randint

direction = None
score = 0

def spawn():
    player = RawTurtle(screen)
    player.hideturtle()
    player.shape('square')
    player.shapesize(0.5)
    player.color('black')
    player.penup()

    x = randint(-100, 100)
    y = randint(-100, 100)
    player.goto(x, y)
    player.showturtle()

    players.append(player)

def check_collision():
    global score

    for player in players:
        if turtle.distance(player) < 15:
            x = randint(-100, 100)
            y = randint(-100, 100)
            player.goto(x, y)
            score += 1

def f():
    global direction

    def move():
        check_collision()

        if direction == 'forward':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'forward':
        direction = 'forward'
        turtle.setheading(90)
        move()

def l():
    global direction

    def move():
        check_collision()

        if direction == 'left':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'left':
        direction = 'left'
        turtle.setheading(180)
        move()

def r():
    global direction

    def move():
        check_collision()

        if direction == 'right':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'right':
        direction = 'right'
        turtle.setheading(0)
        move()

def b():
    global direction

    def move():
        check_collision()

        if direction == 'backward':
            turtle.forward(5)
            screen.ontimer(move, 100)

    if direction != 'backward':
        direction = 'backward'
        turtle.setheading(270)
        move()

def pen():
    if turtle.isdown():
        turtle.penup()
    else:
        turtle.pendown()

def quit_game(e=None):  # called from either turtle or tkinter
    window.destroy()
    print("Score:", score)
    exit()

players = []

window = tk.Tk()
# window.iconbitmap('py.ico')
window.title("Turtle Graphics")
window.geometry("600x600")
window.resizable(False, False)

canvas = tk.Canvas(master=window, width=500, height=500)
canvas.pack()

tk.Button(window, width=17, text='Close', borderwidth=0, command=quit_game).pack()

screen = TurtleScreen(canvas)
turtle = RawTurtle(screen)

screen.onkey(f, 'Up')
screen.onkey(l, 'Left')
screen.onkey(r, 'Right')
screen.onkey(b, 'Down')

screen.onkey(pen, 'p')
screen.onkey(quit_game, 'Escape')
screen.onkey(spawn, 'g')

screen.listen()
screen.mainloop()

enter image description here