diff --git a/graph-search/src/features/maze/solvers.js b/graph-search/src/features/maze/solvers.js
index c6f67cf842bf2e5f8a3e992d07c40966bfa570fa..a8b585075e6e8ccd9854a6ae07d2658851b3d85a 100644
--- a/graph-search/src/features/maze/solvers.js
+++ b/graph-search/src/features/maze/solvers.js
@@ -72,7 +72,7 @@ export function solveByDijkstras(maze) {
 }
 
 function heuristic(maze, cell) {
-  return 0; // TODO: stub
+  return Math.abs(maze.exit.x - cell.x) + Math.abs(maze.exit.y - cell.y);
 }
 
 export function solveByAStar(maze) {
@@ -80,33 +80,28 @@ export function solveByAStar(maze) {
   const worklist = new PriorityQueue();
   worklist.insert(
     new Edge(undefined, maze.entrance, 0),
-    0 + heuristic(maze.entrance, maze.exit),
+    0 + heuristic(maze, maze.exit),
   );
   while (worklist.size > 0) {
     const workitem = worklist.remove();
-    if (backpointers.has(workitem.to) &&
-      backpointers.get(workitem.to).distance <= workitem.distance) {
+    if (backpointers.has(workitem.to)) {
       continue;
     }
     workitem.to.type = CellType.CONSIDERED;
     backpointers.set(workitem.to, workitem);
     if (workitem.to === maze.exit) {
-      const reversedPath = [];
       for (let current = maze.exit;
         current !== undefined;
         current = backpointers.get(current).from) {
-        reversedPath.push(current);
         current.type = CellType.SOLUTION;
       }
-      return reversedPath.reverse();
+      return;
     }
-    for (const incidence of workitem.to.neighbors) {
+    for (const neighbor of workitem.to.neighbors) {
       worklist.insert(
-        new Edge(workitem.to, incidence.destination, workitem.distance),
-        workitem.distance +
-          heuristic(incidence.destination, maze.exit),
+        new Edge(workitem.to, neighbor, workitem.distance + 1),
+        workitem.distance + 1 + heuristic(maze, neighbor),
       );
     }
   }
-  return undefined;
 }