简体   繁体   English

使用onkey()和字典使用turtle(python)绘制错误

[英]Bugs drawing with turtle(python) using onkey() and dictionaries

I decided redo this question as per advice I received, This is an assignment question I have been given for 1st year uni, python coding. 我决定根据收到的建议重做此问题,这是我为一年级uni,python编码给出的作业问题。 I have bugs in my code and Can't figure out where to fix them. 我的代码中有错误,无法找出在哪里修复。 BUG 1 The turtle starts drawing when program is ran even though pen is up. BUG 1即使笔在上面,当程序运行时,乌龟也开始绘图。 BUG 2 undefined key such as 's, 7, tab' trigger space_bar function BUG 2未定义的键,例如's,7,tab'触发space_bar函数

COLOURING BOOK 彩色书

In this task you create a children's colouring game in which given pictures can be coloured by tracing around a shape and then filling it. 在此任务中,您将创建一个儿童着色游戏,其中可以通过跟踪形状然后填充来给给定的图片着色。 The controls are as follows. 控件如下。

ARROW KEYS - Move the "brush" (turtle cursor) left, right, up or down by a fixed small amount. 箭头键-向左,向右,向上或向下移动固定的少量“笔刷”(乌龟光标)。

'z' - Undo the last step. 'z'-撤消最后一步。

'r', 'g', 'b' - Change the brush colour to red, green or blue, respectively. 'r','g','b'-分别将画笔颜色更改为红色,绿色或蓝色。 (You can define more colours if you like, but we expect at least these three.) (您可以根据需要定义更多颜色,但我们至少希望这三种颜色可以使用。)

SPACE BAR - Toggle the painting mode. 空格键-切换绘画模式。 In "move" mode, which is the initial mode, the "brush" (turtle) moves around the screen without drawing. 在“移动”模式(这是初始模式)下,“画笔”(乌龟)在屏幕上移动而不画图。 In "paint" mode the brush leaves a coloured line as it moves. 在“绘画”模式下,画笔在移动时会留下一条彩色的线。 Most importantly, when the mode is changed from "paint" to "move", the area traced out by the brush is filled with colour. 最重要的是,当模式从“绘画”更改为“移动”时,笔刷描出的区域将充满颜色。

from turtle import *
from functools import partial 
bgpic("Colour_A_Turkey.gif") # change this to change the picture

#control the accuracy/speed of the drawing 
step_size =8
pensize(4)
penup()

# whenever spacebar is pressed the current state  and next state switch values 
current_state = penup
next_state = pendown
def space_bar():
    global current_state, next_state
    next_state()
    current_state, next_state = next_state, current_state
    #if the current stat is penup fill in with current colour
    if current_state == penup:
        end_fill()
    else:
        begin_fill()
onkey(space_bar, " ")

# undo do a mistake function
def mistake():
    undo()
onkey(mistake, "z")

#using partial function to store the following functions
#so they can be called  as arguments from a dictionary
#movement
strait = partial(fd, step_size)
reverse = partial(bk, step_size)
turn_rt = partial(rt, step_size)
turn_lf = partial(lt, step_size)

#colour
brow = partial(color, "brown")
gree = partial(color, "green")
yell = partial(color, "yellow")
oran = partial(color, "orange")
purp = partial(color, "purple")
red = partial(color, "red")
blue = partial(color, "blue")


#create a dictionary to store all the keys and there abilities 
key_action = {"b" : blue, "r" : red, "p" : purp, "o" : oran,\
          "y" : yell, "g" : gree, "w" : brow, "Right" : turn_rt , "Up" : strait,\
          "Down" : reverse, "Left" : turn_lf, "z" : undo()}

#when a key in then above dictionary
#is pressed it's function  is activated
for pressed_key, activated_key in key_action.items():
    onkey(activated_key, pressed_key)  

#make turtle look for key strokes with predefined function
listen()
#finish
done()

