Skip to content

kamScripts/pathfinding_grid_based

Repository files navigation

Grid-Based Pathfinding Visualizer

An interactive terminal-based pathfinding visualizer supporting Dijkstra's algorithm and A search with Manhattan distance heuristic on weighted grid graphs.*


Overview

This project demonstrates optimal pathfinding algorithms on randomly generated weighted 2D grids. It features an interactive CLI interface with real-time visualization using Unicode box-drawing characters, colored terrain costs, and highlighted solution paths.

Key Features:

  • Two pathfinding algorithms: Dijkstra's algorithm and A* search
  • Weighted grid graphs with configurable terrain costs (1-3)
  • Random grid generation with seeded reproducibility
  • Live terminal visualization with Unicode box-drawing
  • Interactive CLI menu with safe input handling
  • Performance benchmarking utilities
  • Cross-platform terminal support (Windows, Linux, macOS)

Quick Start

Installation

No external dependencies required for the core application. Uses only Python standard library.

# Optional: For Benchmark visualization
pip install matplotlib

Run the Application

python main.py

Or as a module:

python -m main

This launches an interactive CLI interface with a default 20 by 10 cells grid.

Example Session

  1. Generate New Grid Enter dimensions, choose seed or use random, and wall probability (0.1 = 10% walls)
  2. Find Path Select algorithm (Dijkstra or A*) Enter start and goal coordinates
  3. View Results Visualized path with execution time and total cost displayed

Project Structure

Core Modules

\Graph.py\ - Grid representation

class Graph:
    """Undirected, weighted 4-directional grid graph."""
    - width, height: Grid dimensions
    - weight: 1D adjacency list (optimized memory layout)
    - Methods: node_at(), neighbours(), idx()

Key Functions:

  • \create_grid_graph(width, height, seed, wall_probability)\ - Generate random weighted grids
  • \print_grid_graph(graph, path)\ - Render grid with Unicode visualization
  • \cost_to_color(cost)\ - Map terrain costs to ANSI colors

Grid Representation:

  • Internal: 1D list indexed as \y * width + x\
  • Each cell stores [right_edge_cost, down_edge_cost]\
  • Edge weight 0 = blocked path; 1-3 = terrain cost

\algorithms.py\ - Pathfinding implementations

Implements three algorithms:

1. Dijkstra's Algorithm

def dijkstra(graph, start, goal) -> (distances, previous)
  • Uses priority queue (heapq)
  • Explores nodes in order of increasing distance from start
  • Guaranteed optimal path for non-negative weights
  • Time complexity: O((V + E) log V)

2. A Search*

def a_star(graph, start, goal) -> (previous, g_score)
  • Uses Manhattan distance heuristic: \1.5 * (|x_goal - x| + |y_goal - y|)\
  • Heuristic weighted factor improves efficiency
  • Guarantees optimal path when heuristic is admissible
  • Time complexity: O((V + E) log V) with better practical performance

3. Breadth-First Search (Utility)

def bfs(graph, start) -> parent_map
  • For unweighted grids
  • Used internally for various analyses

Wrapper Function:

