{
    "slug": "a_star_algorithm",
    "term": "A* Pathfinding Algorithm",
    "category": "algorithms",
    "difficulty": "advanced",
    "short": "Heuristic search algorithm that finds the lowest-cost path using f(n)=g(n)+h(n), widely used in maps and game AI.",
    "long": "A* is a best-first graph search algorithm that extends Dijkstra’s algorithm by adding a heuristic function h(n), which estimates the remaining cost to the goal. Nodes are prioritised using f(n) = g(n) + h(n), where g(n) is the known cost from the start. With an admissible and consistent heuristic, A* is both complete and optimal. Its efficiency depends heavily on heuristic quality — a good heuristic drastically reduces explored nodes compared to Dijkstra. Common heuristics include Manhattan distance for grid movement and Euclidean distance for continuous space. In PHP, A* is most applicable in routing systems, game AI, logistics optimisation, and path-based simulations.",
    "aliases": [
        "A-star",
        "A* search",
        "heuristic pathfinding"
    ],
    "tags": [
        "algorithms",
        "pathfinding",
        "graphs",
        "game-ai",
        "optimization"
    ],
    "misconception": "A* is always faster than Dijkstra. In reality, performance depends entirely on the heuristic — with h(n)=0, A* becomes Dijkstra and loses its advantage.",
    "why_it_matters": "Poor pathfinding scales badly — A* reduces search space dramatically, enabling real-time routing, AI movement, and logistics optimisation without brute-force traversal.",
    "common_mistakes": [
        "Using a heuristic that overestimates — breaks optimality guarantees.",
        "Using arrays instead of a priority queue — leads to O(n) extraction instead of O(log n).",
        "Revisiting nodes without checking for better gScore — causes unnecessary expansions.",
        "Not separating g(n) and f(n) — mixing them leads to incorrect path selection."
    ],
    "when_to_use": [
        "Finding shortest paths in weighted graphs with spatial structure.",
        "Game AI movement or map routing with clear distance heuristics."
    ],
    "avoid_when": [
        "Graph has no meaningful heuristic — use Dijkstra instead.",
        "All edge costs are equal and graph is small — BFS may be simpler."
    ],
    "related": [
        "dijkstra_algorithm",
        "graph_algorithms",
        "graph_data_structure"
    ],
    "prerequisites": [],
    "refs": [
        "https://en.wikipedia.org/wiki/A*_search_algorithm"
    ],
    "bad_code": "<?php\n// ❌ BFS — ignores edge weights and heuristic guidance\nfunction bfsPath(array $grid, array $start, array $goal): array\n{\n    $queue = [[$start, [$start]]];\n    $visited = [];\n\n    while (!empty($queue)) {\n        [$node, $path] = array_shift($queue); // O(n)\n\n        if ($node === $goal) {\n            return $path;\n        }\n\n        foreach (neighbours($grid, $node) as $next) {\n            if (!in_array($next, $visited, true)) {\n                $visited[] = $next;\n                $queue[] = [$next, [...$path, $next]];\n            }\n        }\n    }\n\n    return [];\n}",
    "good_code": "<?php\n// ✅ A* with proper priority queue and scoring\nfunction astar(array $grid, array $start, array $goal): array\n{\n    $open = new SplMinHeap();\n    $gScore = [];\n    $cameFrom = [];\n\n    $key = fn($n) => $n[0] . ',' . $n[1];\n\n    $h = fn($n) => abs($goal[0] - $n[0]) + abs($goal[1] - $n[1]);\n\n    $startKey = $key($start);\n    $gScore[$startKey] = 0;\n\n    $open->insert([0 + $h($start), $start]);\n\n    while (!$open->isEmpty()) {\n        [, $current] = $open->extract();\n\n        if ($current === $goal) {\n            return reconstructPath($cameFrom, $current);\n        }\n\n        foreach (neighbours($grid, $current) as $next) {\n            $currentKey = $key($current);\n            $nextKey = $key($next);\n\n            $tentativeG = ($gScore[$currentKey] ?? INF) + cost($current, $next);\n\n            if ($tentativeG < ($gScore[$nextKey] ?? INF)) {\n                $cameFrom[$nextKey] = $current;\n                $gScore[$nextKey] = $tentativeG;\n\n                $fScore = $tentativeG + $h($next);\n                $open->insert([$fScore, $next]);\n            }\n        }\n    }\n\n    return []; // no path\n}",
    "example_note": "BFS explores uniformly, while A* prioritises promising paths using a heuristic, reducing explored nodes significantly.",
    "quick_fix": "Use SplMinHeap and Manhattan heuristic: f = g + abs(dx) + abs(dy).",
    "severity": "info",
    "effort": "high",
    "created": "2026-03-23",
    "updated": "2026-03-27",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/a_star_algorithm",
        "html_url": "https://codeclaritylab.com/glossary/a_star_algorithm",
        "json_url": "https://codeclaritylab.com/glossary/a_star_algorithm.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[A* Pathfinding Algorithm](https://codeclaritylab.com/glossary/a_star_algorithm) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/a_star_algorithm"
            }
        }
    }
}