Codecombat计算机科学6.15冰块中的宝藏

温馨提示:
这一关绝对是一个坑!!!
如果认为自己有能力,去走那么一遭也无妨;
若是认为自己是混到这一关的,还是掉头吧,小心虐哭你的脑细胞。

在这里插入图片描述
这一关看似和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?
亲爱的,这个平台可以是激发你学习兴趣的一个好辅助!
但知识性东西还是系统性的从课本入手吧!
我先睡了,有什么问题欢迎留言!
大神要是看到这篇文章,如解析有不当之处有所冒犯,还请见谅!
拜过!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值