Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kruskal'的Python实现问题;s迷宫算法_Python_Turtle Graphics_Maze - Fatal编程技术网

Kruskal'的Python实现问题;s迷宫算法

Kruskal'的Python实现问题;s迷宫算法,python,turtle-graphics,maze,Python,Turtle Graphics,Maze,我决定制作一个可变大小的二叉树迷宫生成器。我正在尝试使用Kruskal的迷宫算法,我需要创建一个程序,看看玩家是否有办法从x单元到y单元。我在解决迷宫问题上遇到了困难。我决定在二叉树生成器中实现一个迷宫解算器,我有一些基础知识,但它有一些问题我无法解决 开始于第一个细胞的中间,然后随机地选择一个方向,并试图前进到墙壁可能或不可能的地方,如果它不是一个可能的移动,它又在另一个随机方向上再次尝试。因为我只是简单地在墙上画了一些空间,但是用白色画了出来,所以我必须创建一个列表,列出每一个可以通过的墙

我决定制作一个可变大小的二叉树迷宫生成器。我正在尝试使用Kruskal的迷宫算法,我需要创建一个程序,看看玩家是否有办法从x单元到y单元。我在解决迷宫问题上遇到了困难。我决定在二叉树生成器中实现一个迷宫解算器,我有一些基础知识,但它有一些问题我无法解决

开始于第一个细胞的中间,然后随机地选择一个方向,并试图前进到墙壁可能或不可能的地方,如果它不是一个可能的移动,它又在另一个随机方向上再次尝试。因为我只是简单地在墙上画了一些空间,但是用白色画了出来,所以我必须创建一个列表,列出每一个可以通过的墙

我目前的问题是,由于某种原因,它不能垂直运行两次,但(通常)水平运行两次没有问题。有什么想法吗

from turtle import *
import random

def online(y,z):
  first = z[0]
  second = z[1]
  firstx = first[0]
  firsty = first[1]
  secondx = second[0]
  secondy = second[1]
  if firstx <= y[0] <= secondx and firsty >= y[1] >= secondy:
    return(True)
  elif firstx <= y[0] <= secondx and firsty <= y[1] <= secondy:
    return(True)
  elif firstx >= y[0] >= secondx and firsty >= y[1] >= secondy:
    return(True)
  elif firstx <= y[0] <= secondx and firsty >= y[1] >= secondy:
    return(True)

speed(0)
gridsize = 4
cellsize = 50
hideturtle()

cango = []

for i in range(4):
  a = pos()
  forward(gridsize*cellsize)
  b = pos()
  x = (a,b)
  left(90)
goto(0,0)
for i in range(gridsize):
  forward(cellsize)
  left(90)
  a = pos()
  forward(gridsize*cellsize)
  b = pos()
  x = (a,b)
  forward(-gridsize*cellsize)
  seth(0)
goto(0,0)
seth(90)
for i in range(gridsize):
  forward(cellsize)
  right(90)
  a = pos()
  forward(gridsize*cellsize)
  b = pos()
  x = (a,b)
  forward(-gridsize*cellsize)
  seth(90)
  
color("white")
pensize(2)
seth(270)
a = pos()
forward(cellsize)
b = pos()
x = (a,b)
forward(-cellsize)
seth(0)


choices = (1,2)
for i in range(gridsize):
  choices = (1,2) #Choice 1 cuts the right wall and choice 2 cuts the bottom wall
  for i in range(gridsize):
    a = int(pos()[0])
    b = int(pos()[1])
    #if the x value is all the way on the right, force the choice to cut the bottom
    if a == (gridsize-1)*cellsize or a == (gridsize-1)*cellsize-1:
      x = 2
    #if the y value is all the way on the bottom, force the choice to cut the right
    elif b == cellsize or b == cellsize-1:
      x = 1
    else:
    #if not at x or y max choose randomly between cutting right and cutting down
      x = random.choice(choices)
    #cut right
    if x == 1:
      penup()
      seth(0)
      forward(cellsize)
      right(90)
      pendown()
      a = pos()
      forward(cellsize)
      b = pos()
      x = a,b
      cango.append(x)
      forward(-cellsize)
      seth(0)
    #cut bottom
    elif x == 2:
      penup()
      seth(270)
      forward(cellsize)
      seth(0)
      pendown()
      a = pos()
      forward(cellsize)
      b = pos()
      x = a,b
      cango.append(x)
      penup()
      seth(90)
      forward(cellsize)
      seth(0)
  penup()
  seth(180)
  forward(cellsize*gridsize)
  seth(270)
  forward(cellsize)
  seth(0)
