ocaml-toys / maze / maze.ml

module Parser = struct
  let split separator s =
    let list = ref [] in
    let start = ref 0 in
    let () = try
        while true do
          let index = String.index_from s !start separator in
          list := (String.sub s !start (index - !start)) :: !list;
          start := index + 1
        done
      with Not_found -> list := (String.sub s !start ((String.length s) - !start)) :: !list
    in
    List.rev !list
  
  let from_string str =
    let ants = ref [] and goal = ref (0, 0) in
    let lines = split '\n' str in
    let height, width = List.length lines, String.length (List.hd lines) in
    let maze = Array.make_matrix width height ' ' in
    for x = 0 to width -1 do
      for y = 0 to height -1 do
        maze.(x).(y) <- (List.nth lines y).[x];
        if maze.(x).(y) = '@' then ants := (x, y) :: !ants
        else if maze.(x).(y) = 'X' then goal := x, y
      done
    done;
    maze, !goal, !ants
  
  let from_file filename =
    let channel = open_in_bin filename in
    let size = in_channel_length channel in
    let buffer = Buffer.create size in
    Buffer.add_channel buffer channel size;
    from_string (Buffer.contents buffer)
end

let width maze = Array.length maze
let height maze = Array.length maze.(0)
let check maze (x, y) = x >= 0 && y >= 0 && x < (width maze) && y < (height maze)
let get maze (x, y) = maze.(x).(y)
let set maze (x, y) value = maze.(x).(y) <- value

let walk maze path =
  let walk_once coords = if get maze coords = ' ' then set maze coords '.' in
  List.iter walk_once path

let draw maze =
  for y = 0 to (height maze) -1 do
    for x = 0 to (width maze) -1 do
      print_char (get maze (x, y))
    done;
    print_newline ()
  done

let is_passable maze coord = get maze coord <> '#'

let distance (x1, y1) (x2, y2) =
  let square x = x * x in
  let sqrt_int x = int_of_float (sqrt (float_of_int x)) in
  sqrt_int (square (x1 - x2) + square (y1 - y2))

let neighbor_nodes maze (x, y) =
  let nodes = [] in
  let nodes = if x > 0 then (x -1, y) :: nodes else nodes in
  let nodes = if x < (width maze) - 1 then (x +1, y) :: nodes else nodes in
  let nodes = if y > 0 then (x, y -1) :: nodes else nodes in
  let nodes = if y < (height maze) - 1 then (x, y +1) :: nodes else nodes in
  nodes
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.