[{"data":1,"prerenderedAt":1523},["ShallowReactive",2],{"blog-game-pathfinding-algorithms":3},{"id":4,"title":5,"body":6,"description":15,"extension":1513,"meta":1514,"navigation":659,"path":1519,"seo":1520,"stem":1521,"__hash__":1522},"blog\u002Fblog\u002Fgame-pathfinding-algorithms.md","Game Pathfinding Explained: DFS, BFS, Dijkstra, and A*",{"type":7,"value":8,"toc":1511},"minimark",[9,1507],[10,11,12,819],"i18n-text",{},[13,14,16,20,29,32,37,52,55,59,62,99,104,222,226,229,255,259,363,367,378,406,411,558,562,569,626,631,784,788,816],"template",{"v-slot:en":15},"",[17,18,5],"h1",{"id":19},"game-pathfinding-explained-dfs-bfs-dijkstra-and-a",[21,22,23,24,28],"p",{},"Have you ever wondered how enemies in a game navigate a complex maze to find the player, or how a strategy game unit figures out the best route around obstacles? The answer lies in ",[25,26,27],"strong",{},"Pathfinding algorithms",".",[21,30,31],{},"In this guide, we'll explore the four most common pathfinding algorithms used in game development, from the simplest to the industry standard.",[33,34,36],"h2",{"id":35},"_1-the-world-as-a-graph-or-grid","1. The World as a Graph or Grid",[21,38,39,40,43,44,47,48,51],{},"Before an algorithm can find a path, it needs to understand the game world. Most games represent the walkable world as a ",[25,41,42],{},"Grid"," (squares, hexagons) or a ",[25,45,46],{},"NavMesh"," (polygons). These can all be boiled down to a ",[25,49,50],{},"Graph",": a series of points (nodes) connected by lines (edges).",[21,53,54],{},"Our goal is simple: find a sequence of nodes from the start point to the target point.",[33,56,58],{"id":57},"_2-depth-first-search-dfs","2. Depth-First Search (DFS)",[21,60,61],{},"Imagine walking through a maze. You pick a path, follow it until you hit a dead end, backtrack to the last intersection, and try another path. This is exactly how Depth-First Search works.",[63,64,65,72,78,88],"ul",{},[66,67,68,71],"li",{},[25,69,70],{},"How it works:"," It dives as \"deep\" as possible into the graph before backtracking.",[66,73,74,77],{},[25,75,76],{},"Pros:"," Uses very little memory.",[66,79,80,83,84,87],{},[25,81,82],{},"Cons:"," It does ",[25,85,86],{},"not"," guarantee the shortest path. In a wide open grid, DFS might take a wild zigzagging route hitting every corner before finding the target.",[66,89,90,93,94,98],{},[25,91,92],{},"Best for:"," Procedural maze generation or checking if a path ",[95,96,97],"em",{},"exists",", but terrible for actual character movement.",[21,100,101],{},[25,102,103],{},"Example Code (Grid-based):",[105,106,110],"pre",{"className":107,"code":108,"language":109,"meta":15,"style":15},"language-javascript shiki shiki-themes github-light github-dark","function dfs_grid(grid, start, target) {\n  let stack = [start];\n  let visited = new Set();\n  \n  while (stack.length > 0) {\n    let current = stack.pop(); \u002F\u002F Pop from top (LIFO)\n    let key = `${current.x},${current.y}`;\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Found\n    \n    if (!visited.has(key)) {\n      visited.add(key);\n      let neighbors = getNeighbors(grid, current); \u002F\u002F e.g., up, down, left, right\n      for (let neighbor of neighbors) stack.push(neighbor);\n    }\n  }\n  return false;\n}\n","javascript",[111,112,113,121,127,133,139,145,151,157,163,169,174,180,186,192,198,204,210,216],"code",{"__ignoreMap":15},[114,115,118],"span",{"class":116,"line":117},"line",1,[114,119,120],{},"function dfs_grid(grid, start, target) {\n",[114,122,124],{"class":116,"line":123},2,[114,125,126],{},"  let stack = [start];\n",[114,128,130],{"class":116,"line":129},3,[114,131,132],{},"  let visited = new Set();\n",[114,134,136],{"class":116,"line":135},4,[114,137,138],{},"  \n",[114,140,142],{"class":116,"line":141},5,[114,143,144],{},"  while (stack.length > 0) {\n",[114,146,148],{"class":116,"line":147},6,[114,149,150],{},"    let current = stack.pop(); \u002F\u002F Pop from top (LIFO)\n",[114,152,154],{"class":116,"line":153},7,[114,155,156],{},"    let key = `${current.x},${current.y}`;\n",[114,158,160],{"class":116,"line":159},8,[114,161,162],{},"    \n",[114,164,166],{"class":116,"line":165},9,[114,167,168],{},"    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Found\n",[114,170,172],{"class":116,"line":171},10,[114,173,162],{},[114,175,177],{"class":116,"line":176},11,[114,178,179],{},"    if (!visited.has(key)) {\n",[114,181,183],{"class":116,"line":182},12,[114,184,185],{},"      visited.add(key);\n",[114,187,189],{"class":116,"line":188},13,[114,190,191],{},"      let neighbors = getNeighbors(grid, current); \u002F\u002F e.g., up, down, left, right\n",[114,193,195],{"class":116,"line":194},14,[114,196,197],{},"      for (let neighbor of neighbors) stack.push(neighbor);\n",[114,199,201],{"class":116,"line":200},15,[114,202,203],{},"    }\n",[114,205,207],{"class":116,"line":206},16,[114,208,209],{},"  }\n",[114,211,213],{"class":116,"line":212},17,[114,214,215],{},"  return false;\n",[114,217,219],{"class":116,"line":218},18,[114,220,221],{},"}\n",[33,223,225],{"id":224},"_3-breadth-first-search-bfs","3. Breadth-First Search (BFS)",[21,227,228],{},"Unlike DFS, BFS explores the world symmetrically. Imagine dropping a stone in a pond; the ripples expand outwards in all directions equally.",[63,230,231,236,245,250],{},[66,232,233,235],{},[25,234,70],{}," It checks all immediate neighbors first, then the neighbors of those neighbors, expanding outwards step by step.",[66,237,238,240,241,244],{},[25,239,76],{}," It ",[25,242,243],{},"guarantees"," the shortest path, provided every step has the same cost (unweighted graph).",[66,246,247,249],{},[25,248,82],{}," It explores everywhere in all directions. It doesn't care where the target is until it accidentally bumps into it. Thus, it is slow and wastes memory.",[66,251,252,254],{},[25,253,92],{}," Finding the shortest path on a simple, flat grid where every tile takes the same effort to walk on (e.g., standard tile-based puzzle games).",[21,256,257],{},[25,258,103],{},[105,260,262],{"className":107,"code":261,"language":109,"meta":15,"style":15},"function bfs_grid(grid, start, target) {\n  let queue = [start];\n  let visited = new Set();\n  visited.add(`${start.x},${start.y}`);\n  \n  while (queue.length > 0) {\n    let current = queue.shift(); \u002F\u002F Remove from front (FIFO)\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Found\n    \n    let neighbors = getNeighbors(grid, current);\n    for (let neighbor of neighbors) {\n      let key = `${neighbor.x},${neighbor.y}`;\n      if (!visited.has(key)) {\n        visited.add(key);\n        queue.push(neighbor);\n      }\n    }\n  }\n  return false;\n}\n",[111,263,264,269,274,278,283,287,292,297,301,305,309,314,319,324,329,334,339,344,348,353,358],{"__ignoreMap":15},[114,265,266],{"class":116,"line":117},[114,267,268],{},"function bfs_grid(grid, start, target) {\n",[114,270,271],{"class":116,"line":123},[114,272,273],{},"  let queue = [start];\n",[114,275,276],{"class":116,"line":129},[114,277,132],{},[114,279,280],{"class":116,"line":135},[114,281,282],{},"  visited.add(`${start.x},${start.y}`);\n",[114,284,285],{"class":116,"line":141},[114,286,138],{},[114,288,289],{"class":116,"line":147},[114,290,291],{},"  while (queue.length > 0) {\n",[114,293,294],{"class":116,"line":153},[114,295,296],{},"    let current = queue.shift(); \u002F\u002F Remove from front (FIFO)\n",[114,298,299],{"class":116,"line":159},[114,300,162],{},[114,302,303],{"class":116,"line":165},[114,304,168],{},[114,306,307],{"class":116,"line":171},[114,308,162],{},[114,310,311],{"class":116,"line":176},[114,312,313],{},"    let neighbors = getNeighbors(grid, current);\n",[114,315,316],{"class":116,"line":182},[114,317,318],{},"    for (let neighbor of neighbors) {\n",[114,320,321],{"class":116,"line":188},[114,322,323],{},"      let key = `${neighbor.x},${neighbor.y}`;\n",[114,325,326],{"class":116,"line":194},[114,327,328],{},"      if (!visited.has(key)) {\n",[114,330,331],{"class":116,"line":200},[114,332,333],{},"        visited.add(key);\n",[114,335,336],{"class":116,"line":206},[114,337,338],{},"        queue.push(neighbor);\n",[114,340,341],{"class":116,"line":212},[114,342,343],{},"      }\n",[114,345,346],{"class":116,"line":218},[114,347,203],{},[114,349,351],{"class":116,"line":350},19,[114,352,209],{},[114,354,356],{"class":116,"line":355},20,[114,357,215],{},[114,359,361],{"class":116,"line":360},21,[114,362,221],{},[33,364,366],{"id":365},"_4-dijkstras-algorithm","4. Dijkstra's Algorithm",[21,368,369,370,373,374,377],{},"What if the world isn't flat? What if walking through a swamp takes twice as much energy as walking on a road? BFS assumes every step costs the same (cost = 1). ",[25,371,372],{},"Dijkstra's Algorithm"," fixes this by introducing ",[25,375,376],{},"movement costs"," (weighted graphs).",[63,379,380,385,392,397],{},[66,381,382,384],{},[25,383,70],{}," It keeps track of the \"accumulated cost\" from the start node to all explored nodes. It always prioritizes exploring the next node with the lowest accumulated cost.",[66,386,387,240,389,391],{},[25,388,76],{},[25,390,243],{}," the lowest-cost (shortest or easiest) path in any world with varied terrain (mountains, roads, water).",[66,393,394,396],{},[25,395,82],{}," Like BFS, it expands in all directions (favoring the easy terrain first). It doesn't \"aim\" toward the target. In a large map, this is computationally expensive.",[66,398,399,401,402,405],{},[25,400,92],{}," Strategy games with varied terrain types, but only if the target's location isn't known or if calculating routes to ",[95,403,404],{},"many"," targets at once.",[21,407,408],{},[25,409,410],{},"Example Code (Grid-based with varied weights):",[105,412,414],{"className":107,"code":413,"language":109,"meta":15,"style":15},"function dijkstra_grid(grid, start, target) {\n  \u002F\u002F Using an array and sorting it to simulate a Priority Queue (Min-Heap)\n  let pq = [{ node: start, cost: 0 }];\n  let costs = {};\n  costs[`${start.x},${start.y}`] = 0;\n  \n  while (pq.length > 0) {\n    pq.sort((a, b) => a.cost - b.cost); \u002F\u002F Always process cheapest cost node first\n    let current = pq.shift().node;\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Found\n    \n    let currentCost = costs[`${current.x},${current.y}`];\n    let neighbors = getNeighbors(grid, current);\n    \n    for (let item of neighbors) { \u002F\u002F item contains .node and .weight (terrain difficulty)\n      let nextNode = item.node;\n      let newCost = currentCost + item.weight; \n      let key = `${nextNode.x},${nextNode.y}`;\n      \n      \u002F\u002F If unvisited or a cheaper path is found\n      if (!(key in costs) || newCost \u003C costs[key]) {\n        costs[key] = newCost;\n        pq.push({ node: nextNode, cost: newCost });\n      }\n    }\n  }\n  return false;\n}\n",[111,415,416,421,426,431,436,441,445,450,455,460,464,468,472,477,481,485,490,495,500,505,510,515,521,527,533,538,543,548,553],{"__ignoreMap":15},[114,417,418],{"class":116,"line":117},[114,419,420],{},"function dijkstra_grid(grid, start, target) {\n",[114,422,423],{"class":116,"line":123},[114,424,425],{},"  \u002F\u002F Using an array and sorting it to simulate a Priority Queue (Min-Heap)\n",[114,427,428],{"class":116,"line":129},[114,429,430],{},"  let pq = [{ node: start, cost: 0 }];\n",[114,432,433],{"class":116,"line":135},[114,434,435],{},"  let costs = {};\n",[114,437,438],{"class":116,"line":141},[114,439,440],{},"  costs[`${start.x},${start.y}`] = 0;\n",[114,442,443],{"class":116,"line":147},[114,444,138],{},[114,446,447],{"class":116,"line":153},[114,448,449],{},"  while (pq.length > 0) {\n",[114,451,452],{"class":116,"line":159},[114,453,454],{},"    pq.sort((a, b) => a.cost - b.cost); \u002F\u002F Always process cheapest cost node first\n",[114,456,457],{"class":116,"line":165},[114,458,459],{},"    let current = pq.shift().node;\n",[114,461,462],{"class":116,"line":171},[114,463,162],{},[114,465,466],{"class":116,"line":176},[114,467,168],{},[114,469,470],{"class":116,"line":182},[114,471,162],{},[114,473,474],{"class":116,"line":188},[114,475,476],{},"    let currentCost = costs[`${current.x},${current.y}`];\n",[114,478,479],{"class":116,"line":194},[114,480,313],{},[114,482,483],{"class":116,"line":200},[114,484,162],{},[114,486,487],{"class":116,"line":206},[114,488,489],{},"    for (let item of neighbors) { \u002F\u002F item contains .node and .weight (terrain difficulty)\n",[114,491,492],{"class":116,"line":212},[114,493,494],{},"      let nextNode = item.node;\n",[114,496,497],{"class":116,"line":218},[114,498,499],{},"      let newCost = currentCost + item.weight; \n",[114,501,502],{"class":116,"line":350},[114,503,504],{},"      let key = `${nextNode.x},${nextNode.y}`;\n",[114,506,507],{"class":116,"line":355},[114,508,509],{},"      \n",[114,511,512],{"class":116,"line":360},[114,513,514],{},"      \u002F\u002F If unvisited or a cheaper path is found\n",[114,516,518],{"class":116,"line":517},22,[114,519,520],{},"      if (!(key in costs) || newCost \u003C costs[key]) {\n",[114,522,524],{"class":116,"line":523},23,[114,525,526],{},"        costs[key] = newCost;\n",[114,528,530],{"class":116,"line":529},24,[114,531,532],{},"        pq.push({ node: nextNode, cost: newCost });\n",[114,534,536],{"class":116,"line":535},25,[114,537,343],{},[114,539,541],{"class":116,"line":540},26,[114,542,203],{},[114,544,546],{"class":116,"line":545},27,[114,547,209],{},[114,549,551],{"class":116,"line":550},28,[114,552,215],{},[114,554,556],{"class":116,"line":555},29,[114,557,221],{},[33,559,561],{"id":560},"_5-a-a-star-search-algorithm","5. A* (A-Star) Search Algorithm",[21,563,564,565,568],{},"Dijkstra is smart, but it's blind to the target. ",[25,566,567],{},"A","* takes Dijkstra's Algorithm and gives it a compass. This is the undisputed king of pathfinding in the game industry.",[63,570,571,607,616,621],{},[66,572,573,575,576,579,580,583],{},[25,574,70],{}," A* uses a ",[25,577,578],{},"heuristic"," (a smart guess) to estimate the distance remaining from a node to the goal.\nThe algorithm evaluates nodes based on the formula: ",[111,581,582],{},"F = G + H",[63,584,585,591,597],{},[66,586,587,590],{},[25,588,589],{},"G:"," The exact cost from the start to the current node (like Dijkstra).",[66,592,593,596],{},[25,594,595],{},"H (Heuristic):"," The estimated cost from the current node to the end target.",[66,598,599,602,603,606],{},[25,600,601],{},"F:"," The total score. A* always explores the node with the lowest ",[111,604,605],{},"F"," first.",[66,608,609,611,612,615],{},[25,610,76],{}," It is incredibly fast because it actively stretches ",[95,613,614],{},"towards"," the target, ignoring paths that obviously go in the wrong direction. It guarantees the shortest path (if the heuristic is well-designed).",[66,617,618,620],{},[25,619,82],{}," Can consume a lot of memory on massive maps, requiring optimizations like NavMeshes or Hierarchical Pathfinding.",[66,622,623,625],{},[25,624,92],{}," Almost every modern game requiring intelligent point-A to point-B movement.",[21,627,628],{},[25,629,630],{},"Example Code (Grid-based with Heuristic):",[105,632,634],{"className":107,"code":633,"language":109,"meta":15,"style":15},"\u002F\u002F Manhattan distance heuristic for 4-directional grid movement\nfunction heuristic(nodeA, nodeB) {\n  return Math.abs(nodeA.x - nodeB.x) + Math.abs(nodeA.y - nodeB.y);\n}\n\nfunction a_star_grid(grid, start, target) {\n  let pq = [{ node: start, fCost: 0 }];\n  let gCosts = {}; \u002F\u002F Cost from start\n  gCosts[`${start.x},${start.y}`] = 0;\n  \n  while (pq.length > 0) {\n    pq.sort((a, b) => a.fCost - b.fCost); \u002F\u002F Explore lowest F-cost first\n    let current = pq.shift().node;\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Found\n    \n    let neighbors = getNeighbors(grid, current);\n    for (let item of neighbors) {\n      let nextNode = item.node;\n      let newGCost = gCosts[`${current.x},${current.y}`] + item.weight; \n      let key = `${nextNode.x},${nextNode.y}`;\n      \n      if (!(key in gCosts) || newGCost \u003C gCosts[key]) {\n        gCosts[key] = newGCost;\n        \u002F\u002F F = G + H\n        let fCost = newGCost + heuristic(nextNode, target); \n        pq.push({ node: nextNode, fCost: fCost });\n      }\n    }\n  }\n  return false;\n}\n",[111,635,636,641,646,651,655,661,666,671,676,681,685,689,694,698,702,706,710,714,719,723,728,732,736,741,746,751,756,761,765,769,774,779],{"__ignoreMap":15},[114,637,638],{"class":116,"line":117},[114,639,640],{},"\u002F\u002F Manhattan distance heuristic for 4-directional grid movement\n",[114,642,643],{"class":116,"line":123},[114,644,645],{},"function heuristic(nodeA, nodeB) {\n",[114,647,648],{"class":116,"line":129},[114,649,650],{},"  return Math.abs(nodeA.x - nodeB.x) + Math.abs(nodeA.y - nodeB.y);\n",[114,652,653],{"class":116,"line":135},[114,654,221],{},[114,656,657],{"class":116,"line":141},[114,658,660],{"emptyLinePlaceholder":659},true,"\n",[114,662,663],{"class":116,"line":147},[114,664,665],{},"function a_star_grid(grid, start, target) {\n",[114,667,668],{"class":116,"line":153},[114,669,670],{},"  let pq = [{ node: start, fCost: 0 }];\n",[114,672,673],{"class":116,"line":159},[114,674,675],{},"  let gCosts = {}; \u002F\u002F Cost from start\n",[114,677,678],{"class":116,"line":165},[114,679,680],{},"  gCosts[`${start.x},${start.y}`] = 0;\n",[114,682,683],{"class":116,"line":171},[114,684,138],{},[114,686,687],{"class":116,"line":176},[114,688,449],{},[114,690,691],{"class":116,"line":182},[114,692,693],{},"    pq.sort((a, b) => a.fCost - b.fCost); \u002F\u002F Explore lowest F-cost first\n",[114,695,696],{"class":116,"line":188},[114,697,459],{},[114,699,700],{"class":116,"line":194},[114,701,162],{},[114,703,704],{"class":116,"line":200},[114,705,168],{},[114,707,708],{"class":116,"line":206},[114,709,162],{},[114,711,712],{"class":116,"line":212},[114,713,313],{},[114,715,716],{"class":116,"line":218},[114,717,718],{},"    for (let item of neighbors) {\n",[114,720,721],{"class":116,"line":350},[114,722,494],{},[114,724,725],{"class":116,"line":355},[114,726,727],{},"      let newGCost = gCosts[`${current.x},${current.y}`] + item.weight; \n",[114,729,730],{"class":116,"line":360},[114,731,504],{},[114,733,734],{"class":116,"line":517},[114,735,509],{},[114,737,738],{"class":116,"line":523},[114,739,740],{},"      if (!(key in gCosts) || newGCost \u003C gCosts[key]) {\n",[114,742,743],{"class":116,"line":529},[114,744,745],{},"        gCosts[key] = newGCost;\n",[114,747,748],{"class":116,"line":535},[114,749,750],{},"        \u002F\u002F F = G + H\n",[114,752,753],{"class":116,"line":540},[114,754,755],{},"        let fCost = newGCost + heuristic(nextNode, target); \n",[114,757,758],{"class":116,"line":545},[114,759,760],{},"        pq.push({ node: nextNode, fCost: fCost });\n",[114,762,763],{"class":116,"line":550},[114,764,343],{},[114,766,767],{"class":116,"line":555},[114,768,203],{},[114,770,772],{"class":116,"line":771},30,[114,773,209],{},[114,775,777],{"class":116,"line":776},31,[114,778,215],{},[114,780,782],{"class":116,"line":781},32,[114,783,221],{},[33,785,787],{"id":786},"summary","Summary",[63,789,790,796,802,808],{},[66,791,792,795],{},[25,793,794],{},"DFS:"," Wanders aimlessly until it bumps into the goal. Bad for pathfinding.",[66,797,798,801],{},[25,799,800],{},"BFS:"," Expands equally in all directions. Finds shortest path in unweighted grids.",[66,803,804,807],{},[25,805,806],{},"Dijkstra:"," Expands favoring easier terrain. Finds lowest-cost path in weighted grids.",[66,809,810,815],{},[95,811,812,814],{},[95,813,567],{},":","* Explores smartly toward the target. The industry standard for efficient pathfinding.",[21,817,818],{},"Understanding these concepts will drastically improve how you approach AI movement in your games!",[13,820,821,825,831,834,838,850,853,856,859,893,898,978,981,984,1010,1014,1104,1108,1119,1148,1153,1278,1282,1288,1335,1340,1476,1480,1504],{"v-slot:id":15},[17,822,824],{"id":823},"memahami-pathfinding-game-dfs-bfs-dijkstra-dan-a","Memahami Pathfinding Game: DFS, BFS, Dijkstra, dan A*",[21,826,827,828,28],{},"Pernahkah Anda bertanya-tanya bagaimana musuh dalam game bisa menavigasi labirin yang rumit untuk menemukan pemain, atau bagaimana unit permainan strategi mencari rute terbaik untuk menghindari rintangan? Jawabannya ada pada ",[25,829,830],{},"Algoritma Pathfinding",[21,832,833],{},"Dalam panduan ini, kita akan menjelajahi empat algoritma pathfinding paling umum yang digunakan dalam pengembangan game, dari yang paling sederhana hingga standar industri saat ini.",[33,835,837],{"id":836},"_1-dunia-sebagai-graph-atau-grid","1. Dunia Sebagai Graph atau Grid",[21,839,840,841,843,844,846,847,849],{},"Sebelum sebuah algoritma dapat menemukan jalur, algoritma tersebut harus memahami simulasi dunia game. Sebagian besar game merepresentasikan area yang bisa dipijak sebagai ",[25,842,42],{}," (kotak-kotak, heksagon) atau ",[25,845,46],{}," (poligon). Semua ini pada dasarnya bisa disederhanakan menjadi ",[25,848,50],{}," (Graf): sekumpulan titik (node) yang dihubungkan oleh garis (edge).",[21,851,852],{},"Tujuan utama kita sangat jelas: menemukan urutan titik dari titik awal (start) menuju titik tujuan (target).",[33,854,58],{"id":855},"_2-depth-first-search-dfs-1",[21,857,858],{},"Bayangkan Anda sedang berjalan di dalam labirin. Anda memilih satu lorong, menelusurinya terus sampai menemui jalan buntu, lalu kembali ke persimpangan terakhir dan mencoba lorong lain. Ini adalah cara kerja DFS secara harfiah.",[63,860,861,867,873,883],{},[66,862,863,866],{},[25,864,865],{},"Cara kerja:"," Menjelajah \"sedalam\" mungkin ke dalam rute graf sebelum akhirnya mundur (backtracking) jika menemui kegagalan.",[66,868,869,872],{},[25,870,871],{},"Kelebihan:"," Menggunakan sangat sedikit memori.",[66,874,875,878,879,882],{},[25,876,877],{},"Kekurangan:"," Algoritma ini ",[25,880,881],{},"tidak"," menjamin rute terpendek. Pada ruang terbuka, DFS bisa mengambil jalur zig-zag ekstrem ke seluruh penjuru ruangan sebelum menemukan targetnya.",[66,884,885,888,889,892],{},[25,886,887],{},"Cocok untuk:"," Pembuatan labirin acak (procedural generation) atau memeriksa apakah sebuah ",[95,890,891],{},"jalur itu ada",", tetapi amat sangat buruk untuk pergerakan karakter.",[21,894,895],{},[25,896,897],{},"Contoh Kode (Berbasis Grid):",[105,899,901],{"className":107,"code":900,"language":109,"meta":15,"style":15},"function dfs_grid(grid, start, target) {\n  let stack = [start];\n  let visited = new Set();\n  \n  while (stack.length > 0) {\n    let current = stack.pop(); \u002F\u002F Ambil dari urutan paling akhir (LIFO)\n    let key = `${current.x},${current.y}`;\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Ketemu\n    \n    if (!visited.has(key)) {\n      visited.add(key);\n      let neighbors = getNeighbors(grid, current); \u002F\u002F cth: atas, bawah, kiri, kanan\n      for (let neighbor of neighbors) stack.push(neighbor);\n    }\n  }\n  return false;\n}\n",[111,902,903,907,911,915,919,923,928,932,936,941,945,949,953,958,962,966,970,974],{"__ignoreMap":15},[114,904,905],{"class":116,"line":117},[114,906,120],{},[114,908,909],{"class":116,"line":123},[114,910,126],{},[114,912,913],{"class":116,"line":129},[114,914,132],{},[114,916,917],{"class":116,"line":135},[114,918,138],{},[114,920,921],{"class":116,"line":141},[114,922,144],{},[114,924,925],{"class":116,"line":147},[114,926,927],{},"    let current = stack.pop(); \u002F\u002F Ambil dari urutan paling akhir (LIFO)\n",[114,929,930],{"class":116,"line":153},[114,931,156],{},[114,933,934],{"class":116,"line":159},[114,935,162],{},[114,937,938],{"class":116,"line":165},[114,939,940],{},"    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Ketemu\n",[114,942,943],{"class":116,"line":171},[114,944,162],{},[114,946,947],{"class":116,"line":176},[114,948,179],{},[114,950,951],{"class":116,"line":182},[114,952,185],{},[114,954,955],{"class":116,"line":188},[114,956,957],{},"      let neighbors = getNeighbors(grid, current); \u002F\u002F cth: atas, bawah, kiri, kanan\n",[114,959,960],{"class":116,"line":194},[114,961,197],{},[114,963,964],{"class":116,"line":200},[114,965,203],{},[114,967,968],{"class":116,"line":206},[114,969,209],{},[114,971,972],{"class":116,"line":212},[114,973,215],{},[114,975,976],{"class":116,"line":218},[114,977,221],{},[33,979,225],{"id":980},"_3-breadth-first-search-bfs-1",[21,982,983],{},"Berbeda dengan DFS, BFS menjelajahi dunia secara merata. Bayangkan Anda menjatuhkan batu ke dalam kolam; riaknya melebar ke segala arah secara bersamaan.",[63,985,986,991,1000,1005],{},[66,987,988,990],{},[25,989,865],{}," Algoritma memeriksa semua area sekitarnya terlebih dahulu (radius 1 langkah), kemudian area di sekitar area tersebut (radius 2 langkah), dan terus melebar selangkah demi selangkah.",[66,992,993,995,996,999],{},[25,994,871],{}," Secara otomatis ",[25,997,998],{},"menjamin"," rute terpendek, dengan syarat setiap langkah punya bobot kesulitan yang sama (unweighted graph).",[66,1001,1002,1004],{},[25,1003,877],{}," BFS menjelajah ke segala penjuru arah. Ia tidak peduli di mana target berada hingga secara tidak sengaja \"menabrak\" target tersebut. Karena itu, kinerjanya lambat memproses banyak petak dan boros memori.",[66,1006,1007,1009],{},[25,1008,887],{}," Mencari jalur terpendek pada grid kotak yang polos, di mana setiap area memakan usaha langkah yang sama (misalkan game puzzle tile base sederhana).",[21,1011,1012],{},[25,1013,897],{},[105,1015,1017],{"className":107,"code":1016,"language":109,"meta":15,"style":15},"function bfs_grid(grid, start, target) {\n  let queue = [start];\n  let visited = new Set();\n  visited.add(`${start.x},${start.y}`);\n  \n  while (queue.length > 0) {\n    let current = queue.shift(); \u002F\u002F Ambil dari urutan paling awal (FIFO)\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Ketemu\n    \n    let neighbors = getNeighbors(grid, current);\n    for (let neighbor of neighbors) {\n      let key = `${neighbor.x},${neighbor.y}`;\n      if (!visited.has(key)) {\n        visited.add(key);\n        queue.push(neighbor);\n      }\n    }\n  }\n  return false;\n}\n",[111,1018,1019,1023,1027,1031,1035,1039,1043,1048,1052,1056,1060,1064,1068,1072,1076,1080,1084,1088,1092,1096,1100],{"__ignoreMap":15},[114,1020,1021],{"class":116,"line":117},[114,1022,268],{},[114,1024,1025],{"class":116,"line":123},[114,1026,273],{},[114,1028,1029],{"class":116,"line":129},[114,1030,132],{},[114,1032,1033],{"class":116,"line":135},[114,1034,282],{},[114,1036,1037],{"class":116,"line":141},[114,1038,138],{},[114,1040,1041],{"class":116,"line":147},[114,1042,291],{},[114,1044,1045],{"class":116,"line":153},[114,1046,1047],{},"    let current = queue.shift(); \u002F\u002F Ambil dari urutan paling awal (FIFO)\n",[114,1049,1050],{"class":116,"line":159},[114,1051,162],{},[114,1053,1054],{"class":116,"line":165},[114,1055,940],{},[114,1057,1058],{"class":116,"line":171},[114,1059,162],{},[114,1061,1062],{"class":116,"line":176},[114,1063,313],{},[114,1065,1066],{"class":116,"line":182},[114,1067,318],{},[114,1069,1070],{"class":116,"line":188},[114,1071,323],{},[114,1073,1074],{"class":116,"line":194},[114,1075,328],{},[114,1077,1078],{"class":116,"line":200},[114,1079,333],{},[114,1081,1082],{"class":116,"line":206},[114,1083,338],{},[114,1085,1086],{"class":116,"line":212},[114,1087,343],{},[114,1089,1090],{"class":116,"line":218},[114,1091,203],{},[114,1093,1094],{"class":116,"line":350},[114,1095,209],{},[114,1097,1098],{"class":116,"line":355},[114,1099,215],{},[114,1101,1102],{"class":116,"line":360},[114,1103,221],{},[33,1105,1107],{"id":1106},"_4-algoritma-dijkstra","4. Algoritma Dijkstra",[21,1109,1110,1111,1114,1115,1118],{},"Bagaimana jika dunia tidak sepenuhnya rata? Bagaimana bila berjalan melewati rawa membutuhkan waktu dua kali lipat dibanding berjalan di aspal? BFS mengasumsikan setiap langkah berharga sama (cost = 1). ",[25,1112,1113],{},"Algoritma Dijkstra"," memperbaiki kelemahan ini dengan memperkenalkan ",[25,1116,1117],{},"movement cost"," (bobot graf\u002Fweighted graph).",[63,1120,1121,1126,1134,1139],{},[66,1122,1123,1125],{},[25,1124,865],{}," Melacak \"akumulasi biaya perjalanan\" dari titik awal ke semua titik yang sedang dijelajahi. Dijkstra akan selalu memprioritaskan penjelajahan ke titik berikutnya yang memiliki total poin\u002Fbiaya perjalanan terendah.",[66,1127,1128,1130,1131,1133],{},[25,1129,871],{}," Dijkstra ",[25,1132,998],{}," jalur dengan rintangan\u002Fbiaya termurah (terpendek atau termudah) di peta dengan medan yang bervariasi (gunung, jalan raya, air).",[66,1135,1136,1138],{},[25,1137,877],{}," Sama seperti BFS, Dijkstra melebar secara radial (walau ia akan lebih dulu menjelajah daratan yang mudah). Ia tidak \"membidik\" ke arah tujuan. Pada ukuran map yang masif, melakukan ini terlalu intensif secara komputasi.",[66,1140,1141,1143,1144,1147],{},[25,1142,887],{}," Permainan strategi (RTS) dengan banyak jenis medan, tapi hanya efisien bila posisi target tidak diketahui pasti atau ketika mencari rute ke ",[95,1145,1146],{},"banyak"," objek sekaligus.",[21,1149,1150],{},[25,1151,1152],{},"Contoh Kode (Berbasis Grid dengan bobot bervariasi):",[105,1154,1156],{"className":107,"code":1155,"language":109,"meta":15,"style":15},"function dijkstra_grid(grid, start, target) {\n  \u002F\u002F Menggunakan array yang disortir untuk mensimulasikan Priority Queue (Min-Heap)\n  let pq = [{ node: start, cost: 0 }];\n  let costs = {};\n  costs[`${start.x},${start.y}`] = 0;\n  \n  while (pq.length > 0) {\n    pq.sort((a, b) => a.cost - b.cost); \u002F\u002F Proses jarak\u002Fbiaya termurah lebih dulu\n    let current = pq.shift().node;\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Ketemu\n    \n    let currentCost = costs[`${current.x},${current.y}`];\n    let neighbors = getNeighbors(grid, current);\n    \n    for (let item of neighbors) { \u002F\u002F item berisi .node dan .weight (kesulitan medan)\n      let nextNode = item.node;\n      let newCost = currentCost + item.weight; \n      let key = `${nextNode.x},${nextNode.y}`;\n      \n      \u002F\u002F Jika belum dikunjungi atau menemukan rute yang lebih murah\n      if (!(key in costs) || newCost \u003C costs[key]) {\n        costs[key] = newCost;\n        pq.push({ node: nextNode, cost: newCost });\n      }\n    }\n  }\n  return false;\n}\n",[111,1157,1158,1162,1167,1171,1175,1179,1183,1187,1192,1196,1200,1204,1208,1212,1216,1220,1225,1229,1233,1237,1241,1246,1250,1254,1258,1262,1266,1270,1274],{"__ignoreMap":15},[114,1159,1160],{"class":116,"line":117},[114,1161,420],{},[114,1163,1164],{"class":116,"line":123},[114,1165,1166],{},"  \u002F\u002F Menggunakan array yang disortir untuk mensimulasikan Priority Queue (Min-Heap)\n",[114,1168,1169],{"class":116,"line":129},[114,1170,430],{},[114,1172,1173],{"class":116,"line":135},[114,1174,435],{},[114,1176,1177],{"class":116,"line":141},[114,1178,440],{},[114,1180,1181],{"class":116,"line":147},[114,1182,138],{},[114,1184,1185],{"class":116,"line":153},[114,1186,449],{},[114,1188,1189],{"class":116,"line":159},[114,1190,1191],{},"    pq.sort((a, b) => a.cost - b.cost); \u002F\u002F Proses jarak\u002Fbiaya termurah lebih dulu\n",[114,1193,1194],{"class":116,"line":165},[114,1195,459],{},[114,1197,1198],{"class":116,"line":171},[114,1199,162],{},[114,1201,1202],{"class":116,"line":176},[114,1203,940],{},[114,1205,1206],{"class":116,"line":182},[114,1207,162],{},[114,1209,1210],{"class":116,"line":188},[114,1211,476],{},[114,1213,1214],{"class":116,"line":194},[114,1215,313],{},[114,1217,1218],{"class":116,"line":200},[114,1219,162],{},[114,1221,1222],{"class":116,"line":206},[114,1223,1224],{},"    for (let item of neighbors) { \u002F\u002F item berisi .node dan .weight (kesulitan medan)\n",[114,1226,1227],{"class":116,"line":212},[114,1228,494],{},[114,1230,1231],{"class":116,"line":218},[114,1232,499],{},[114,1234,1235],{"class":116,"line":350},[114,1236,504],{},[114,1238,1239],{"class":116,"line":355},[114,1240,509],{},[114,1242,1243],{"class":116,"line":360},[114,1244,1245],{},"      \u002F\u002F Jika belum dikunjungi atau menemukan rute yang lebih murah\n",[114,1247,1248],{"class":116,"line":517},[114,1249,520],{},[114,1251,1252],{"class":116,"line":523},[114,1253,526],{},[114,1255,1256],{"class":116,"line":529},[114,1257,532],{},[114,1259,1260],{"class":116,"line":535},[114,1261,343],{},[114,1263,1264],{"class":116,"line":540},[114,1265,203],{},[114,1267,1268],{"class":116,"line":545},[114,1269,209],{},[114,1271,1272],{"class":116,"line":550},[114,1273,215],{},[114,1275,1276],{"class":116,"line":555},[114,1277,221],{},[33,1279,1281],{"id":1280},"_5-algoritma-a-a-star","5. Algoritma A* (A-Star)",[21,1283,1284,1285,1287],{},"Dijkstra cukup pintar, tapi dia buta arah terhadap tujuan akhir. ",[25,1286,567],{},"* lahir dengan cara mengambil pondasi dasar Dijkstra lalu memberikannya semacam \"kompas\". Algoritma Inilah raja pathfinding yang tak terbantahkan dalam industri game.",[63,1289,1290,1320,1325,1330],{},[66,1291,1292,1294,1295,1297,1298,1300],{},[25,1293,865],{}," A* menggunakan fitur yang disebut ",[25,1296,578],{}," (perkiraan logis yang cerdas) untuk memperkirakan sisa jarak dari titik saat ini ke garis finish.\nA* mengevaluasi wilayah berdasarkan rumus: ",[111,1299,582],{},[63,1301,1302,1307,1312],{},[66,1303,1304,1306],{},[25,1305,589],{}," Biaya akurat sesungguhnya dari garis awal ke titik saat ini (seperti Dijkstra).",[66,1308,1309,1311],{},[25,1310,595],{}," Estimasi kasar jarak dari titik saat ini ke titik target.",[66,1313,1314,1316,1317,1319],{},[25,1315,601],{}," Nilai total biaya. A* akan selalu memprioritaskan mengecek node dengan nilai ",[111,1318,605],{}," terendah terlebih dahulu.",[66,1321,1322,1324],{},[25,1323,871],{}," Sangat cepat dan responsif. Karena algoritma ini secara aktif \"meregang\" ke arah target, ia mengabaikan jalur yang jelas-jelas bergerak ke arah yang salah. A* tetap menjamin rute pergerakan terpendek (asalkan rumus heuristic di desain dengan benar).",[66,1326,1327,1329],{},[25,1328,877],{}," Bisa memakan jumlah memori yang besar pada lingkungan raksasa (Open world map) sehingga memerlukan optimasi ekstra seperti sistem Hierarchical Pathfinding dan NavMesh poligon khusus.",[66,1331,1332,1334],{},[25,1333,887],{}," Hampir semua AI modern mutakhir yang memicu pergerakan karakter A-ke-B.",[21,1336,1337],{},[25,1338,1339],{},"Contoh Kode (Berbasis Grid beserta Heuristic):",[105,1341,1343],{"className":107,"code":1342,"language":109,"meta":15,"style":15},"\u002F\u002F Rumus jarak Manhattan untuk pergerakan 4-arah dalam grid\nfunction heuristic(nodeA, nodeB) {\n  return Math.abs(nodeA.x - nodeB.x) + Math.abs(nodeA.y - nodeB.y);\n}\n\nfunction a_star_grid(grid, start, target) {\n  let pq = [{ node: start, fCost: 0 }];\n  let gCosts = {}; \u002F\u002F Biaya (Cost) asli dari lokasi start\n  gCosts[`${start.x},${start.y}`] = 0;\n  \n  while (pq.length > 0) {\n    pq.sort((a, b) => a.fCost - b.fCost); \u002F\u002F Proses nilai F (F-cost) terendah terlebih dahulu\n    let current = pq.shift().node;\n    \n    if (current.x === target.x && current.y === target.y) return true; \u002F\u002F Ketemu\n    \n    let neighbors = getNeighbors(grid, current);\n    for (let item of neighbors) {\n      let nextNode = item.node;\n      let newGCost = gCosts[`${current.x},${current.y}`] + item.weight; \n      let key = `${nextNode.x},${nextNode.y}`;\n      \n      if (!(key in gCosts) || newGCost \u003C gCosts[key]) {\n        gCosts[key] = newGCost;\n        \u002F\u002F F = G + H\n        let fCost = newGCost + heuristic(nextNode, target); \n        pq.push({ node: nextNode, fCost: fCost });\n      }\n    }\n  }\n  return false;\n}\n",[111,1344,1345,1350,1354,1358,1362,1366,1370,1374,1379,1383,1387,1391,1396,1400,1404,1408,1412,1416,1420,1424,1428,1432,1436,1440,1444,1448,1452,1456,1460,1464,1468,1472],{"__ignoreMap":15},[114,1346,1347],{"class":116,"line":117},[114,1348,1349],{},"\u002F\u002F Rumus jarak Manhattan untuk pergerakan 4-arah dalam grid\n",[114,1351,1352],{"class":116,"line":123},[114,1353,645],{},[114,1355,1356],{"class":116,"line":129},[114,1357,650],{},[114,1359,1360],{"class":116,"line":135},[114,1361,221],{},[114,1363,1364],{"class":116,"line":141},[114,1365,660],{"emptyLinePlaceholder":659},[114,1367,1368],{"class":116,"line":147},[114,1369,665],{},[114,1371,1372],{"class":116,"line":153},[114,1373,670],{},[114,1375,1376],{"class":116,"line":159},[114,1377,1378],{},"  let gCosts = {}; \u002F\u002F Biaya (Cost) asli dari lokasi start\n",[114,1380,1381],{"class":116,"line":165},[114,1382,680],{},[114,1384,1385],{"class":116,"line":171},[114,1386,138],{},[114,1388,1389],{"class":116,"line":176},[114,1390,449],{},[114,1392,1393],{"class":116,"line":182},[114,1394,1395],{},"    pq.sort((a, b) => a.fCost - b.fCost); \u002F\u002F Proses nilai F (F-cost) terendah terlebih dahulu\n",[114,1397,1398],{"class":116,"line":188},[114,1399,459],{},[114,1401,1402],{"class":116,"line":194},[114,1403,162],{},[114,1405,1406],{"class":116,"line":200},[114,1407,940],{},[114,1409,1410],{"class":116,"line":206},[114,1411,162],{},[114,1413,1414],{"class":116,"line":212},[114,1415,313],{},[114,1417,1418],{"class":116,"line":218},[114,1419,718],{},[114,1421,1422],{"class":116,"line":350},[114,1423,494],{},[114,1425,1426],{"class":116,"line":355},[114,1427,727],{},[114,1429,1430],{"class":116,"line":360},[114,1431,504],{},[114,1433,1434],{"class":116,"line":517},[114,1435,509],{},[114,1437,1438],{"class":116,"line":523},[114,1439,740],{},[114,1441,1442],{"class":116,"line":529},[114,1443,745],{},[114,1445,1446],{"class":116,"line":535},[114,1447,750],{},[114,1449,1450],{"class":116,"line":540},[114,1451,755],{},[114,1453,1454],{"class":116,"line":545},[114,1455,760],{},[114,1457,1458],{"class":116,"line":550},[114,1459,343],{},[114,1461,1462],{"class":116,"line":555},[114,1463,203],{},[114,1465,1466],{"class":116,"line":771},[114,1467,209],{},[114,1469,1470],{"class":116,"line":776},[114,1471,215],{},[114,1473,1474],{"class":116,"line":781},[114,1475,221],{},[33,1477,1479],{"id":1478},"kesimpulan-singkat","Kesimpulan Singkat",[63,1481,1482,1487,1492,1497],{},[66,1483,1484,1486],{},[25,1485,794],{}," Berjalan tanpa tujuan jelas sampai menabrak finish. Buruk untuk pathfinding.",[66,1488,1489,1491],{},[25,1490,800],{}," Bergerak meluas keluar seperti riak air. Menemukan rute terpendek di jarak kotak yang bobot jalannya rata.",[66,1493,1494,1496],{},[25,1495,806],{}," Meluas namun mengutamakan medan jalan termurah. Menemukan rute berbiaya usaha terendah pada map bergelombang\u002Frintangan.",[66,1498,1499,1503],{},[95,1500,1501,814],{},[95,1502,567],{},"* Secara cerdas membidik ke arah tujuan finish. Solusi terbaik standar perindustrian.",[21,1505,1506],{},"Memahami konsep-konsep ini akan secara dramatis meningkatkan cara Anda merancang pergerakan kecerdasan buatan (AI) buatan sendiri!",[1508,1509,1510],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":15,"searchDepth":123,"depth":123,"links":1512},[],"md",{"title_en":5,"title_id":824,"description_en":1515,"description_id":1516,"date":1517,"readingTime":1518},"A comprehensive guide to understanding pathfinding algorithms in game development, from basic DFS and BFS to advanced Dijkstra and A* (A-Star).","Panduan lengkap memahami algoritma pathfinding dalam pembuatan game, mulai dari dasar DFS dan BFS hingga Dijkstra dan A* (A-Star).","2026-03-26","12 min read","\u002Fblog\u002Fgame-pathfinding-algorithms",{"title":5,"description":15},"blog\u002Fgame-pathfinding-algorithms","P_zZNLUPB0fiinrVA7Mj7qKLFsgG9TyaTofAK4l4uGc",1783751390913]