speed(3)
showturtle()
color("red")
goto(25,175)
penup()
print(cango)
pensize(4)
for i in range(1000):
    if pos() == (175.0,0.0):
        pensize(10)
        pencolor("green")
        break
    direction = random.randint(1,4)
    penup()
    if direction == 1:
        seth(0)
    elif direction == 2:
        seth(90)
    elif direction == 3:
        seth(180)
    else:
        seth(270)
    penup()
    forward(25)
    nohit = True
    for i in cango:
      if online(pos(),i) == True:
          nohit = False
      x = i[0]
      y = i[1]
      #if x[0] == pos()[0] and x[1] == pos()[1] or y[0] == pos()[0] and y[1] == pos()[1]:
        #nohit = True
    if nohit == False:
      backward(25)
      pendown()
      forward(50)
    else:
      backward(25)
从海龟导入*
随机输入
def在线(y,z):
第一个=z[0]
秒=z[1]
firstx=第一个[0]
firsty=first[1]
secondx=秒[0]
secondy=second[1]
如果firstx=secondy:
返回(真)
elif firstx=第二个:
返回(真)
elif firstx=第二个:
返回(真)
速度(0)
网格大小=4
单元大小=50
希德图尔()
cango=[]
对于范围(4)中的i:
a=pos()
正向(网格大小*单元格大小)
b=pos()
x=(a,b)
左(90)
后藤(0,0)
对于范围内的i(网格大小):
前进(单元格大小)
左(90)
a=pos()
正向(网格大小*单元格大小)
b=pos()
x=(a,b)
正向(-gridsize*cellsize)
赛斯(0)
后藤(0,0)
赛斯(90岁)
对于范围内的i(网格大小):
前进(单元格大小)
右(90)
a=pos()
正向(网格大小*单元格大小)
b=pos()
x=(a,b)
正向(-gridsize*cellsize)
赛斯(90岁)
颜色(“白色”)
养老金(2)
赛斯(270)
a=pos()
前进(单元格大小)
b=pos()
x=(a,b)
正向(-cellsize)
赛斯(0)
选项=(1,2)
对于范围内的i(网格大小):
选项=(1,2)#选项1切右墙,选项2切底墙
对于范围内的i(网格大小):
a=int(位置()[0])
b=int(位置()[1])
#如果x值一直位于右侧,则强制选择切割底部
如果a==(gridsize-1)*cellsize或a==(gridsize-1)*cellsize-1:
x=2
#如果y值一直位于底部,则强制选择向右剪切
elif b==cellsize或b==cellsize-1:
x=1
其他:
#如果不在x或y最大值,则在右切割和向下切割之间随机选择
x=随机。选择(选择)
#右转
如果x==1:
彭普()
赛斯(0)
前进(单元格大小)
右(90)
彭敦()
a=pos()
前进(单元格大小)
b=pos()
x=a,b
cango.append(x)
正向(-cellsize)
赛斯(0)
#切底
elif x==2:
彭普()
赛斯(270)
前进(单元格大小)
赛斯(0)
彭敦()
a=pos()
前进(单元格大小)
b=pos()
x=a,b
cango.append(x)
彭普()
赛斯(90岁)
前进(单元格大小)
赛斯(0)
彭普()
赛斯(180)
正向(单元格大小*网格大小)
赛斯(270)
前进(单元格大小)
赛斯(0)
速度(3)
showturtle()
颜色(“红色”)
后藤(25175)
彭普()
打印(cango)
养老金(4)
对于范围(1000)内的i:
如果pos()==(175.0,0.0):
养老金(10)
铅笔色(“绿色”)
打破
方向=random.randint(1,4)
彭普()
如果方向==1:
赛斯(0)
elif方向==2:
赛斯(90岁)
elif方向==3:
赛斯(180)
其他:
赛斯(270)
彭普()
转发(25)
nohit=True
我在坎戈:
如果在线(pos(),i)=真:
nohit=False
x=i[0]
y=i[1]
#如果x[0]==pos()[0]和x[1]==pos()[1]或y[0]==pos()[0]和y[1]==pos()[1]:
#nohit=True
如果nohit==False:
向后(25)
彭敦()
前进(50)
其他:
向后(25)

解决了的 如果有人遇到类似的问题,我的问题是python turtle在定义点时不是100%准确,因此我的点有时是(24.999999991100)最后我强迫它们是整数,对于我的程序,我只使用5的倍数,所以我测试的每一个点是4还是9,如果是的话,我加1

python turtle在定义点时不是100%准确的,因为我的 积分有时是(24.9999999100)

你必须改变你的想法。海龟在浮点平面上游荡。所有浮点实现都有折衷之处。学会与他们打交道:

最后我强迫他们成为整数。。。对于我测试的每一个点,如果有任何东西是4或9,如果是,我加1

