温馨提示:
这一关绝对是一个坑!!!
如果认为自己有能力,去走那么一遭也无妨;
若是认为自己是混到这一关的,还是掉头吧,小心虐哭你的脑细胞。
这一关看似和14关差不多,只是多了个宝藏。
但是,在这里我觉得应该称之为baocang,
实在是cang的太深了!
我的算法拿不出手,钻了漏洞。
但别担心,我还有更好地分享给你!
这份代码听朋友说是百度的,恕我搜索技巧拙劣,找不到它的出处
不过,我们先把这关过了,再研究搜索技巧的事情。
大神代码先呈上:
# 找到迷宫中的宝藏。
# 拿到宝藏后,请走出出口。
# 出口有红十字的标记。关卡会中你踩到标记的时候结束。
# 有一些门被堵住了,有一些门会在你靠近它的时候打开。
exitPosition = {"x": 150, "y": 120}
distanceBetweenRooms = 16
zeroShift = {"x": 10, "y": 10}
inSearch = True
width = 19
height = 15
def coorConvert(i, dist):
return i * distanceBetweenRooms / 2 + zeroShift.x
wall = "X"
unknown = "?"
empty = "."
# Clear map of the maze.
maze = []
# left border
for i in range(height):
maze.append([wall])
# top border
for j in range(width - 1):
maze[0].append(wall)
for i in range(height - 1):
if i % 2:
for j in range(width - 1):
maze[i].append(unknown)
else:
for j in range(width - 1):
if j % 2:
maze[i].append(wall)
else:
maze[i].append(unknown)
# bottom border
for j in range(width - 1):
maze[height-1].append(wall)
# right border
for i in range(height):
maze.append([wall])
# Start position
hero.row = 13
hero.col = 17
# Exit
exitRow = 13
exitCol = 17
# function for find positions in various directions
def east():
return {'x': coorConvert(hero.col - 2),
'y': coorConvert(hero.row),
'row': hero.row, 'col': hero.col - 2}
def west():
return {'x': coorConvert(hero.col + 2),
'y': coorConvert(hero.row),
'row': hero.row, 'col': hero.col + 2}
def south():
return {'x': coorConvert(hero.col),
'y': coorConvert(hero.row - 2),
'row': hero.row - 2, 'col': hero.col}
def north():
return {'x': coorConvert(hero.col),
'y': coorConvert(hero.row + 2),
'row': hero.row + 2, 'col': hero.col}
def exit():
return exitPosition
# Move hero in the direction and update property positions
def moveDir(direction):
newPosFunc = {
"N": north,
"S": south,
"E": east,
"W": west,
"!": exit
}[direction]
newPos = newPosFunc()
hero.moveXY(newPos.x, newPos.y)
if direction == "!":
inSearch = False
hero.row = newPos.row
hero.col = newPos.col
# check near door and update map
def checkPaths(cMap):
cMap[hero.row][hero.col] = "."
dirs = [[1, 0, north], [-1, 0, south], [0, 1, west], [0, -1, east]]
for d in range(len(dirs)):
dx = dirs[d][0]
dy = dirs[d][1]
dPosFunc = dirs[d][2]
if (cMap[hero.row+dx][hero.col+dy] == "?"
and hero.isPathClear(hero.pos, dPosFunc())):
cMap[hero.row+dx][hero.col+dy] = "."
return cMap
def findPath(m, needExit):
stack = [[hero.row, hero.col, ""]]
visited = []
index = 0
while len(stack):
# Hack for the broken pop(0)
current = stack[index]
index += 1
row = current[0]
col = current[1]
path = current[2]
# hero.say(row + " " + col + " " + path)
data = m[row-1][col] + " "
# hero.say(row + " " + col + " " + data)
strPos = row + '-' + col
if visited.indexOf(strPos) != -1:
continue
visited.append(strPos)
if not needExit and m[row][col] == "?":
return path
if needExit and row == exitRow and col == exitCol:
return path + "!"
if m[row-1][col] == ".":
stack.append([row-2, col, path + "S"])
if m[row+1][col] == ".":
stack.append([row+2, col, path + "N"])
if m[row][col+1] == ".":
stack.append([row, col+2, path + "W"])
if m[row][col-1] == ".":
stack.append([row, col-2, path + "E"])
path = ""
treasureFound = False
while inSearch:
maze = checkPaths(maze)
if hero.gold > 0:
treasureFound = True
inSearch = False
path = findPath(maze, treasureFound)
if not path:
hero.say("Arrrr!")
else:
for p in range(len(path)):
moveDir(path[p])
能自己看懂的朋友们功力实在深厚,在此处可以break!
ᕦ༼ ~ •́ ₒ •̀ ~ ༽ᕤ
我怕我的解释的把大佬您给绕进去!
第一步:
矩阵划起来
看到图片左下角的甜甜圈🍩了吗?
那个就是(0,0)点
为什么要以那个点为原点?
都说了,系统给的提示和已知条件很重要的!
再睁大脑子看看系统给的那三条通关秘籍;⊙▂⊙
有没有看到系统给出的代码的第8行“zeroShift = {“x”: 10, “y”: 10}”?
如果没有看懂zeroShift{}
那么你的矩阵可能是这样画的?
刚开始我的矩阵就是这样划分的!t( -_- t )
这也许就是我与大神的区别吧!
好,我们看看大神划分完矩阵后,如何存储这“迷宫”的信息的
如下图:怕了吗?ɖීීϸ
整个页面最令人不适的可能就是这张充满“x”"?"的图了
啊,我要吐了🤮
到这里还有体力满格,没被吓倒的,优秀,给自己鼓个掌!↖(ω)↗
那我们继续来看看代码,看看大神的脑子是怎么转的?
这是大神初始化部分的源代码:
你看懂了吗?我有点迷糊?(´~`)
不过被我修改了一番后,我觉得思路能理清了。༼ つ ◕_◕ ༽つ
那我就讲讲这个我修改后的:
第二步:初始化Maze
# Clear map of the maze.
maze = []
# left border
for i in range(height):
maze.append([wall])
for i in range(height):
if i % 2:
for j in range(width - 1):
maze[i].append(unknown)
else:
for j in range(width - 1):
if j % 2:
maze[i].append(wall)
else:
maze[i].append(unknown)
maze[ ]这个二维数组,是要存储图中各个点的信息的
1、maze[ ]中append了15个元素,每一个元素都是一个列表[ ]
(这步是对数组中row的扩展)
for i in range(height):
maze.append([wall])
2、对maze[i]进行append操作
(这一步就是对数组横向(col)的扩展了)
for i in range(height):
if i % 2:
for j in range(width - 1):
maze[i].append(unknown)
else:
for j in range(width - 1):
if j % 2:
maze[i].append(wall)
else:
maze[i].append(unknown)
于是就得到了上面那副恐怖的初始化图!
第三步:更新Maze
hero的初始row=13,col=17
# check near door and update map
def checkPaths(cMap):
cMap[hero.row][hero.col] = "."
dirs = [[1, 0, north], [-1, 0, south], [0, 1, west], [0, -1, east]]
for d in range(len(dirs)):
dx = dirs[d][0]
dy = dirs[d][1]
dPosFunc = dirs[d][2]
#dPosFunc()相当于north()/east()/west()/south()
if (cMap[hero.row+dx][hero.col+dy] == "?"
and hero.isPathClear(hero.pos, dPosFunc())):
cMap[hero.row+dx][hero.col+dy] = "."
return cMap
第四步:走自己的路
注释给大家加里面了,就不具体讲了
def findPath(m, needExit)
#核心利器“stack”
stack = [[hero.row, hero.col, ""]]
visited = []
index = 0
while len(stack):
current = stack[index]
index += 1
row = current[0]
col = current[1]
#path:N/S/W/E/!
path = current[2]
# hero.say(row + " " + col + " " + path)
#data: "."/'?'/'!'/"x"
data = m[row-1][col] + " "
# hero.say(row + " " + col + " " + data)
strPos = row + '-' + col
#indexOf()返回第一次出现的指定子字符串在此字符串中的索引。
#如果没有找到返回-1
if visited.indexOf(strPos) != -1:
continue
#把访问过的点放到visited[]中
visited.append(strPos)
if not needExit and m[row][col] == "?":
return path
if needExit and row == exitRow and col == exitCol:
return path + "!"
if m[row-1][col] == ".":
stack.append([row-2, col, path + "S"])
if m[row+1][col] == ".":
stack.append([row+2, col, path + "N"])
if m[row][col+1] == ".":
stack.append([row, col+2, path + "W"])
if m[row][col-1] == ".":
stack.append([row, col-2, path + "E"])
第五步:行动吧!
for p in range(len(path)):
moveDir(path[p])
ᕦ༼ •́ ‸ •̀ ༽ᕤ ok,结束了!
什么?没有弄懂?
不好意思,落下一块内容了!
补上!
第六步:moveDir()
最牛的操作moveDir()忘了给大家介绍了
newPosFunc = {
"N": north,
"S": south,
"E": east,
"W": west,
"!": exit
}[direction]
newPos = newPosFunc()
之前我也提到过我是c++入门的,刚看到上面这写法,
newPosFunc = { "N": north, "S": south, "E": east, "W": west, "!": exit }[direction]
我以为newPosFunc是“结构体”/“类”,newPos是newPosFunc对象?
但这完全解释不通[direction];
可恶,(▰˘︹˘▰)手边没有python书
再看看代码,万一突然就可以自己说服自己了呢?๑乛◡乛๑
def moveDir(direction):
newPosFunc = {
"N": north,
"S": south,
"E": east,
"W": west,
"!": exit
}[direction]
newPos = newPosFunc()
hero.moveXY(newPos.x, newPos.y)
if direction == "!":
inSearch = False
hero.row = newPos.row
hero.col = newPos.col
盯着这块漫游了一下午,马上就21:00了!
我怕晚上睡不着,不能瞑目(`へ´)
于是乎,深夜打扰王老师了,
疙瘩终于是解开了!
王老师说:那是字典
我知道python中的的组合数据类型有:列表,元组,字典,集合。可像这样的字典用法,我还没了解过。
王老师接着解释道:这个字典的“键”是[direction],
而它对应的键值有“N”/“S”/“E”/“W”/“!”
soga!(⊙ᗜ⊙)
所以newPosFunc()即为取到的键值对应的函数north()/south()/east()/west()/exit()
def east():
return {'x': coorConvert(hero.col - 2),
'y': coorConvert(hero.row),
'row': hero.row, 'col': hero.col - 2}
def west():
return {'x': coorConvert(hero.col + 2),
'y': coorConvert(hero.row),
'row': hero.row, 'col': hero.col + 2}
def south():
return {'x': coorConvert(hero.col),
'y': coorConvert(hero.row - 2),
'row': hero.row - 2, 'col': hero.col}
def north():
return {'x': coorConvert(hero.col),
'y': coorConvert(hero.row + 2),
'row': hero.row + 2, 'col': hero.col}
def exit():
return exitPosition
这是大神代码中的N/S/W/E
我一般是用图像的“上下左右”的 ╰[ ⁰﹏⁰ ]╯
不过,即使是用N/S/W/E,W不应该在左侧,E在图像的右侧吗?
不纠结了,大神说哪是东就哪是东吧,不影响
说了这么多,有伙伴好像还有点迷糊
不用看了,准备10张A4纸,第一张纸上准备画“X?X?X?X”
其他纸上准备写执行过程,把程序自己走一编(一定要做好心理准备啊)
夜已深,睡吧!
有时间一定要买本python书好好学学
什么你只想靠codecombat学python?
亲爱的,这个平台可以是激发你学习兴趣的一个好辅助!
但知识性东西还是系统性的从课本入手吧!
我先睡了,有什么问题欢迎留言!
大神要是看到这篇文章,如解析有不当之处有所冒犯,还请见谅!
拜过!