Skip to content

Commit

Permalink
Add Hex Game implementations.
Browse files Browse the repository at this point in the history
- Add a generic Graph interface for board representation.
- Add a uniform player interface with concrete classes for a human and AI players.
- AI players uses a Monte Carlo approach.
- Path searching uses a custom Depth First approach over a graph.
- Add  a console interface to play the game.
  • Loading branch information
idapena committed Feb 15, 2024
1 parent a2500a9 commit 1e602d2
Show file tree
Hide file tree
Showing 26 changed files with 1,416 additions and 0 deletions.
31 changes: 31 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.27)
project(HexGame)

set(CMAKE_CXX_STANDARD 17)

add_executable(HexGame src/main.cpp
src/common/Graph.tpp
include/common/Graph.h
include/game/Game.h
src/game/HexGame.cpp
include/game/HexGame.h
include/enums/PlayerToken.h
include/player/Player.h
include/player/HumanPlayer.h
include/enums/PlayingSide.h
src/player/HumanPlayer.cpp
src/game/HexBoard.cpp
include/game/HexBoard.h
include/utils/GlobalParameters.h
src/common/GlobalParameters.cpp
include/enums/CompiledOS.h
include/common/AppFunctions.h
src/common/AppFunctions.cpp
src/game/GameSettings.cpp
include/game/GameSettings.h
include/algorithms/PathAlgorithm.h
"include/algorithms/DepthFirstSearch.h"
src/algortihms/DepthFirstSearch.tpp
src/player/MonteCarloAIPlayer.cpp
include/player/MonteCarloAIPlayer.h
)
26 changes: 26 additions & 0 deletions include/algorithms/DepthFirstSearch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef HEXGAME_DEPTHFIRSTSEARCH_H
#define HEXGAME_DEPTHFIRSTSEARCH_H

#include "PathAlgorithm.h"

/**
* @brief Represents a Depth-First Search algorithm approach.
*
* @tparam T Vertex key.
* @tparam V Vertex content.
*/


template<typename T, typename V>
class DepthFirstSearch : public PathAlgorithm<T, V> {
public:

std::set<T> get_path(const Graph<T, V> &graph,
const std::unordered_set<T> &starting_pos,
const std::unordered_set<T> &ending_pos,
std::function<bool(const V &token)> condition) const override;
};

#include "../../src/algortihms/DepthFirstSearch.tpp"

#endif //HEXGAME_DEPTHFIRSTSEARCH_H
26 changes: 26 additions & 0 deletions include/algorithms/PathAlgorithm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef HEXGAME_PATHALGORITHM_H
#define HEXGAME_PATHALGORITHM_H

#include <set>
#include "../common/Graph.h"

template<typename T, typename V>
class PathAlgorithm {
public:

virtual ~PathAlgorithm() = default;

/**
* @brief Finds a path between a nodes.
*
* @param graph Graph object to find the path over.
* @param condition Filtering condition for each node (if any).
* @return Returns a `set` with the founded path, else an empty `set`.
*/
virtual std::set<T> get_path(const Graph<T, V> &graph,
const std::unordered_set<T> &starting_pos,
const std::unordered_set<T> &ending_pos,
std::function<bool(const V &token)> condition) const = 0;
};

#endif //HEXGAME_PATHALGORITHM_H
77 changes: 77 additions & 0 deletions include/common/AppFunctions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#ifndef HEXGAME_APPFUNCTIONS_H
#define HEXGAME_APPFUNCTIONS_H

#include <string>
#include <iostream>
#include <limits>
#include "../utils/GlobalParameters.h"

/**
* @brief Prints a title on the screen.
*
* @param title Title to be displayed and formatted like a menu.
*/
void print_menu_title(const std::string &title);

/**
* @brief Prints a title separator on screen.
*
* @param size The size of the title to used as reference.
*/
void print_menu_title_sep(const int &size);

/**
* @brief Prints a option on the screen.
*
* @param title Subtitle to be displayed and formatted like a menu option.
*/
void print_menu_option(const std::string &option);

/**
* @brief Waits for enter to continue.
*/
void wait_for_enter(const std::string &message);

/**
* @brief Prints a message on the screen.
*
* @param message Message to be displayed.
*/
void print_message(const std::string &message);

/**
* @brief Prints a error message on the screen.
*
* @param message Message to be displayed.
*/
void print_error(const std::string &message);

/**
* @brief Clears console messages.
*/
void clear_console();


/**
* @brief Get an input from the console
*
* @tparam T Type of the input that is expected (casted).
* @param prompt Message to be displayed.
* @return The input with the given type `T`
*/
template<typename T>
T get_input(const std::string &prompt) {
T input;
std::cout << ">> " << prompt << " ";

while (!(std::cin >> input)) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
print_error("Invalid input. Please try again: ");
}

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return input;
}

#endif //HEXGAME_APPFUNCTIONS_H
133 changes: 133 additions & 0 deletions include/common/Graph.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#ifndef HEXGAME_GRAPH_H
#define HEXGAME_GRAPH_H

#include <unordered_map>
#include <unordered_set>
#include <functional>
#include <iostream>
#include <vector>

/**
* @brief A class representing an undirected graph_.
*
* @tparam T The type of the vertex index.
* @tparam V The type of the vertex value.
*/
template<typename T, typename V>
class Graph {
public:
/**
* @brief Constructs a graph_ with optional initial capacity for vertices.
*
* @param initialVertexCapacity The initial capacity for the vertex set.
*/
explicit Graph(std::size_t initialVertexCapacity)
: vertices_(initialVertexCapacity),
adjacency_list_(initialVertexCapacity) {};

/**
* @brief Construct a new Graph object by copying the vertices and adjacency list from an existing graph_.
*
* @param graph The graph_ to be copied.
*/
Graph(const Graph<T, V> &graph) {
// Copy the vertices
for (const auto &vertex: graph.vertices_) {
vertices_[vertex.first] = vertex.second;
}

// Copy the adjacency list
for (const auto &adjacency: graph.adjacency_list_) {
adjacency_list_[adjacency.first] = adjacency.second;
}
}

/**
* @brief Adds a vertex with content to the graph_.
*
* @param vertex The vertex to be added.
* @param content The content associated with the vertex.
*/
void add_node(const T &vertex, const V &content);

/**
* @brief Adds an edge between two vertices in the graph_.
* The graph_ is undirected, so the edge is bidirectional.
*
* @param vertex1 The first vertex of the edge.
* @param vertex2 The second vertex of the edge.
*/
void add_edge(const T &vertex1, const T &vertex2);

/**
* @brief Checks if a vertex exists in the graph_.
*
* @param vertex The vertex to check.
* @return `true` if the vertex exists, `false` otherwise.
*/
bool has_node(const T &vertex) const;

/**
* @brief Checks if an edge exists between two vertices in the graph_.
*
* @param vertex1 The first vertex of the edge.
* @param vertex2 The second vertex of the edge.
* @return `true` if the edge exists, `false` otherwise.
*/
bool has_edge(const T &vertex1, const T &vertex2) const;

/**
* @brief Gets the content of a vertex.
* @param vertex The vertex to get content.
* @return The content of a vertex.
*/
const V &get_node(const T &vertex) const;

/**
* @brief Sets the content of a vertex.
* @param vertex The vertex to set content.
* @param content Content of the vertex.
*/
void update_node(const T &vertex, const V &content);

/**
* @brief Retrieves the adjacency list of a given vertex.
* @param vertex The vertex for which to retrieve the adjacency list.
* @return A reference to the adjacency list of the specified vertex.
*/
const std::unordered_set<T> &get_adjacency_list(const T &vertex) const;


/**
* @brief Overloaded stream insertion operator for the `Graph` class.
*
* This operator allows the Graph class to be printed to an output stream.
* It prints the vertices and their content, as well as the adjacency list
* of each vertex.
*
* @param out The output stream to print the graph_ to.
* @param graph The Graph object to be printed.
* @return A reference to the output stream after printing the graph_.
*/
friend std::ostream &operator<<(std::ostream &out, const Graph<T, V> &graph) {
for (const auto &vertex: graph.vertices_) {
out << "Vertex: " << vertex.first << ", Content: " << static_cast<int>(vertex.second) << '\n';
if (graph.adjacency_list_.count(vertex.first) > 0) {
out << "Adjacency List: ";
for (const auto &neighbor: graph.adjacency_list_.at(vertex.first)) {
out << neighbor << ' ';
}
out << '\n';
}
}
return out;
}

private:
std::unordered_map<T, V> vertices_; /** Map of vertices and their content. */
std::unordered_map<T, std::unordered_set<T>> adjacency_list_; /** Adjacency list representation of the graph_. */
};

#include "../../src/common/Graph.tpp"

#endif //HEXGAME_GRAPH_H
13 changes: 13 additions & 0 deletions include/enums/CompiledOS.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef HEXGAME_COMPILEDOS_H
#define HEXGAME_COMPILEDOS_H

/**
* @brief Class that is used to define different OS environments.
*/
enum class CompiledOS {
WINDOWS = 0,
LINUX = 1,
MAC = 2
};

#endif //HEXGAME_COMPILEDOS_H
30 changes: 30 additions & 0 deletions include/enums/PlayerToken.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef HEXGAME_PLAYERTOKEN_H
#define HEXGAME_PLAYERTOKEN_H

#include <string>

/**
* @brief Represents a owner token.
*/
enum class PlayerToken {
NONE = 0,
PLAYER = 1,
AI = 2,
};

class PlayerTokenHandler {
public:
static std::string to_string(PlayerToken token) {
switch (token) {
case PlayerToken::PLAYER:
return "PLAYER";
case PlayerToken::AI:
return "AI";
default:
return "NONE";
}
}
};


#endif //HEXGAME_PLAYERTOKEN_H
19 changes: 19 additions & 0 deletions include/enums/PlayingSide.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef HEXGAME_PLAYINGSIDE_H
#define HEXGAME_PLAYINGSIDE_H

#include <string>

enum class PlayingSide {
HORIZONTAL = 0,
VERTICAL = 1
};

class PlayingSideHandler {
public:
static std::string to_string(PlayingSide player_side) {
return player_side == PlayingSide::HORIZONTAL ? "HORIZONTAL" : "VERTICAL";
}
};


#endif //HEXGAME_PLAYINGSIDE_H
Loading

0 comments on commit 1e602d2

Please sign in to comment.