def shortest_path(graph, start, goal, algorithm=\"dijkstra\")
   (path_with_costs, total_cost)

Returns list of (node_coordinates, cumulative_cost)\ tuples and total path cost.


\app.py\ - Interactive CLI application

Main Class: \App\

  • Manages user interaction, grid generation, and pathfinding workflow
  • Features colorized output with ANSI color codes
  • Safe input handling with type conversion and validation

Key Methods:

  • \generate_grid()\ - Interactive grid creation with parameters
  • \find_path()\ - Algorithm selection and pathfinding execution
  • \display_main_menu()\ - Main menu interface
  • \print_header()\ - Formatted header with styling

Menu Options:

1. Generate New Grid     - Create new grid with custom dimensions/seed
2. Find Path            - Select algorithm and find path between points
3. Print Current Grid   - Display current grid state
q. Quit                - Exit application

\main.py\ - Entry point

from app import App
app = App()
app.run()

Utilities & Benchmarking

\algo_benchmark.py\ - Performance benchmarking

Benchmarks pathfinding algorithms across multiple grid sizes with multiple trials.

benchmark_running_times()
  • Tests sizes: 50 by 50 to 1000 by 1000
  • Runs 50 trials per test for statistical accuracy
  • Outputs JSON with timing results for three path variants: horizontal, diagonal, center
  • Saves results to \dijkstra_astar.json\

\performance_algos.py\ - Detailed algorithm profiling

benchmark_pathfinding()
  • Profiles CPU time and memory usage
  • Generates .prof\ files for cProfile analysis
  • Tests three path variants: horizontal, diagonal, center

\visualize_tests.py\ - Benchmark visualization

plot_pathfinding_benchmark(json_file=\"dijkstra_astar.json\")
  • Creates comparative performance plots
  • Shows execution time vs. grid size for both algorithms
  • Generates 3-subplot figure (one per path variant)
  • Saves visualization as \pathfinding_benchmark_3_variants.png\

Dependencies

Core (No external packages)

  • \collections\ (deque)
  • \heapq\ (priority queue)
  • \typing\ (type hints)
  • \random\ (grid generation)
  • \os \time \typing (CLI utilities)

Optional (For benchmarking/visualization)

  • \matplotlib\ - Benchmark result visualization
  • \cProfile, \ tracemalloc, \pstats\ - Performance profiling (standard library)
  • \json\ - Results serialization -\gc garbage collector

Algorithm Details

Dijkstra's Algorithm

Suitable for: Weighted graphs where all weights are non-negative

1. Initialize distances to all nodes as infinity (except start = 0)
2. Use priority queue to always process nearest unvisited node
3. For each neighbor, calculate relaxation: new_dist = current_dist + edge_weight
4. Update if new_dist improves previous best
5. Continue until goal reached or queue empty

Complexity:

  • Time: O((V + E) log V) with binary heap
  • Space: O(V) for distances and visited set

A* Search

Suitable for: Single-pair shortest path when good heuristic exists

1. Use f_score = g_score (actual cost) + h(node) (estimated cost to goal)
2. Manhattan heuristic: h = 1.5 * (|x_goal - x| + |y_goal - y|)
3. Heuristic weighting (1.5 factor) accelerates convergence
4. Expand nodes with lowest f_score first
5. Guarantees optimality if heuristic is admissible (never overestimates)

Why faster than Dijkstra:

  • Heuristic guides search toward goal
  • Explores fewer total nodes
  • Especially effective for grid-based pathfinding

Complexity:

  • Time: O((V + E) log V) best case, O(V log V) average with good heuristic
  • Space: O(V) for priority queue and tracking sets

Grid Visualization

Visual Elements

Node Symbols:

  • \ (empty circle) - Unvisited node
  • \ (filled circle) - Node on solution path

Edge Symbols:

 (thin line)  - Single edge (1-3 weight)
 (bold line)  - Path edge (solution path)
 (thin pipe)  - Vertical edge
 (bold pipe)  - Vertical path edge

Colors (ANSI):

  • Green (#41) - Open terrain (cost 1)
  • Blue (#63) - Forest/hills (cost 2)
  • Purple (#198) - Mountain/rough (cost 3)
  • Yellow (\93m) - Solution path
  • Bright green - Menu text

Example Output:

 ○───○───○───○───○───○───○───○───○───○
 │   │   │   │   │   │   │   │   │   │   
 ○───○───○───○───○───○───○───○───○───○
 │   │   │   │   │   │   │   │   │   | 
 ○───○───○───○───○───○───○───○───○───○
 │   │   │   │   │   │   |   │   │   │
 ○───○───○───○───○───○───○───○───○───○
 │   │   │   │   │   │   │   │   │   │
 ○───○───○───○───○───○───○───○───○───○

Configuration & Parameters

Grid Generation

create_grid_graph(
    width: int,              # Grid width (recommend  50-60 for display)
    height: int,             # Grid height (recommend  100)
    seed: int | str,         # Random seed for reproducibility
    wall_probability: float  # Probability to block edge (0.0-1.0)
)

Recommended Settings:

  • Small grids: 10-20 cells for clear visualization
  • Medium grids: 50-100 cells for performance testing
  • Large grids: 500-1000 cells for benchmark comparison

Terrain Costs

COSTS = (1, 2, 3)  # Randomly assigned edge weights
  • Cost 1 = Open terrain (fast)
  • Cost 2 = Forest/hills (moderate)
  • Cost 3 = Mountain/rough (slow)

Performance Characteristics

Benchmark Results Summary

Tested on grids from 5050 to 10001000 with 50 trials each:

Benchmarking 300x300 grid Variant: horizontal dijkstra : 1.8217s | 18.3 MB astar : 0.6007s | 2.8 MB -> A* speedup: 3.03x Variant: diagonal dijkstra : 1.9385s | 25.5 MB astar : 0.0596s | 0.8 MB -> A* speedup: 32.52x Variant: center dijkstra : 0.8105s | 8.0 MB astar : 0.0296s | 0.4 MB -> A* speedup: 27.35x

Key Observations:

  • A* consistently outperforms Dijkstra by 25-75%
  • Speedup increases with grid size
  • Both scale approximately linearly with grid area
  • Manhattan heuristic very effective for grid pathfinding

Usage Examples

Interactive CLI

\$ python main.py

----------------------------------------------------------------------
                  GRID-BASED PATH-FINDING VISUALIZER
                             ● Dijkstra ●
                             ●    A*    ●
----------------------------------------------------------------------
                              Main Menu:
----------------------------------------------------------------------
                        1 → Generate New Grid
                        2 → Find Path
                        3 → Print Current Grid
----------------------------------------------------------------------
                               q → Quit
----------------------------------------------------------------------
Choose option:


Choose option: 1

Generate New Grid

Enter width: 15
Enter height: 10
Enter seed or press Enter for random: 42
Wall-removal probability (0.0-1.0, default 0.1): 0.15

Generating 15x10 grid (seed=42)

...

Programmatic Usage

from Graph import create_grid_graph
from algorithms import shortest_path, dijkstra, a_star

# Create grid
graph = create_grid_graph(20, 15, seed=\'myseed999\', wall_probability=0.1)

# Find shortest path
path, total_cost = shortest_path(
    graph, 
    start=(0, 0), 
    goal=(19, 14), 
    algorithm=\"astar\"
)

if path:
    print(f\"Path length: {len(path)} nodes\")
    print(f\"Total cost: {total_cost:.2f}\")
    for node, cumulative_cost in path:
        print(f\"  {node}: {cumulative_cost:.2f}\")
else:
    print(\"No path found!\")

Running Benchmarks

# Performance benchmarks with JSON output
python algo_benchmark.py

# Detailed profiling (outputs .prof files)
python performance_algos.py

# Visualize results
python visualize_tests.py

Limitations & Future Improvements

Current Limitations

  • Display: Grid width limited to ~50-60 cells for proper terminal rendering (due to terminal width)
  • Grid height: Should not exceed ~100 to avoid excessive scrolling
  • Edge weights: Fixed to 1-3 (not configurable at runtime)
  • Heuristic: Manhattan distance only (no option for Euclidean or other metrics)
  • Movement: 4-directional (no diagonal movement)

Future Enhancements

  • 8-directional movement (including diagonals)
  • Configurable heuristics (Euclidean, custom)
  • Bidirectional A* search
  • Jump Point Search (JPS)
  • Theta* (any-angle pathfinding)
  • Dynamic obstacle handling
  • Multiple goal search
  • GUI visualization (matplotlib/pygame)
  • A* with weights (Weighted A*)
  • Persistent grid save/load

Technical Notes

Memory Optimization

  • Uses 1D list for grid storage instead of 2D for better cache locality
  • Compact representation: 2 integers per cell (edge weights)
  • Example: 10001000 grid = ~2MB (vs ~4MB for 2D arrays)

Algorithm Optimizations

  • Dijkstra: Priority queue prevents unnecessary relaxations
  • A:* Heuristic reduces explored nodes by ~60-75%
  • Tie-breaking: Counter in heap prevents comparison of non-comparable objects

Why 1.5 Manhattan Heuristic?

  • Pure Manhattan distance is admissible but underestimates in weighted grids
  • Weighting factor 1.5 still admissible (weights max out at 3)
  • Provides better guidance toward goal without sacrificing optimality

Code Quality

  • Type Hints: Full typing annotations for better IDE support and documentation
  • Docstrings: Comprehensive module and function documentation
  • Comments: Inline comments for complex logic
  • Error Handling: Input validation with try-except for type conversion
  • Constants: Named constants for magic numbers and colors

References

Amit Patel. (2025) Amit’s A* Pages. Red Blob Games. [Online] [9th December 2025] https://theory.stanford.edu/~amitp/GameProgramming/index.html Goodrich, M. T, Tamassia, R., and Goldwasser M. H. (2013) Data Structures and Algorithms in Python. 1st ed., USA: John Wiley and sons.

Hart, P., Nilsson, N. & Raphael, B. (1968). A Formal Basis for the Heuristic Determination of Minimum Cost Paths. IEEE Transactions on Systems Science and Cybernetics, 4(2), pp.100–107. Python Software Foundation. (2025) heapq - Heap queue algorithm. Python Docs. [Online] [Accessed on 5th December 2025] https://docs.python.org/3/library/heapq.html#priority-queue-implementation-notes Rajesh Kumar. (2024) The A* Algorithm: A Complete Guide. Datacamp. [Online] [9th December 2025] https://www.datacamp.com/tutorial/a-star-algorithm Red Blob Games. (2023) Implementation of A*. Red Blob Games. [Online] [Accessed on 7th December] https://www.redblobgames.com/pathfinding/a-star/implementation.html

Github copilot - readme.md

License

This project is open source and available under the MIT License.


Author

kamScripts - Grid-Based Pathfinding Visualizer Project

About

Pathfinding in A Grid Based World

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages