diff --git a/shenzhen_solitaire/c++/CMakeLists.txt b/shenzhen_solitaire/c++/CMakeLists.txt index de200d7..89b9c8c 100644 --- a/shenzhen_solitaire/c++/CMakeLists.txt +++ b/shenzhen_solitaire/c++/CMakeLists.txt @@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") include( "common" ) -add_library(board STATIC lib/board.cpp) +add_library(board STATIC lib/board.cpp lib/card.cpp lib/goal.cpp) set_property(TARGET board PROPERTY CXX_STANDARD 17) -target_include_directories(board PUBLIC include) \ No newline at end of file +target_include_directories(board PUBLIC include) +add_subdirectory(auxiliary) \ No newline at end of file diff --git a/shenzhen_solitaire/c++/auxiliary/CMakeLists.txt b/shenzhen_solitaire/c++/auxiliary/CMakeLists.txt new file mode 100644 index 0000000..88a686c --- /dev/null +++ b/shenzhen_solitaire/c++/auxiliary/CMakeLists.txt @@ -0,0 +1,12 @@ +find_package(SWIG REQUIRED) +include(${SWIG_USE_FILE}) + +find_package(PythonLibs REQUIRED) + +set_property(SOURCE swig.i PROPERTY CPLUSPLUS ON) +swig_add_library(shenzhen_python TYPE SHARED LANGUAGE PYTHON SOURCES swig.i) + +target_include_directories(shenzhen_python PUBLIC ${PYTHON_INCLUDE_PATH}) +target_link_libraries(shenzhen_python PUBLIC board) + +set_property(TARGET shenzhen_python PROPERTY CXX_STANDARD 17) diff --git a/shenzhen_solitaire/c++/auxiliary/swig.i b/shenzhen_solitaire/c++/auxiliary/swig.i new file mode 100644 index 0000000..0d36755 --- /dev/null +++ b/shenzhen_solitaire/c++/auxiliary/swig.i @@ -0,0 +1,54 @@ +%module shenzhen +%{ + #include "board.hpp" + #include "card.hpp" + #include "goal.hpp" +%} + +namespace solitaire { +enum class CardType : int { Zhong, Bai, Fa, Hua, Red, Green, Black }; + +auto isNormalCardType(CardType type) -> bool; + +struct Card { + CardType type; + int value; + auto toString() const noexcept -> std::string; +}; + +class Goal { + std::array, 3> goal{}; + auto getEmptyId() -> std::optional; + +public: + auto getId(CardType suit) const noexcept -> std::optional; + auto get(CardType suit) const noexcept -> std::optional; + + void set(CardType suit, int value) noexcept; + void inc(CardType suit) noexcept; +}; + +struct BunkerField { + std::optional card; + bool empty{}; + bool closed{}; +}; + +inline constexpr int MAX_ROW_SIZE = 13; +inline constexpr int MAX_COLUMN_SIZE = 8; + +class Stack { + std::array, MAX_COLUMN_SIZE> values{}; +}; + +struct Board { + std::array field{}; + std::array bunker{}; + Goal goal{}; + bool flower_gone{}; + + auto solved() const noexcept -> bool; + auto hash() const noexcept -> std::size_t; + auto correct() const noexcept -> bool; +}; +} \ No newline at end of file diff --git a/shenzhen_solitaire/c++/include/board.hpp b/shenzhen_solitaire/c++/include/board.hpp index 9cd1589..2a7c05b 100644 --- a/shenzhen_solitaire/c++/include/board.hpp +++ b/shenzhen_solitaire/c++/include/board.hpp @@ -1,27 +1,35 @@ +#pragma once +#include "card.hpp" +#include "goal.hpp" + #include +#include #include namespace solitaire { -class Card { - bool isNormalCard(); - bool isSpecialCard(); + +struct BunkerField { + std::optional card; + bool empty{}; + bool closed{}; }; -struct BunkerField{ - Card card; - bool empty; - bool closed; +inline constexpr int MAX_ROW_SIZE = 13; +inline constexpr int MAX_COLUMN_SIZE = 8; + +class Stack { + std::array, MAX_COLUMN_SIZE> values{}; }; -class Board { -public: - static constexpr int MAX_ROW_SIZE = 13; - static constexpr int MAX_COLUMN_SIZE = 8; +struct Board { + std::array field{}; + std::array bunker{}; + Goal goal{}; + bool flower_gone{}; -private: - std::array, MAX_ROW_SIZE> field; - std::array bunker; - std::array, 3> goal; - bool flower_gone; + [[nodiscard]] auto solved() const noexcept -> bool; + [[nodiscard]] auto hash() const noexcept -> std::size_t; + [[nodiscard]] auto correct() const noexcept -> bool; }; + } // namespace solitaire \ No newline at end of file diff --git a/shenzhen_solitaire/c++/include/card.hpp b/shenzhen_solitaire/c++/include/card.hpp new file mode 100644 index 0000000..51e1aba --- /dev/null +++ b/shenzhen_solitaire/c++/include/card.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +namespace solitaire { +enum class CardType : int { Zhong, Bai, Fa, Hua, Red, Green, Black }; + +auto isNormalCardType(CardType type) -> bool; + +struct Card { + CardType type; + int value; + [[nodiscard]] auto toString() const noexcept -> std::string; +}; +} // namespace solitaire \ No newline at end of file diff --git a/shenzhen_solitaire/c++/include/goal.hpp b/shenzhen_solitaire/c++/include/goal.hpp new file mode 100644 index 0000000..ec37f44 --- /dev/null +++ b/shenzhen_solitaire/c++/include/goal.hpp @@ -0,0 +1,20 @@ + +#pragma once +#include "card.hpp" + +#include +#include + +namespace solitaire { +class Goal { + std::array, 3> goal{}; + auto getEmptyId() -> std::optional; + +public: + [[nodiscard]] auto getId(CardType suit) const noexcept -> std::optional; + [[nodiscard]] auto get(CardType suit) const noexcept -> std::optional; + + void set(CardType suit, int value) noexcept; + void inc(CardType suit) noexcept; +}; +} // namespace solitaire \ No newline at end of file diff --git a/shenzhen_solitaire/c++/lib/card.cpp b/shenzhen_solitaire/c++/lib/card.cpp new file mode 100644 index 0000000..e7e00dc --- /dev/null +++ b/shenzhen_solitaire/c++/lib/card.cpp @@ -0,0 +1,15 @@ +#include "card.hpp" +namespace solitaire { +auto +isNormalCardType(CardType type) -> bool { + switch (type) { + case CardType::Red: + case CardType::Green: + case CardType::Black: + return true; + break; + default: + return false; + } +} +} // namespace solitaire diff --git a/shenzhen_solitaire/c++/lib/goal.cpp b/shenzhen_solitaire/c++/lib/goal.cpp new file mode 100644 index 0000000..dc4895c --- /dev/null +++ b/shenzhen_solitaire/c++/lib/goal.cpp @@ -0,0 +1,66 @@ + +#include "goal.hpp" + +namespace solitaire { +auto +Goal::getEmptyId() -> std::optional { + int counter = 0; + for (const auto& slot : goal) { + if (!slot) { + return counter; + } + ++counter; + } + return std::nullopt; +} + +[[nodiscard]] auto +Goal::getId(CardType suit) const noexcept -> std::optional { + int counter = 0; + for (const auto& slot : goal) { + if (slot && slot->type == suit) { + return counter; + } + ++counter; + } + return std::nullopt; +} + +[[nodiscard]] auto +Goal::get(CardType suit) const noexcept -> std::optional { + if (auto index = getId(suit); index) { + return goal[*index]->value; + } + return std::nullopt; +} + +void +Goal::set(CardType suit, int value) noexcept { + assert(value >= 0); + assert(value <= 9); + + const auto card = [&]() -> std::optional { + if (value == 0) { + return std::nullopt; + } + return Card{suit, value}; + }(); + + const int goal_index = [&]() -> int { + if (auto index = getId(suit); index) { + return *index; + } + return *getEmptyId(); + }(); + + goal[goal_index] = card; +} + +void +Goal::inc(CardType suit) noexcept { + auto get_value = get(suit); + int new_value = get_value ? (*get_value) + 1 : 1; + set(suit, new_value); +} + +} // namespace solitaire \ No newline at end of file