Remember, in Python, everything is an object and we really mean that . 请记住,在Python中, 一切都是对象,而我们的意思是 Functions are objects too. 函数也是对象。 We can store functions in a dictionary, and in fact that's exactly what you seem to want to do here. 我们可以将函数存储在字典中,实际上,这正是您似乎想要在此处执行的操作。

turn_lf = lt(step_size )

The key problem here is that you want to store "a function that calls lt with step_size as the argument", but here you have just called lt with step_size as an argument immediately, and stored the return value. 这里的关键问题是您要存储“一个以step_size作为参数调用lt的函数”,但是这里您只是立即以step_size作为参数调用lt并存储了返回值。

Arguably the simplest way to get what you want is to use functools.partial to "bind" the step_size argument. 可以说,获得所需内容的最简单方法是使用functools.partial来“绑定” step_size参数。

from functools import partial
turn_lf = partial(lt, step_size) # `lt` is not called yet.

# Now, later on, we can do
turn_lf() # and it's just as if we did `lt(step_size)`.
# So now we can store `turn_lf` in a dict, look it up and call it later, etc.

# Similarly for all the other functions you want to make.

(Another problem is that you haven't been consistent with this; if you want everything to go in one dict, then you need to indicate the bindings for the color function as well. 'brown' is just a string, after all. Fortunately, this is just as simple as with the other functions: we just make our partial(color, 'brown') . (另一个问题是您与此不一致;如果您希望所有内容都包含在一个字典中,那么您还需要指明color函数的绑定。毕竟, 'brown'只是一个字符串。幸运的是, ,这和其他函数一样简单:我们只需要创建partial(color, 'brown')

As for "z" : delete , well - we don't have any arguments to bind to undo . 至于"z" : delete ,-没有绑定到undo参数。 So while we could follow the pattern and write partial(undo) (notice, no more arguments, because we aren't binding anything), it makes much more sense to just write undo directly. 因此,尽管我们可以遵循该模式并编写partial(undo) (注意,没有更多参数,因为我们没有绑定任何东西),但直接编写undo更为有意义。

As an aside, we can simplify this: 顺便说一句,我们可以简化一下:

for key in key_action:
    pressed_key = key
    activated_key = key_action[key]

To this: 对此:

for pressed_key, activated_key in key_action.items():

Why define all the functions? 为什么要定义所有功能? We can directly use: Break the dict as : 我们可以直接使用:将dict打破为:

key_action = {"b" : "blue", "r" : "red", "p" : "purple", "o" : "orange", "y" : "yellow","g" : "green", "w" : "brown","Right" : rt , "Left": lt, "Up" : fd, "Down" : bk,"z" : undo}


no_input = ["z"]

one_input = ["Right", "Left", "Up", "Down"]

for key in key_action:
    activated_key = key_action[key]
    if key in no_input:
       activated_key()
    elif key in one_input():
        activated_key(step_size)
    else:
        onkey(color(activated_key), key)

Your dictionary approach is along the right way of thinking. 您的字典方法是正确的思维方式。 However, your function will not behave correctly. 但是,您的功能将无法正常运行。 Using a dictionary is simplier than you think. 使用字典比您想象的要简单。 First of all you have to have separate FUNCTIONS against STRING and handle them correctly. 首先,您必须针对STRING使用单独的FUNCTIONS并正确处理它们。 As each of them will behave differently: 由于它们各自的行为不同:

# Get rid of the top four lines, they will not work
# All actions mapping
key_action = {"b" : "blue", "r" : "red", "p" : "purple", "o" : "orange",
              "y" : "yellow", "g" : "green", "w" : "brown",
              "Right" : rt , "Left": lt, "Up" : fd, "Down" : bk,
              "z" : undo}
# Note down which are special actions
# Functions with no input
foo = ["z"]
# Function with one input
bar = ["Right", "Left", "Up", "Down"]

# Assuming the input key is get here, I don't use turtle don't know how
# the input is read
key = listen()  # PSEUDOCODE!

# Handle the input
if key in foo:
     foo[key]() # Execute no input function
elif key in bar:
     foo[key](step_size)
else:
     onkey(key_action[key], key)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM