迷路ゲーム

説明

迷路の中にある他のキャラクターに捕まらずに、すべてのドットを食べてください!

キーボードのカーソルキー、または行きたい方向に画面をタップすることで、男の子のキャラクターを動かすことができます。

Studioで試す

以下のリンクから Jasmine Tea でこのサンプルプログラムを Studio 画面で開いて実際に試すことができます。プログラムを実行したいときは、エディターの右下にある青色の「実行」ボタンを押してください。

Studio で開く

プログラム

// 迷路の大きさ
MAZE_WIDTH=19
MAZE_HEIGHT=11

// メインループ
do
  cls 3
  // 迷路を描いて配列を得る
  maze@=draw_maze@(MAZE_WIDTH,MAZE_HEIGHT)
  // ドット総数
  all_dots=calc_dot_count(MAZE_WIDTH,MAZE_HEIGHT,maze@)
  // 主人公の表示
  mx=1
  my=1
  call show_hero mx,my
  // 敵の表示
  ex@=[MAZE_WIDTH-2,MAZE_WIDTH-2]
  ey@=[MAZE_HEIGHT-2,1]
  es@=[random(1,12),random(1,12)]
  call show_enemy ex@,ey@,es@,0
  call show_enemy ex@,ey@,es@,1
  // 敵2の方向
  ed=-1
  do
    // 主人公の移動
    mpos@=move_hero@(mx,my,MAZE_WIDTH,maze@)
    mx=mpos@[0]
    my=mpos@[1]
    // 敵1の移動
    epos@=move_enemy1@(mx,my,ex@[0],ey@[0],es@[0],MAZE_WIDTH,maze@)
    ex@[0]=epos@[0]
    ey@[0]=epos@[1]
    es@[0]=epos@[2]
    // 敵2の移動
    epos@=move_enemy2@(ex@[1],ey@[1],es@[1],ed,MAZE_WIDTH,maze@)
    ex@[1]=epos@[0]
    ey@[1]=epos@[1]
    es@[1]=epos@[2]
    ed=epos@[3]
    // クラッシュ判定
    call is_crash es@
    // ドット食べたか判定
    if is_ate_dot(mx,my,MAZE_WIDTH,maze@) then
      maze@[my*MAZE_WIDTH+mx]=2
      box (mx*32+16,my*32+8)-(mx*32+31+16,my*31+32+8),0,0
      all_dots=all_dots-1
    end if
    // 残りのドット数の表示
    call print_remaining_dot_count all_dots
    // クリア判定
    if all_dots=0 then
      call print_game_clear
      exit do
    end if
  loop
loop

// ゲームクリア表示
procedure print_game_clear
  locate 17,10
  print "ゲームクリア"
  pause 5000
end procedure

// 残りのドット数の表示
procedure print_remaining_dot_count all_dots
  locate 1,23
  print "のこりのドット:";all_dots;"  ";
end procedure

// ドット判定
function is_ate_dot(x,y,width,maze@)
  return maze@[y*width+x]=0
end function

// 当たり判定
procedure is_crash es@
  if crash(0,es@[0]) or crash(0,es@[1]) then
    locate 15,10
    print "ゲームオーバー"
    end
  end if
end procedure

