Giải quyết một mê cung băng


19

Mê cung băng là một trong những trò chơi Pokémon yêu thích của tôi kể từ khi ra mắt trong Pokémon Gold và Silver. Nhiệm vụ của bạn sẽ là tạo ra một chương trình giải quyết các loại vấn đề này.

Mê cung băng chủ yếu bao gồm, như tên cho thấy, băng. Một khi người chơi di chuyển theo hướng trên băng, họ sẽ tiếp tục di chuyển theo hướng đó cho đến khi va chạm với một chướng ngại vật nào đó. Ngoài ra còn có đất có thể được di chuyển tự do và sẽ ngăn bất kỳ người chơi nào di chuyển qua nó. Trở ngại cuối cùng là đá. Đá không thể chiếm cùng một không gian với người chơi và nếu người chơi cố gắng di chuyển vào đó, họ sẽ ngừng di chuyển trước khi họ có thể.

Bạn sẽ nhận được một thùng chứa các giá trị hai chiều, chẳng hạn như danh sách danh sách hoặc chuỗi được phân tách bằng dòng mới, chứa 3 giá trị riêng biệt cho mỗi loại trong số 3 loại sàn (Ice, Soil và Stone). Bạn cũng sẽ nhận được hai cặp (hoặc hai thùng chứa giá trị tương đương khác) biểu thị tọa độ bắt đầu và mục tiêu trong mê cung. Đây có thể là 0 hoặc một chỉ mục.

Bạn phải xuất ra một danh sách các bước di chuyển (4 giá trị riêng biệt với một mệnh đề trên N, E, S, W) sẽ khiến người chơi đến cuối khi thực hiện.

Đầu vào sẽ luôn có một chu vi đá khép kín xung quanh mê cung, do đó bạn không phải lo lắng về việc người chơi thoát khỏi mê cung

Đây là nên ít byte nhất sẽ thắng

Các trường hợp thử nghiệm

Ở đây .sẽ đại diện cho băng, ~sẽ đại diện cho đất, và Osẽ đại diện cho một hòn đá. Tọa độ là 1 chỉ mục. Mỗi chữ cái trong giải pháp thể hiện hướng bắt đầu bằng chữ cái đó (vd N= North)


Đầu vào

OOOOO
OO.OO
O...O
OOOOO

Start : 3,3
End   : 3,2

Đầu ra

N

Đầu vào

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

Đầu ra

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

Đầu vào

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

Đầu ra

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

Đầu vào

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

Đầu ra

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

Đầu vào sẽ luôn có ít nhất một giải pháp hợp lệ?
Pavel

@Pavel Bạn có thể giả sử như vậy.
Phù thủy lúa mì

Là các trường hợp thử nghiệm (hàng, cột) hoặc (cột, hàng)? 1 hay 0 được lập chỉ mục? Các cạnh bảng được tính là bức tường?
MildlyMilquetoast


2
@busukxuan Bạn có thể bị mắc kẹt vĩnh viễn trong mê cung (xem thử nghiệm 1)
Thuật sĩ lúa mì

Câu trả lời:


4

Toán học, 247 byte

(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]])&

Với ngắt dòng:

(
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]]
)&

Ý tưởng trước mắt của tôi là đại diện cho các vị trí băng và đất dưới dạng các nút trong biểu đồ với các cạnh được định hướng tương ứng với các bước di chuyển hợp pháp, sau đó sử dụng FindPath. Người ta có thể nghĩ rằng việc xác định các động thái hợp pháp sẽ là phần dễ dàng và tìm ra giải pháp sẽ là phần khó. Đối với tôi, nó là ngược lại. Mở để đề xuất về cách tính các cạnh.

Đối số đầu tiên #là một mảng 2D trong đó 0đại diện cho băng, 1đại diện cho đất và 2đại diện cho đá.

Đối số thứ hai #2và đối số thứ ba lần lượt #3là điểm bắt đầu và điểm kết thúc trong biểu mẫu {row,column}.

là ký tự sử dụng riêng 3 byte U+F4A1đại diện \[Function].

Giải trình

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

Xác định hàm pcó danh sách xbiểu mẫu {row,column}và đầu ra #[[row,column]]; tức là giá trị băng / đất / đá tại tọa độ đó.

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

Xác định hàm mlấy vị trí bắt đầu cvà vectơ chỉ hướng vvà xác định đệ quy nơi bạn sẽ kết thúc. Nếu c+vlà băng, thì chúng ta tiếp tục trượt từ điểm đó, vì vậy nó trở lại m[c+v,v]. Nếu c+vlà đất, sau đó chúng ta di chuyển đến c+vvà dừng lại. Mặt khác (nếu c+vlà đá hoặc ngoài giới hạn), bạn không di chuyển. Lưu ý rằng điều này chỉ nhằm mục đích được gọi trên các vị trí băng hoặc đất.

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

Xác định danh sách gcác vị trí băng và đất ( pgiá trị nhỏ hơn 2).

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

Định nghĩa một hàm amà phải mất một vị trí bắt đầu cvà trả về kết quả của việc di chuyển trong {1,0}, {-1,0}, {0,1}, và {0,-1}hướng. Có thể có một số dư thừa. Một lần nữa, điều này giả định rằng ctương ứng với băng hoặc đất.

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

Xác định danh sách ecác cạnh được định hướng đại diện cho các bước đi hợp pháp. Đối với mỗi vị trí #trong g, tính bảng của các cạnh #->ccho mỗi ctrong a@#. Sau đó, vì chúng tôi sẽ kết thúc với một danh sách phụ cho từng vị trí #, tôi làm phẳng cấp độ đầu tiên. Có thể có một số vòng và nhiều cạnh.

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

Graph[e]là biểu đồ trong đó các nút là các vị trí hợp pháp (băng hoặc đất) và các cạnh thể hiện các bước di chuyển hợp pháp (có thể va vào đá và không di chuyển). Sau đó chúng tôi sử dụng FindPathđể tìm đường dẫn từ #2đến #3đại diện dưới dạng danh sách các nút. Vì FindPathcó thể lấy các đối số bổ sung để tìm nhiều hơn một đường dẫn, kết quả thực sự sẽ là một danh sách chứa một đường dẫn duy nhất, vì vậy tôi lấy phần tử đầu tiên sử dụng [[1]]. Sau đó, tôi lấy liên tiếp Differencescủa tọa độ và Normalizechúng. Như vậy là lên {-1,0}, xuống là {1,0}, phải là {0,1}và trái là {0,-1}.

Các trường hợp thử nghiệm

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


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")

Sử dụng BFS , như tôi đã làm để giải quyết thách thức liên quan này

Đầu vào
Bản đồ mê cung là một chuỗi nhiều dòng, sử dụng Ohoặc 0cho đá, 8cho đất và bất kỳ chữ số khác không nhỏ hơn 8 cho băng ( 7nhìn tốt).
Vị trí bắt đầu và kết thúc là không dựa trên.

Đầu ra
Một danh sách bù, trong đó -1 là W, 1 là E, âm nhỏ hơn -1 là Nvà dương lớn hơn 1 làS

Ít chơi gôn

(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
}

Kiểm tra

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.