解决冰迷宫


19

冰迷宫一直是我最喜欢的主食之一的神奇宝贝,因为他们的神奇宝贝黄金和白银登场比赛。您的任务是编写一个解决这些类型问题的程序。

顾名思义,冰迷宫主要由冰组成。一旦玩家在冰上向某个方向移动,他们将继续向该方向移动,直到与某个障碍物碰撞为止。还有可以自由移动的土壤,将阻止任何玩家在其上移动。最后的障碍是石头。石头不能与玩家占据相同的空间,如果玩家尝试进入其中,他们将停止移动,然后才能移动。

您将收到一个二维的值容器,例如列表列表或用换行符分隔的字符串,其中包含3种地板类型(冰,土壤和石头)中的每种的3个不同值。您还将收到两对(或其他等效的两个值容器),它们指示迷宫中的起点和终点坐标。这些可以是零或一个索引。

您必须输出一个动作列表(在N,E,S,W上有两个双射的4个不同值),这将导致玩家在执行时到达终点。

输入始终在迷宫周围有一个封闭的石头周界,因此您不必担心玩家退出迷宫

这是因此最少的字节获胜

测试用例

这里.代表冰,~代表土壤,O代表石头。坐标为1索引。解决方案中的每个字母代表以该字母开头的方向(例如N=北)


输入项

OOOOO
OO.OO
O...O
OOOOO

Start : 3,3
End   : 3,2

输出量

N

输入项

OOOOOOOOOOOOOOOOO
O........O.....OO
O...O..........OO
O.........O....OO
O.O............OO
OO.......O.....OO
O.............OOO
O......O.......~O
O..O...........~O
O.............OOO
O.......O......OO
O.....O...O....OO
O..............OO
OOOOOOOOOOOOOO~~O
OOOOOOOOOOOOOOOOO

Start : 15,12
End   : 16,8

输出量

N,W,N,E,N,E,S,W,N,W,S,E,S,E,N,E,N

输入项

OOOOOOOOOOOOOOOO
O~~~~~OOOOO~~~~O
O~~O~OOOOOOO~~OO
O...O..........O
O........O.....O
O..............O
OO.............O
O.............OO
O....~....O....O
O..............O
O..............O
OOOOOOOOOOOOOOOO

Start : 2,2
End   : 14,3

输出量

E,S,S,W,N,E,N

输入项

OOOOOOOOOOOOOOOOOOO
O~~~~~~~OOOOOOOOOOO
O~~~~...OOOOOOOOOOO
OO~O~..OOOOOOOOOOOO
O..OO.............O
O..............O..O
O....O............O
O.O............~..O
O........OOOO.....O
O.......OOOOO.....O
O.......O~~~O.....O
O.......~~~~~.....O
O.......~~~~~.....O
O..........O......O
O..O..~...........O
O...............O.O
O.....O...........O
O.................O
OOOOOOOOOOOOOOOOOOO

Start : 2,2
End   : 11,11

输出量

E,E,E,E,E,S,S,E,N,W,S,E,N,N,N

输入中是否始终会至少有一个有效的解决方案?
Pavel

@Pavel您可以这样假设。
小麦巫师

是测试用例(行,列)还是(列,行)?1或0索引?板的边缘是否算作墙?
MildlyMilquetoast


2
@busukxuan您可能会被永久困在迷宫中(请参见测试案例1)
小麦巫师

Answers:


4

Mathematica,247个字节

(p=x#[[##&@@x]];m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c];g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}};e=Flatten[Table[#->c,{c,a@#}]&/@g,1];Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]])&

带换行符:

(
p=x#[[##&@@x]];
m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c];
g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];
a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}};
e=Flatten[Table[#->c,{c,a@#}]&/@g,1];
Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]]
)&

我的直接想法是将冰和土壤的位置表示为图形中具有对应于合法移动的有向边的节点,然后使用FindPath。有人可能会认为,确定法律举动将是一件容易的事,而找到解决方案将是一件困难的事。对我而言,情况恰恰相反。公开有关如何计算边缘的建议。

第一个参数#是2D数组,其中0表示冰,1表示土壤和2石头。

第二个自变量#2和第三个自变量#3分别是形式的起点和终点{row,column}

U+F4A1代表的3字节私人使用字符\[Function]

说明

p=x#[[##&@@x]];

定义一个函数p,该函数接受x表单的列表{row,column}和输出#[[row,column]]; 即该坐标处的冰/土壤/石头值。

m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c]

定义一个函数m,该函数采用起始位置c和方向矢量,v然后递归确定最终结果。如果c+v是冰,那么我们将从该点继续滑动,因此它返回m[c+v,v]。如果c+v是土壤,那么我们将c+v停下来。否则(如果c+v是石头或越界),您就不会移动。请注意,这仅在冰或土壤位置被调用。

g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];

定义g冰和土壤位置的列表(p值小于2)。

a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}}; 

定义了一个函数a,其需要一个起始位置c,并返回在移动的结果{1,0}{-1,0}{0,1},和{0,-1}方向。可能会有一些冗余。同样,这假定c对应于冰或土壤。

e=Flatten[Table[#->c,{c,a@#}]&/@g,1];

定义e代表合法移动的有向边的列表。对于每一个位置#g,计算边缘的表#->c为每个ca@#。然后,由于我们最终得到每个位置的子列表#,因此我将第一层展平。可能会有一些循环和多个边缘。

Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]]