// 敵2の移動
function move_enemy2@(ex,ey,es,ed,width,maze@)
  if not moving(es) then
    if ed=-1 then
      if can_move(ex,ey,width,5,maze@) then
        epos@=move_enemy2_sprite@(ex,ey,5,es,ed)
      else
        if can_move(ex,ey,width,7,maze@) then
          epos@=move_enemy2_sprite@(ex,ey,7,es,ed)
        end if
      end if
    else
      if ed=1 or ed=5 then
        if random(0,1)=0 then
          nd1=3
          nd2=7
        else
          nd1=7
          nd2=3
        end if
        if can_move(ex,ey,width,nd1,maze@) then
            epos@=move_enemy2_sprite@(ex,ey,nd1,es,ed)
        else
          if can_move(ex,ey,width,nd2,maze@) then
            epos@=move_enemy2_sprite@(ex,ey,nd2,es,ed)
          else
            if ed=1 then
              if can_move(ex,ey,width,1,maze@) then
                epos@=move_enemy2_sprite@(ex,ey,1,es,ed)
              else
                epos@=move_enemy2_sprite@(ex,ey,5,es,ed)
              end if
            else
              if can_move(ex,ey,width,5,maze@) then
                epos@=move_enemy2_sprite@(ex,ey,5,es,ed)
              else
                epos@=move_enemy2_sprite@(ex,ey,1,es,ed)
              end if
            end if
          end if
        end if
      else
        if random(0,1)=0 then
          nd1=1
          nd2=5
        else
          nd1=5
          nd2=1
        end if
        if can_move(ex,ey,width,nd1,maze@) then
          epos@=move_enemy2_sprite@(ex,ey,nd1,es,ed)
        else
          if can_move(ex,ey,width,nd2,maze@) then
            epos@=move_enemy2_sprite@(ex,ey,nd2,es,ed)
          else
            if ed=3 then
              if can_move(ex,ey,width,3,maze@) then
                epos@=move_enemy2_sprite@(ex,ey,3,es,ed)
              else
                epos@=move_enemy2_sprite@(ex,ey,7,es,ed)
              end if
            else
              if can_move(ex,ey,width,7,maze@) then
                epos@=move_enemy2_sprite@(ex,ey,7,es,ed)
              else
                epos@=move_enemy2_sprite@(ex,ey,3,es,ed)
              end if
            end if
          end if
        end if
      end if
    end if
    ex=epos@[0]
    ey=epos@[1]
    ed=epos@[2]
  end if
  return [ex,ey,es,ed]
end function

// 敵2のスプライトの移動
function move_enemy2_sprite@(ex,ey,d,es,ed)
  direction es,d
  if d=5 then
    ey=ey+1
  end if
  if d=7 then
    ex=ex-1
  end if
  if d=3 then
    ex=ex+1
  end if
  if d=1 then
    ey=ey-1
  end if
  ed=d
  move es
  return [ex,ey,ed]
end function

// 敵1の移動
function move_enemy1@(mx,my,ex,ey,es,width,maze@)
  if not moving(es) then
    tdir=decide_enemy1_direction(mx,my,ex,ey,width,maze@)
    direction es,tdir
    if tdir=1 then
      ey=ey-1
    end if
    if tdir=3 then
      ex=ex+1
    end if
    if tdir=5 then
      ey=ey+1
    end if
    if tdir=7 then
      ex=ex-1
    end if
    move es
  end if
  return [ex,ey,es]
end function

// 敵機1の移動方向の決定
function decide_enemy1_direction(mx,my,ex,ey,width,maze@)
  tdist=100
  if can_move(ex,ey,width,1,maze@) then
    dist=calc_hero_enemy_distance(mx,my,ex,ey-1)
    if dist<tdist then
      tdist=dist
      tdir=1
    end if
  end if
  if can_move(ex,ey,width,3,maze@) then
    dist=calc_hero_enemy_distance(mx,my,ex+1,ey)
    if dist<tdist then
      tdist=dist
      tdir=3
    end if
  end if
  if can_move(ex,ey,width,5,maze@) then
    dist=calc_hero_enemy_distance(mx,my,ex,ey+1)
    if dist<tdist then
      tdist=dist
      tdir=5
    end if
  end if
  if can_move(ex,ey,width,7,maze@) then
    dist=calc_hero_enemy_distance(mx,my,ex-1,ey)
    if dist<tdist then
      tdist=dist
      tdir=7
    end if
  end if
  return tdir
end function

// 自機と敵の距離を計算
function calc_hero_enemy_distance(mx,my,ex,ey)
  return sqr(pow(abs(mx-ex),2)+pow(abs(my-ey),2))
end function

// 主人公の移動
function move_hero@(mx,my,width,maze@)
  if not moving(0) then
    d=decide_hero_direction()
    if can_move(mx,my,width,d,maze@) then
      mpos@=move_hero_sprite@(d,mx,my)
      mx=mpos@[0]
      my=mpos@[1]
    end if
  end if
  return [mx,my]
end function

