BuildFun และ SolveFun
อย่างนี้ใช้เวลาสักพักและฉันก็ไม่แน่ใจว่านักแก้ปัญหาจะโกงหรือไม่ ในขณะที่มันสามารถเข้าถึงเขาวงกตได้ตลอดเวลามันจะมองไปที่เซลล์ที่อยู่ข้างในเท่านั้นผนังที่ล้อมรอบมันและหากไม่มีกำแพงกั้นระหว่างพวกมันเซลล์ที่อยู่ติดกับมัน หากสิ่งนี้ขัดกับกฎโปรดแจ้งให้เราทราบและฉันจะพยายามเปลี่ยน
อย่างไรก็ตามนี่คือรหัส:
#Architect function
def BuildFun(size,seed):
#Initialise grid and ensure inputs are valid
if size<15:size=15
if size>50:size=50
if seed<4:seed=4
if seed>size:seed=size
grid=[]
for x in range(size):
gridbuilder=[]
for y in range(size):gridbuilder.append([0,1,1])
grid.append(gridbuilder)
coords=[0,0]
grid[0][0][0]=1
#Generate maze
while 1:
#Choose a preffered direction based on location in grid and seed
pref=((((coords[0]+coords[1]+2)*int(size/2))%seed)+(seed%(abs(coords[0]-coords[1])+1)))%4
#Find legal moves
opt=[]
if coords[0]>0:opt+=[0] if grid[coords[0]-1][coords[1]][0]==0 else []
if coords[1]<size-1:opt+=[1] if grid[coords[0]][coords[1]+1][0]==0 else []
if coords[0]<size-1:opt+=[2] if grid[coords[0]+1][coords[1]][0]==0 else []
if coords[1]>0:opt+=[3] if grid[coords[0]][coords[1]-1][0]==0 else []
#There are legal moves
if len(opt)>0:
moved=False
while not moved:
#Try to move in preffered direction
if pref in opt:
if pref==0:
coords[0]-=1
grid[coords[0]][coords[1]][0]=1
grid[coords[0]][coords[1]][2]=0
elif pref==1:
grid[coords[0]][coords[1]][1]=0
coords[1]+=1
grid[coords[0]][coords[1]][0]=1
elif pref==2:
grid[coords[0]][coords[1]][2]=0
coords[0]+=1
grid[coords[0]][coords[1]][0]=1
else:
coords[1]-=1
grid[coords[0]][coords[1]][0]=1
grid[coords[0]][coords[1]][1]=0
moved=True
#Change preferred direction if unable to move
else:
pref+=1
if pref==4:pref=0
#There aren't legal moves
else:
moved=False
#Return to a previously visited location
if not moved:
try:
if grid[coords[0]-1][coords[1]][0]==1 and grid[coords[0]-1][coords[1]][2]==0:
grid[coords[0]][coords[1]][0]=2
coords[0]-=1
moved=True
except:pass
if not moved:
try:
if grid[coords[0]][coords[1]+1][0]==1 and grid[coords[0]][coords[1]][1]==0:
grid[coords[0]][coords[1]][0]=2
coords[1]+=1
moved=True
except:pass
if not moved:
try:
if grid[coords[0]+1][coords[1]][0]==1 and grid[coords[0]][coords[1]][2]==0:
grid[coords[0]][coords[1]][0]=2
coords[0]+=1
moved=True
except:pass
if not moved:
try:
if grid[coords[0]][coords[1]-1][0]==1 and grid[coords[0]][coords[1]-1][1]==0:
grid[coords[0]][coords[1]][0]=2
coords[1]-=1
moved=True
except:pass
#Check if finished
fin=True
for x in grid:
for y in x:
if y[0]==0:
fin=False
break
if not fin:break
if fin:break
for x in grid:
for y in x:
y[0]=0
#Find positions for start and finish such that the route between them is as long as possible
lsf=[[0,0],[0,0],0]
for y in range(size):
for x in range(size):
#Check all start positions
lengths=[]
coords=[[y,x,4,0]]
while len(coords)>0:
#Spread tracers out from start to the rest of the maze
for coord in coords:
opt=[]
if coord[0]>0:opt+=[0] if grid[coord[0]-1][coord[1]][2]==0 else []
opt+=[1] if grid[coord[0]][coord[1]][1]==0 else []
opt+=[2] if grid[coord[0]][coord[1]][2]==0 else []
if coord[1]>0:opt+=[3] if grid[coord[0]][coord[1]-1][1]==0 else []
try:opt.remove(coord[2])
except:pass
#Dead end, tracer dies and possible end point is recorded along with length
if len(opt)==0:
lengths.append([coord[0],coord[1],coord[3]])
coords.remove(coord)
else:
#Create more tracers at branch points
while len(opt)>1:
if opt[0]==0:coords.append([coord[0]-1,coord[1],2,coord[3]+1])
elif opt[0]==1:coords.append([coord[0],coord[1]+1,3,coord[3]+1])
elif opt[0]==2:coords.append([coord[0]+1,coord[1],0,coord[3]+1])
else:coords.append([coord[0],coord[1]-1,1,coord[3]+1])
del opt[0]
if opt[0]==0:
coord[0]-=1
coord[2]=2
coord[3]+=1
elif opt[0]==1:
coord[1]+=1
coord[2]=3
coord[3]+=1
elif opt[0]==2:
coord[0]+=1
coord[2]=0
coord[3]+=1
else:
coord[1]-=1
coord[2]=1
coord[3]+=1
#Find furthest distance and, if it's longer than the previous one, the start/end positions get updated
lengths=sorted(lengths,key=lambda x:x[2],reverse=True)
if lengths[0][2]>lsf[2]:lsf=[[y,x],[lengths[0][0],lengths[0][1]],lengths[0][2]]
#Find number of walls and output maze
w=draw(grid,size,lsf[0],lsf[1])
#Output maze information
print('Start = '+str(lsf[0]))
print('End = '+str(lsf[1]))
print('Distance = '+str(lsf[2]))
print('Walls = '+str(w))
print('Score = '+str(float(lsf[2])/float(w))[:5])
#Convert array grid to binary strings horizontal and vertical
horizontal=vertical=''
for y in range(size):
for x in range(size-1):vertical+=str(grid[y][x][1])
for y in range(size-1):
for x in range(size):horizontal+=str(grid[y][x][2])
#Save maze information to text file for use with SolveFun
save=open('Maze.txt','w')
save.write(str(size)+'\n'+str(lsf[0][0])+' '+str(lsf[0][1])+'\n'+str(lsf[1][0])+' '+str(lsf[1][1])+'\n'+horizontal+'\n'+vertical)
save.close()
#Solver function
def SolveFun():
try:
#Get maze information from text file
save=open('Maze.txt','r')
data=save.readlines()
save.close()
size=int(data[0])
s=data[1].rsplit(' ')
start=[int(s[0]),int(s[1])]
e=data[2].rsplit(' ')
end=[int(e[0]),int(e[1])]
horizontal=data[3].rstrip('\n')
vertical=data[4]
#Build maze from information
grid=[]
for y in range(size):
grid.append([])
for x in range(size):
grid[y].append([0,1,1])
for y in range(size):
for x in range(size-1):
grid[y][x][1]=int(vertical[y*(size-1)+x])
for y in range(size-1):
for x in range(size):
grid[y][x][2]=int(horizontal[y*size+x])
path=''
cpath=''
bs=0
pos=start[:]
grid[pos[0]][pos[1]][0]=1
while pos!=end:
#Want to move in direction of finish
if end[0]<pos[0] and pos[0]-end[0]>=abs(pos[1]-end[1]):pref=0
elif end[1]>pos[1] and end[1]-pos[1]>=abs(pos[0]-end[0]):pref=1
elif end[0]>pos[0] and end[0]-pos[0]>=abs(pos[1]-end[1]):pref=2
else:pref=3
#Find legal moves
opt=[]
if pos[0]>0:
if grid[pos[0]-1][pos[1]][2]==0:opt+=[0]if grid[pos[0]-1][pos[1]][0]==0 else[]
if pos[1]>0:
if grid[pos[0]][pos[1]-1][1]==0:opt+=[3]if grid[pos[0]][pos[1]-1][0]==0 else[]
if grid[pos[0]][pos[1]][2]==0:opt+=[2]if grid[pos[0]+1][pos[1]][0]==0 else[]
if grid[pos[0]][pos[1]][1]==0:opt+=[1]if grid[pos[0]][pos[1]+1][0]==0 else[]
if len(opt)>0:
moved=False
while not moved:
#Try to move in preferred direction
if pref in opt:
if pref==0:
pos[0]-=1
path+='0'
cpath+='0'
elif pref==1:
pos[1]+=1
path+='1'
cpath+='1'
elif pref==2:
pos[0]+=1
path+='2'
cpath+='2'
else:
pos[1]-=1
path+='3'
cpath+='3'
grid[pos[0]][pos[1]][0]=1
moved=True
#Change preferred direction by 1
else:
pref=(pref+1)%4
#No legal moves, backtrack
else:
bs+=1
grid[pos[0]][pos[1]][0]=2
if int(cpath[len(cpath)-1])==0:
pos[0]+=1
path+='2'
elif int(cpath[len(cpath)-1])==1:
pos[1]-=1
path+='3'
elif int(cpath[len(cpath)-1])==2:
pos[0]-=1
path+='0'
else:
pos[1]+=1
path+='1'
cpath=cpath[:len(cpath)-1]
#Output maze with solution as well as total steps and wasted steps
draw(grid,size,start,end)
print('\nPath taken:')
print(str(len(path))+' steps')
print(str(bs)+' backsteps')
print(str(bs*2)+' wasted steps')
except:print('Could not find maze')
def draw(grid,size,start,end):
#Build output in string d
d=' '
for x in range(size):d+=' '+str(x)[0]
d+='\n '
for x in range(size):d+=' ' if len(str(x))==1 else ' '+str(x)[1]
d+='\n '+'_'*(size*2-1)
w=0
for y in range(size):
d+='\n'+str(y)+' |' if len(str(y))==1 else '\n'+str(y)+' |'
for x in range(size):
if grid[y][x][2]:
if start==[y,x]:d+=UL.S+'S'+UL.E
elif end==[y,x]:d+=UL.S+'F'+UL.E
elif grid[y][x][0]==1:d+=UL.S+'*'+UL.E
else:d+='_'
w+=1
else:
if start==[y,x]:d+='S'
elif end==[y,x]:d+='F'
elif grid[y][x][0]==1:d+='*'
else:d+=' '
if grid[y][x][1]:
d+='|'
w+=1
else:d+=' '
#Output maze and return number of walls
print(d)
w-=size*2
return w
#Underlines text
class UL:
S = '\033[4m'
E = '\033[0m'
ฉันรู้ว่านี่เป็นเวลาที่น่าขันและไม่ได้อ่านง่ายโดยเฉพาะ แต่ฉันขี้เกียจนี่คือสิ่งที่มันเป็น
BuildFun
BuildFun สถาปนิกเป็นโปรแกรมสร้างเขาวงกตที่ค่อนข้างง่ายซึ่งจะสร้างเขาวงกตที่ 'สมบูรณ์แบบ' เสมอ (หนึ่งที่ไม่มีลูปและจุดสองจุดใด ๆ จะมีเส้นทางเดียวระหว่างพวกเขาเสมอ) มันอิงตรรกะของมันจากอินพุตเมล็ดซึ่งหมายความว่าเขาวงกตที่สร้างขึ้นนั้นเป็นแบบหลอกหลอกด้วยสิ่งที่ดูเหมือนว่าจะเป็นรูปแบบการทำซ้ำบ่อยครั้งและด้วยเมล็ดและขนาดเดียวกันเขาวงกตเดียวกันจะถูกสร้างขึ้น
เมื่อเขาวงกตถูกสร้างขึ้นโปรแกรมจะพยายามเพิ่มคะแนนเขาวงกตให้มากที่สุดโดยการค้นหาจุดเริ่มต้นและจุดสิ้นสุดที่ทำให้เส้นทางที่ยาวที่สุดระหว่างพวกเขา ในการทำเช่นนี้มันจะวิ่งผ่านจุดเริ่มต้นทุกจุดกระจายตัวติดตามเพื่อหาจุดสิ้นสุดที่ไกลที่สุดจากนั้นและเลือกชุดค่าผสมกับเส้นทางที่ยาวที่สุด
หลังจากนี้มันจะดึงเขาวงกตนับจำนวนกำแพงและแสดงข้อมูลของเขาวงกต นี่คือจุดเริ่มต้นจุดสิ้นสุดระยะห่างระหว่างพวกเขาจำนวนของกำแพงและคะแนน นอกจากนี้ยังจัดรูปแบบข้อมูลนี้เป็นรูปแบบที่อธิบายไว้ข้างต้นสำหรับขนาดเริ่มต้นและสิ้นสุดผนังแนวนอนและแนวผนังและบันทึกเป็นไฟล์ข้อความที่เรียกว่า Maze.txt เพื่อใช้ในภายหลัง
SolveFun
SolveFun Solver ใช้ไฟล์ข้อความ Maze.txt เป็นอินพุตและทำงานในแบบเดียวกับสถาปนิก สำหรับทุกการเคลื่อนไหวมันจะเลือกทิศทางที่มันต้องการจะขึ้นอยู่กับตำแหน่งที่สัมพันธ์กันไปจนถึงจุดสิ้นสุดจากนั้นมันจะดูที่ผนังโดยรอบ หากไม่มีกำแพงอยู่จะมีการตรวจสอบเพื่อดูว่ามีผนังอยู่ในเซลล์ติดกับผนังหรือไม่และจะไม่ถูกเพิ่มเข้าไปในตัวเลือกที่เป็นไปได้ จากนั้นจะเคลื่อนที่ในทิศทางที่ใกล้เคียงกับทิศทางที่ต้องการมากที่สุดหากมีตัวเลือก หากไม่มีตัวเลือกมันจะย้อนกลับจนกว่าจะมี สิ่งนี้จะดำเนินต่อไปจนกว่าจะถึงจุดสิ้นสุด
ในขณะที่มันเคลื่อนที่มันจะบันทึกเส้นทางที่มันกำลังทำอยู่ในเส้นทางของตัวแปรที่ใช้ในตอนท้ายเพื่อส่งออกจำนวนขั้นตอนทั้งหมด นอกจากนี้ยังบันทึกจำนวนครั้งที่ต้องใช้การย้อนรอยเพื่อคำนวณขั้นตอนที่สิ้นเปลืองในตอนท้าย เมื่อถึงจุดสิ้นสุดมันจะเอาท์พุทเขาวงกตด้วยเส้นทางที่สั้นที่สุดตั้งแต่ต้นจนจบที่ทำเครื่องหมายด้วย*
s
วิธีการวิ่ง
เนื่องจากวิธีการแสดงผลเขาวงกต (ซึ่งรวมถึงการขีดเส้นใต้อักขระบางตัว) จึงต้องเรียกใช้จากบรรทัดคำสั่งในแบบฟอร์ม
python -c 'import filename;filename.BuildFun(Size, Seed)'
และ
python -c 'import filename;filename.SolveFun()'
โดยที่ Size เป็นจำนวนเต็มตั้งแต่ 15 ถึง 50 (รวม) และ Seed เป็นจำนวนเต็มระหว่าง 4 ถึงขนาด (รวม)