iT邦幫忙

1

趣味SQL 260301 來走迷宮

  • 分享至 

  • xImage
迷宮 可以用遞迴

-- 迷宮用 2D 陣列表示:0=通道, 1=牆壁, S=起點, E=終點

create table maze (
  row_idx int not null
, col_idx int not null
, cell char(1) not null check(cell in ('0', '1', 'S', 'E'))
, primary key (row_idx, col_idx)
);

-- 範例迷宮 (7×7)
-- S 0 1 0 0 0 0
-- 0 0 1 0 1 1 0
-- 1 0 0 0 0 0 0
-- 0 0 1 1 1 0 1
-- 0 0 0 0 1 0 0
-- 1 1 1 0 0 0 1
-- 0 0 0 0 1 E 0

insert into maze
select r, c
     , case
        when r = 0 and c = 0 then 'S'
        when r = 6 and c = 5 then 'E'
        when (r,c) in ((0,2),(1,2),(1,4),(1,5),(2,0)
             ,(3,2),(3,3),(3,4),(3,6),(4,4),(5,0),
             (5,1),(5,2),(5,6),(6,4)) then '1'
       else '0'
       end
  from generate_series(0,6) r
     , generate_series(0,6) c;
     
--
with recursive bfs as (
-- 起點
select row_idx
     , col_idx
     , 0 as distance
     , array[row(row_idx, col_idx)] as path
  from maze
 where cell = 'S'
union all
select m.row_idx
     , m.col_idx
     , b.distance + 1
     , b.path || row(m.row_idx, m.col_idx)
  from bfs b
  join maze m
    on (m.row_idx = b.row_idx + 1 and m.col_idx = b.col_idx)
    or (m.row_idx = b.row_idx - 1 and m.col_idx = b.col_idx)
    or (m.row_idx = b.row_idx and m.col_idx = b.col_idx + 1)
    or (m.row_idx = b.row_idx and m.col_idx = b.col_idx - 1)
 where m.cell <> '1' -- 不是牆壁
   and not row(m.row_idx, m.col_idx) = any(b.path)
)
select distance
     , path
  from bfs
 where (row_idx, col_idx) =
       (select row_idx, col_idx
          from maze
         where cell = 'E')
order by distance;

https://ithelp.ithome.com.tw/upload/images/20260301/20050647YgS5MWiOfi.png

with recursive bfs as (
-- 起點
select row_idx
     , col_idx
     , 0 as distance
     , array[row(row_idx, col_idx)] as path
  from maze
 where cell = 'S'
union all
select m.row_idx
     , m.col_idx
     , b.distance + 1
     , b.path || row(m.row_idx, m.col_idx)
  from bfs b
  join maze m
    on abs(m.row_idx - b.row_idx) + abs(m.col_idx - b.col_idx) = 1
       -- 這裡改寫
 where m.cell <> '1' -- 不是牆壁
   and not row(m.row_idx, m.col_idx) = any(b.path)
), pickone as (
select path
  from bfs
 where (row_idx, col_idx) =
       (select row_idx, col_idx
          from maze
         where cell = 'E')
order by distance
limit 1
), path_cells as (
select p.r
     , p.c
  from pickone
  join lateral unnest(path) as p(r int, c int)
    on true
), disp_rows as (
select row_idx
     , string_agg(
           case
             when exists (
             select 1
               from path_cells pc
              where pc.r = row_idx
                and pc.c = col_idx
             ) then case
                     when m.cell in ('S', 'E') then m.cell
                     else '.'
                    end
              when m.cell = '1' then 'X'
              else m.cell
            end
           , ' ' order by col_idx
         ) as row_display
  from maze m
 group by m.row_idx
 order by m.row_idx
)
select string_agg(row_display, E'\n') as maze_display
  from disp_rows;

 maze_display
---------------
 S . X 0 0 0 0
 0 . X 0 X X 0
 X . . . . . 0
 0 0 X X X . X
 0 0 0 0 X . 0
 X X X 0 0 . X
 0 0 0 0 X E 0

X 代表牆壁, . 代表路線, 0 代表其他沒有走的.
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友回答

立即登入回答