// 主人公のスプライトを移動
function move_hero_sprite@(d,mx,my)
  if d=5 then
    my=my+1
  end if
  if d=1 then
    my=my-1
  end if
  if d=3 then
    mx=mx+1
  end if
  if d=7 then
    mx=mx-1
  end if
  direction 0,d
  move 0
  return [mx,my]
end function

// 主人公の移動方向を決定
function decide_hero_direction()
  d=0
  k$=inkey$()
  tap tx,ty
  if k$<>"" then
    if k$="ArrowDown" then
      d=5
    else if k$="ArrowUp" then
      d=1
    else if k$="ArrowRight" then
      d=3
    else if k$="ArrowLeft" then
      d=7
    end if
  else
    if tx<>-1 then
      if xpos(0)<tx and tx<xpos(0)+31 then
        if ty<(ypos(0)+16) then
          d=1
        else if (ypos(0)+16)<ty then
          d=5
        end if
      else
        if ypos(0)<ty and ty<ypos(0)+31 then
          if tx<(xpos(0)+16) then
            d=7
          else if (xpos(0)+16)<tx then
            d=3
          end if
        end if
      end if
    end if
  end if
  return d
end function

// 指定位置から指定方向に移動できるか
function can_move(x,y,width,d,maze@)
  if d=5 then
    return maze@[(y+1)*width+x]<>1
  else if d=1 then
    return maze@[(y-1)*width+x]<>1
  else if d=3 then
    return maze@[y*width+(x+1)]<>1
  else if d=7 then
    return maze@[y*width+(x-1)]<>1
  else
    return 0
  end if
end function

// 敵の表示
procedure show_enemy ex@,ey@,es@,no
  distance es@[no],32
  speed es@[no],13
  show es@[no],(16+ex@[no]*32,8+ey@[no]*32-1)
end procedure

// 主人公の表示
procedure show_hero x,y
  distance 0,32
  speed 0,18
  show 0,(16+x*32,8+y*32-1)
end procedure

// ドット数の計算
function calc_dot_count(width,height,maze@)
  dot_count=0
  for y=0 to height-1
    for x=0 to width-1
      if maze@[y*width+x]<>1 then
        if maze@[(y-1)*width+x]=0 or maze@[(y+1)*width+x]=0 or maze@[y*width+(x+1)]=0 or maze@[y*width+(x-1)]=0 then
          dot_count=dot_count+1
        end if
      end if
    next
  next
  return dot_count
end function

// 迷路の描画
function draw_maze@(width,height)
  maze@=[]
  for y=0 to height-1
    for x=0 to width-1
      maze@[y*width+x]=0
      if y=0 or y=height-1 or x=0 or x=width-1 then
        maze@[y*width+x]=1
      end if
      if x%2=0 and y%2=0 then
        maze@[y*width+x]=1
        if x<>0 and x<>width-1 and y<>0 and y<>height-1 then
          r=random(0,3)
          if r=0 then
            maze@[(y-1)*width+x]=1
          else if r=1 then
            maze@[y*width+(x+1)]=1
          else if r=2 then
            maze@[(y+1)*width+x]=1
          else if r=3 then
            maze@[y*width+(x-1)]=1
          end if
        end if
      end if
    next
  next
  wall=random(440,481)
  render 0
  for y=0 to height-1
    for x=0 to width-1
      if maze@[y*width+x]=1 then
        put (x*32+16,y*32+8),wall
        put (x*32+16+16,y*32+8),wall
        put (x*32+16,y*32+16+8),wall
        put (x*32+16+16,y*32+16+8),wall
      else
        if maze@[(y-1)*width+x]=0 or maze@[(y+1)*width+x]=0 or maze@[y*width+(x+1)]=0 or maze@[y*width+(x-1)]=0 then
          put (x*32+16+8,y*32+8+8),random(367,370)
        end if
      end if
    next
  next
  render 1
  return maze@
end function

解説

ゲームのメインループは、6行目から56行目です。メインループでは、以下の処理を順番に行っています。各処理は、プロシージャまたは関数として作成されています。

迷路の情報は、maze@ 配列が持っています。maze@ 配列の各要素は、以下のいずれかの値が代入されています。

2つの敵は、それぞれ移動の処理に特徴があります。