Graph[e]是图形,其中节点是合法位置(冰或土壤),边缘表示合法移动(可能撞到石头而不移动)。然后FindPath,我们使用来找到从#2到的#3表示为节点列表的路径。由于FindPath可以使用其他参数来查找多个路径,因此结果实际上是包含单个路径的列表,因此我使用的第一个元素[[1]]。然后,我取连续Differences坐标和Normalize它们。因此,上是{-1,0}下是{1,0},右是{0,1}{0,-1}

测试用例

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明


4

的JavaScript(ES6)180 183

(m,[x,y],[t,u],o=~m.search`
`,s=[[x-y*o,[]]],k=[])=>eval("for(i=0;[p,l]=s[i++],k[p]=t-u*o-p;)[-1,o,1,-o].map(d=>k[q=(M=p=>+m[p+=d]?m[p]<8?M(p):p:p-d)(p)]||s.push([q,[...l,d]]));l")

像我一样使用BFS解决了相关挑战

输入
迷宫贴图是多线字符串,对于土壤,使用O0表示石头,8对于冰,则使用小于8的任何非零数字(7看起来不错)。
起始和结束位置从零开始。

输出
偏移量列表,其中-1是W,1是E,负数小于-1是N,正数大于1是S

少打高尔夫球

(m,[x,y],[t,u])=>{
  o=~m.search`\n`
  s=[[x-y*o,[]]]
  k=[]
  for(i=0; [p,l]=s[i++], k[p]=1, t-u*o != p;)
  {
    [-1,o,1,-o].map(d=>(
      M=p=>+m[p+=d] ? m[p]<8 ? M(p) : p : p-d,
      q=M(p),
      k[q]||s.push([q,[...l,d]])
    ))
  }
  return l
}

测试

Solve=
(m,[x,y],[t,u],o=~m.search`
`,s=[[x-y*o,[]]],k=[])=>eval("for(i=0;[p,l]=s[i++],k[p]=t-u*o-p;)[-1,o,1,-o].map(d=>k[q=(M=p=>+m[p+=d]?m[p]<8?M(p):p:p-d)(p)]||s.push([q,[...l,d]]));l")

function Go(maze) {
  var map = maze.textContent;
  var [sx,sy, dx,dy] = map.match(/\d+/g)
  --sx, --sy // zero based
  --dx, --dy // zero based
  map = map.split('\n').slice(1).join('\n') // remove first line
  var result = Solve(map.replace(/\./g, 7).replace(/~/g, 8), [sx,sy], [dx,dy])
  S.textContent = result
  Animate(maze, map, result, sx, sy)
}

function Display(maze, map, pos) {
  var row0 = maze.textContent.split('\n')[0]
  map = [...map]
  map[pos] = '☻'
  maze.textContent = row0+'\n'+map.join('')
}

function Animate(maze, map, moves, x, y) {
  console.log('A',moves)
  var offset = map.search('\n')+1
  var curPos = x + offset * y
  var curMove = 0
  var step = _ => {
    Display(maze, map, curPos)
    if (curMove < moves.length) 
    {
      curPos += moves[curMove]
      if (map[curPos] == 'O')
      {
        curPos -= moves[curMove]
        ++curMove
      }  
      else 
      {
        if (map[curPos] == '~') {
          ++curMove
        }
      }
      setTimeout(step, 100)
    }
    else
      setTimeout(_=>Display(maze,map,-1),500)
  }
  step()
}
td { 
  border: 1px solid #888;
}
Select maze<pre id=S></pre>
<table cellspacing=5><tr>
<td valign=top><input type=radio name=R onclick='Go(M1)'><br>
<pre id=M1>3,3 to 3,2  
OOOOO
OO.OO
O...O
OOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M2)'><br>
<pre id=M2>15,12 to 16,8
OOOOOOOOOOOOOOOOO
O........O.....OO
O...O..........OO
O.........O....OO
O.O............OO
OO.......O.....OO
O.............OOO
O......O.......~O
O..O...........~O
O.............OOO
O.......O......OO
O.....O...O....OO
O..............OO
OOOOOOOOOOOOOO~~O
OOOOOOOOOOOOOOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M3)'><br>
<pre id=M3>2,2 to 14,3
OOOOOOOOOOOOOOOO
O~~~~~OOOOO~~~~O
O~~O~OOOOOOO~~OO
O...O..........O
O........O.....O
O..............O
OO.............O
O.............OO
O....~....O....O
O..............O
O..............O
OOOOOOOOOOOOOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M4)'><br>
<pre id=M4>2,2 to 11,11
OOOOOOOOOOOOOOOOOOO
O~~~~~~~OOOOOOOOOOO
O~~~~...OOOOOOOOOOO
OO~O~..OOOOOOOOOOOO
O..OO.............O
O..............O..O
O....O............O
O.O............~..O
O........OOOO.....O
O.......OOOOO.....O
O.......O~~~O.....O
O.......~~~~~.....O
O.......~~~~~.....O
O..........O......O
O..O..~...........O
O...............O.O
O.....O...........O
O.................O
OOOOOOOOOOOOOOOOOOO</pre></td>
</tr></table>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.