Python:绘制非重叠圆圈 - 递归失败, 'while' 有效

标签 python python-3.x tkinter tk-toolkit

我正在创建一个游戏,它会要求用户按数字顺序点击一系列圆圈。我的问题是第 2 行之间。 91 和没有。 110:为什么递归逻辑会生成重叠的圆圈,即使我检查了那个条件,但 while 循环却没有?

def checkCircleCoord(coord):
    global circleCoordCenter #global list
    global checkCircleCoords

    '''why do I work?'''
    flag = False
    while not flag:
        flag = True
        for coord2 in circleCoordCenter:
            if distance(midpoint(coord),coord2) < BALL_DIAMETER():
                coord = randomCircleCoord()
                flag = False
                break

    '''why don't I work?'''
##    for coord2 in circleCoordCenter:
##        if distance(midpoint(coord),coord2) < BALL_DIAMETER():
##            coord = randomCircleCoord()
##            checkCircleCoord(coord)
    ''''''
    return coord

这是我的整个程序:

'''
Daniel Chen
'''
from tkinter import *
from random import choice
from time import clock
import math

## constant variables
def NUM_CIRCLES():
    return 40
def FIELD_X_SIZE():
    return 800
def FIELD_Y_SIZE():
    return 800
def BALL_DIAMETER():
    return 75

# math functions
def square(x):
    return x*x

## use as global variables
upperLeftX, upperLeftY, upperLeftX, upperLeftY = 0, 0, 0, 0
circleCoordCenter = []

def demographicsGUI():
    root = Tk()
    #root['bg'] = 'light yellow'

    form = Frame(root)
    #form['bg'] = 'light green'

    fname = Label(form)
    fname['text'] = 'First Name: '
    fname.pack()

    lname = Label(form)
    lname['text'] = 'Last Name: '
    lname.pack()

    dob = Label(form)
    dob['text'] = 'Date of Birth: '
    dob.pack

    action = Frame(root)
    #action['bg'] = 'pink'

    saveAndStart = Button(action, command=startGame,
                          text = 'Review Information and Start')
    saveAndStart.pack()

    form.pack(expand=YES, fill=BOTH)
    action.pack()
'''
generates a random coordinate to be used as the upper left of circle boundary
the upper left corner will be (0,0)
subtract BALL_DIAMETER from the X and Y field size to prevent the circle being drawn out of bounds
returns only as coordinates, not as array: (x,y)
'''
def randomCircleCoord():
        global upperLeftX
        global upperLeftY
        upperLeftX = choice(list(range(FIELD_X_SIZE() - BALL_DIAMETER() )))
        upperLeftY = choice(list(range(FIELD_Y_SIZE() - BALL_DIAMETER() )))
        return (upperLeftX,upperLeftY)

'''
returns the *center* of the rectangular oval boundary,
it takes a coordinate, creates another coordinate that is (x+BALL_DIAMETER, y+BALL_DIAMETER)
and finds its midpoint using:
(x2+x1)/2, (y2+y1)/2
'''
def midpoint(coord):
    coord = [coord]
    coordDiameter = [( coord[0][0]+BALL_DIAMETER() , coord[0][1]+BALL_DIAMETER() )]
    return (((coordDiameter[0][0])+coord[0][0])/2, ((coordDiameter[0][1]+coord[0][1])/2))

'''
returns the distance between 2 coordinates using:
sqrt( (x2-x1)^2 + (y2-y1)^2 )
'''
def distance(coord1, coord2):
    d = math.sqrt(square(coord2[0]-coord1[0]) + square(coord2[1]-coord1[1]))
    return abs(d)

'''
compares random coord to list of accepted coordinates, circleCoordCenter
randomCircleCoord is passed into checkCircleCoord in startGame()
'''
def checkCircleCoord(coord):
    global circleCoordCenter #global list
    global checkCircleCoords

    '''why do i work?'''
    flag = False
    while not flag:
        flag = True
        for coord2 in circleCoordCenter:
            if distance(midpoint(coord),coord2) < BALL_DIAMETER():
                coord = randomCircleCoord()
                flag = False
                break

    '''why don't i work?'''
##    for coord2 in circleCoordCenter:
##        if distance(midpoint(coord),coord2) < BALL_DIAMETER():
##            coord = randomCircleCoord()
##            checkCircleCoord(coord)
    ''''''
    return coord

def startGame():
    root = Tk()
    field = Canvas(root, width=FIELD_X_SIZE(), height=FIELD_Y_SIZE(), bg='white')
    field.pack()

    global checkCircleCoords
    for circleNumber in range(NUM_CIRCLES()):
        print('------------------------')
        print('circlenumber', circleNumber+1)
        if circleNumber == 0:
            coord = randomCircleCoord()
            upperLeftX, upperLeftY = coord[0],coord[1]
            print('first x y coordinate:', upperLeftX, upperLeftY)
            circleCoordCenter.append(midpoint(coord))
            print('first x y coordinate center: ', circleCoordCenter) #test print first coord
            field.create_oval(upperLeftX, upperLeftY, upperLeftX+BALL_DIAMETER(), upperLeftY + BALL_DIAMETER(), fill='white')
            field.create_text(upperLeftX, upperLeftY, text = "Start", fill = "purple")
        else:
            '''
            gets random point, x
            goes into checkCircleCoord: x, which then will be checked by adding BALL_DIAMETER to both x and y coordinates, and finds the midpoint.
            This midpoint is then compated to the list of midpoints in circleCoordCenter
            if distance between midpoints is greater than BALL_DIAMETER, checkCircleCoord will return the coordinates
            '''
            upperLeftX, upperLeftY = checkCircleCoord(randomCircleCoord())
            print(circleNumber+1, ' x y coordinates: ', upperLeftX, upperLeftY)
            circleCoordCenter.append(midpoint((upperLeftX, upperLeftY)))
            field.create_oval(upperLeftX, upperLeftY, upperLeftX+BALL_DIAMETER(), upperLeftY + BALL_DIAMETER(), fill='white')

            print(circleNumber+1, ' x y center: ', midpoint((upperLeftX, upperLeftY)))

            '''
            labeling circles starting with 'start' finishing with 'finish'
            '''
            if circleNumber != NUM_CIRCLES()-1:
                field.create_text(upperLeftX, upperLeftY, text = str(circleNumber), fill = "purple")
            else:
                field.create_text(upperLeftX, upperLeftY, text = "Finish", fill = "purple")
    print("Circle Center list: ", circleCoordCenter)
##demographicsGUI()
startGame()
mainloop()

最佳答案

提炼 DSM 的答案:

'''why am I not like this?'''
for coord2 in circleCoordCenter:
    if distance(midpoint(coord),coord2) < BALL_DIAMETER():
        coord = randomCircleCoord()
        return checkCircleCoord(coord)
        ^^^^^^

关于Python:绘制非重叠圆圈 - 递归失败, 'while' 有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9449511/

相关文章:

python - 如何展开基于键值 "pairs"的 python 列表字典?

python - 写入 CSV - 字符串在 Excel 中被识别为日期

python - Zope AdvancedQuery ICatalog工具

python - 如果先运行并行代码会挂起,但如果在运行非并行代码之后运行则可以正常工作

python - Python Tkinter 窗口上的启动和停止按钮

python - 在单独的线程中运行 Tkinter 表单

python - 导入 .gif 的最简单代码

python - 根据值向网格图添加边框

python - 使用 Python 的 libxml2 从 XML 节点读取文本

python - 在 tkinter 上运行的多个应用程序/文件/windows 实例