diff --git a/cpp/.clang-format b/.clang-format similarity index 100% rename from cpp/.clang-format rename to .clang-format diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index a6adf82..75be62a 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -13,6 +13,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: make test - working-directory: ./cpp - run: make test + - name: Configure CMake + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug + - name: Build + run: cmake --build build + - name: Test + working-directory: ./build + run: ./tests diff --git a/.gitignore b/.gitignore index 74a239b..c78edeb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ cpp/8puzzle cpp/findpath cpp/minpathbucharest cpp/tests +build/ +build-release diff --git a/cpp/8puzzle.cpp b/8puzzle.cpp similarity index 100% rename from cpp/8puzzle.cpp rename to 8puzzle.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b3ebad1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.10) +project(astar-algorithm-cpp) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# Header-only library interface (optional but good practice) +add_library(stlastar INTERFACE) +target_include_directories(stlastar INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + +# Executables +add_executable(8puzzle 8puzzle.cpp) +target_link_libraries(8puzzle stlastar) + +add_executable(findpath findpath.cpp) +target_link_libraries(findpath stlastar) + +add_executable(minpathbucharest min_path_to_Bucharest.cpp) +target_link_libraries(minpathbucharest stlastar) + +# Tests +enable_testing() +add_executable(tests tests.cpp) +target_link_libraries(tests stlastar) +add_test(NAME tests COMMAND tests) diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..5efa037 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,92 @@ +# A* Algorithm C++ Implementation + +## Project Overview + +This project provides a clean, efficient, and header-only C++ implementation of the A* (A-Star) pathfinding algorithm. It is designed for high-performance applications like video games and includes an optional fixed-size memory allocator (`fsa.h`) to minimize memory fragmentation and allocation overhead. + +The core logic resides in `stlastar.h`, which uses C++ templates to work with any user-defined state class that satisfies the required interface. + +## Building and Running + +### Prerequisites +* C++ compiler supporting C++11 (e.g., `g++`, `clang++`). +* `make` utility. + +### Build Commands +The project uses a `makefile` to manage builds. + +* **Build All:** + ```bash + make + ``` + This compiles the library examples and tests, producing the following executables: + * `8puzzle`: Solves the 8-puzzle sliding tile game. + * `findpath`: Finds a path on a simple grid map. + * `minpathbucharest`: Solves the "classic" AI problem of finding the shortest path to Bucharest. + * `tests`: Runs the unit tests. + +* **Run Tests:** + ```bash + make test + ``` + +* **Clean Build:** + ```bash + make clean + ``` + +### Running Examples +* **8-Puzzle:** + ```bash + ./8puzzle [board_string] + # Example: ./8puzzle 013824765 + ``` +* **Pathfinder:** + ```bash + ./findpath + ``` + +## Development Conventions + +### Core Architecture +* **`stlastar.h`**: The main header file containing the `AStarSearch` class template. This is a header-only library; simply include this file in your project. +* **`fsa.h`**: A fixed-size block memory allocator used internally by `AStarSearch` to optimize node allocation. Can be toggled via `USE_FSA_MEMORY` in `stlastar.h`. + +### User State Interface +To use the A* search, you must define a class (e.g., `MapSearchNode`) that represents a state in your search space. This class acts as a template argument to `AStarSearch` and **must** implement the following methods: + +```cpp +class YourStateClass { +public: + // Heuristic estimate of distance to goal (e.g., Manhattan distance, Euclidean distance) + float GoalDistanceEstimate(YourStateClass &nodeGoal); + + // Returns true if this node is the goal + bool IsGoal(YourStateClass &nodeGoal); + + // Generates successors and adds them to the search + // Implementation should call astarsearch->AddSuccessor(NewNode) for each valid move + bool GetSuccessors(AStarSearch *astarsearch, YourStateClass *parent_node); + + // Cost of moving from this node to the successor + float GetCost(YourStateClass &successor); + + // Returns true if this state is identical to rhs + bool IsSameState(YourStateClass &rhs); + + // Returns a hash of the state (required for std::unordered_set) + size_t Hash(); +}; +``` + +### Usage Pattern +1. Instantiate `AStarSearch astarsearch;`. +2. Create start and goal states. +3. Call `astarsearch.SetStartAndGoalStates(start, goal)`. +4. Loop `astarsearch.SearchStep()` until the state is `SEARCH_STATE_SUCCEEDED` or `SEARCH_STATE_FAILED`. +5. Retrieve the path using `astarsearch.GetSolutionStart()`, `GetSolutionNext()`, etc. +6. Call `astarsearch.FreeSolutionNodes()` and `astarsearch.EnsureMemoryFreed()` to clean up. + +### Testing +* Tests are located in `tests.cpp`. +* Ensure all tests pass with `make test` before submitting changes. diff --git a/README.md b/README.md index c079b18..fb5773f 100644 --- a/README.md +++ b/README.md @@ -54,21 +54,25 @@ If you wish to be added to the list of known products/educational projects using * Lighthouses AI contest https://github.com/marcan/lighthouses_aicontest * Self-Driving Car Engineer Nanodegree Program https://github.com/vanAken/CarND-Path-Planning-Project -### Compilation +### Building -Enter the cpp folder and run make +Generally you can just include the stlastar.h and, optionally, the fsa.h header files and use it directly. The build instructions below are purely for the test suite and example executables. -#### Introduction +#### Using CMake -This implementation is intended to be simple to read yet fairly -efficient. To build it you can compile, with any recent C++ compiler, -the following files : +Some examples: -For 8-puzzle solver +** Use make and make a debug build ** + ```bash + cmake -S . -B builddebug -DCMAKE_BUILD_TYPE=debug + ``` -* 8puzzle.cpp -* stlastar.h -* optionally fsa.h +** Use Ninja and make a Release build ** + ```bash + cmake -S . -B ninjabuildrelease -DCMAKE_BUILD_TYPE=release + ``` + +In both cases you can execute the build using `make -C [build folder]` or `ninja -C [build folder]`. #### Command line @@ -99,4 +103,4 @@ it if you hit an out of memory assert during the search. Compatibility notes: -This version of the code requires any standards compliant C++ using std C++11 +This version of the code requires any standards compliant C++ using std C++11. To build it requires a minimum cmake version you can find in the `CMakeLists.txt` file. diff --git a/cpp/makefile b/cpp/makefile deleted file mode 100644 index 88e7c4a..0000000 --- a/cpp/makefile +++ /dev/null @@ -1,25 +0,0 @@ -all : 8puzzle findpath minpathbucharest tests - -# Set the C++ compiler to g++ -CXX = g++ - -# Set some common C++ flags -CXXFLAGS = -std=c++11 -Wall - -clean : - rm 8puzzle findpath minpathbucharest tests - -minpathbucharest : min_path_to_Bucharest.cpp stlastar.h - $(CXX) $(CXXFLAGS) min_path_to_Bucharest.cpp -o minpathbucharest - -8puzzle : 8puzzle.cpp stlastar.h - $(CXX) $(CXXFLAGS) -Wall 8puzzle.cpp -o 8puzzle - -findpath : findpath.cpp stlastar.h - $(CXX) $(CXXFLAGS) findpath.cpp -o findpath - -tests : tests.cpp 8puzzle findpath minpathbucharest - $(CXX) $(CXXFLAGS) tests.cpp -o tests - -test: tests - ./tests diff --git a/cpp/findpath.cpp b/findpath.cpp similarity index 100% rename from cpp/findpath.cpp rename to findpath.cpp diff --git a/cpp/fsa.h b/fsa.h similarity index 100% rename from cpp/fsa.h rename to fsa.h diff --git a/license.txt b/license.txt index 1d985c2..a0dbee3 100644 --- a/license.txt +++ b/license.txt @@ -1,5 +1,6 @@ The MIT License (MIT) -Copyright (c) 2001, 2013 Justin Heyes-Jones + +Copyright (c) 2001 - 2026 Justin Heyes-Jones Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/cpp/min_path_to_Bucharest.cpp b/min_path_to_Bucharest.cpp similarity index 100% rename from cpp/min_path_to_Bucharest.cpp rename to min_path_to_Bucharest.cpp diff --git a/cpp/stlastar.h b/stlastar.h similarity index 100% rename from cpp/stlastar.h rename to stlastar.h diff --git a/cpp/tests.cpp b/tests.cpp similarity index 100% rename from cpp/tests.cpp rename to tests.cpp