我建议使用
round()
,而不是将
int()
与上面和下面的测试结合起来。但更好的方法是使用减法,或
turtle.distance()
,并检查差异是否足够小,可以称之为相同

下面是我使用上述方法对代码进行的返工;修复问题以允许调整网格的大小;样式和优化更改。看看这些修改对您是否有意义:

from turtle import *
from random import randrange, choice

GRID_SIZE = 5
CELL_SIZE = 50
RIGHT, BOTTOM = 1, 2  # Choice 1 cuts the right wall and choice 2 cuts the bottom wall

def online(position, line):

    x, y = position

    (firstx, firsty), (secondx, secondy) = line

    if firstx <= x <= secondx and firsty >= y >= secondy:
        return True
    if firstx <= x <= secondx and firsty <= y <= secondy:
        return True
    if firstx >= x >= secondx and firsty >= y >= secondy:
        return True
    if firstx <= x <= secondx and firsty >= y >= secondy:
        return True

    return False

# Draw the grid

hideturtle()
speed('fastest')

for _ in range(GRID_SIZE):
    forward(CELL_SIZE)
    left(90)
    forward(GRID_SIZE * CELL_SIZE)
    backward(GRID_SIZE * CELL_SIZE)
    right(90)

home()
setheading(90)

for _ in range(GRID_SIZE):
    forward(CELL_SIZE)
    right(90)
    forward(GRID_SIZE * CELL_SIZE)
    backward(GRID_SIZE * CELL_SIZE)
    left(90)

# Undraw walls to create a maze

color('white')
setheading(270)

forward(CELL_SIZE)
backward(CELL_SIZE)
setheading(0)

cango = []

for _ in range(GRID_SIZE):

    for i in range(GRID_SIZE):
        a, b = position()

        # if the x value is all the way on the right, force the choice to cut the bottom
        if abs(((GRID_SIZE - 1) * CELL_SIZE) - a) < CELL_SIZE / 4:
            wall = BOTTOM
        # if the y value is all the way on the bottom, force the choice to cut the right
        elif abs(CELL_SIZE - b) < CELL_SIZE / 4:
            wall = RIGHT
        else:
            # if not at x nor y max, choose randomly between cutting right and cutting down
            wall = choice([RIGHT, BOTTOM])

        penup()

        if wall == RIGHT:  # cut right
            setheading(0)
            forward(CELL_SIZE)
            right(90)
            pendown()
            start = position()
            forward(CELL_SIZE)
            end = position()

        elif wall == BOTTOM:  # cut bottom
            setheading(270)
            forward(CELL_SIZE)
            setheading(0)
            pendown()
            start = position()
            forward(CELL_SIZE)
            end = position()
            right(90)

        cango.append((start, end))
        penup()
        backward(CELL_SIZE)
        setheading(0)

    penup()
    backward(CELL_SIZE * GRID_SIZE)
    setheading(270)
    forward(CELL_SIZE)
    setheading(0)

#  Solve the maze

speed('slow')
shape('turtle')
color('red')
pensize(4)
goto(CELL_SIZE / 2, GRID_SIZE * CELL_SIZE - CELL_SIZE / 2)
showturtle()

change_heading = False  # get the most you can out of a direction change

while pencolor() == 'red':

    if distance(GRID_SIZE * CELL_SIZE - CELL_SIZE / 2, -CELL_SIZE / 2) <= CELL_SIZE / 4:
        color('green')
        break

    penup()

    if change_heading:
        direction = randrange(4) * 90
        setheading(direction)
        change_heading = False

    forward(CELL_SIZE / 2)

    nohit = True

    for line in cango:
        if online((round(xcor()), round(ycor())), line):
            nohit = False
            break

    backward(CELL_SIZE / 2)

    if not nohit:
        pendown()
        forward(CELL_SIZE)
    else:
        change_heading = True

mainloop()
从海龟导入*
从随机输入范围,选择
网格大小=5
单元大小=50
右,底部=1,2#选项1剪切右墙,选项2剪切底墙
def在线(位置、线路):
x、 y=位置
(firstx,firsty),(secondx,secondy)=行
如果firstx=secondy:
返回真值
如果firstx=secondy:
返回真值
如果firstx=secondy:
返回真值
返回错误
#画网格
希德图尔()
速度(“最快”)
对于范围内的(网格大小):
正向(单元格大小)
左(90)
正向(网格大小*单元格大小)
向后(网格大小*单元大小)
右(90)
home()
设置标题(90)
对于范围内的(网格大小):
正向(单元格大小)
右(90)
正向(网格大小*单元格大小)
向后(网格大小*单元大小)
左(90)
#未加工的墙