├── .gitignore ├── Gobang ├── Gobang.pro ├── data │ ├── cache │ │ └── latest_server.json │ └── environment.json ├── inc │ └── json │ │ ├── json │ │ ├── allocator.h │ │ ├── assertions.h │ │ ├── autolink.h │ │ ├── config.h │ │ ├── forwards.h │ │ ├── json.h │ │ ├── json_features.h │ │ ├── reader.h │ │ ├── value.h │ │ ├── version.h │ │ └── writer.h │ │ ├── json_reader.cpp │ │ ├── json_tool.h │ │ ├── json_value.cpp │ │ ├── json_valueiterator.inl │ │ └── json_writer.cpp ├── res │ ├── bgcolor.png │ ├── black.png │ ├── color-palette.ico │ ├── copy.ico │ ├── disconnect.png │ ├── exchange.ico │ ├── paste.ico │ ├── preparing.png │ ├── reset.ico │ ├── reset_defalut.png │ ├── screenshot.ico │ ├── select-file.ico │ ├── setting.ico │ └── white.png └── src │ ├── chess │ ├── base.cpp │ ├── base.h │ ├── chessboard.cpp │ ├── chessboard.h │ ├── chessboardvs.cpp │ ├── chessboardvs.h │ └── player.h │ ├── dialog │ ├── chessonline.cpp │ ├── chessonline.h │ ├── createroomdialog.cpp │ ├── createroomdialog.h │ ├── imagecropperdialog.h │ ├── joinroomdialog.cpp │ ├── joinroomdialog.h │ ├── settingpanel.cpp │ ├── settingpanel.h │ ├── watchchessonline.cpp │ └── watchchessonline.h │ ├── environment.cpp │ ├── environment.h │ ├── main.cpp │ ├── mainwindow.cpp │ ├── mainwindow.h │ ├── network │ ├── api.cpp │ ├── api.h │ ├── client.cpp │ └── client.h │ └── widget │ ├── chathistory.cpp │ ├── chathistory.h │ ├── chatinput.cpp │ ├── chatinput.h │ ├── imagecropperlabel.cpp │ └── imagecropperlabel.h ├── GobangServer ├── src │ ├── api.cpp │ ├── api.h │ ├── base.cpp │ ├── base.h │ ├── gobangserver.cpp │ ├── gobangserver.h │ ├── jsoncpp │ │ ├── json │ │ │ ├── allocator.h │ │ │ ├── assertions.h │ │ │ ├── autolink.h │ │ │ ├── config.h │ │ │ ├── forwards.h │ │ │ ├── json.h │ │ │ ├── json_features.h │ │ │ ├── reader.h │ │ │ ├── value.h │ │ │ ├── version.h │ │ │ └── writer.h │ │ ├── json_reader.cpp │ │ ├── json_tool.h │ │ ├── json_value.cpp │ │ ├── json_valueiterator.inl │ │ └── json_writer.cpp │ ├── main.cpp │ ├── player.h │ ├── room.cpp │ ├── room.h │ ├── socket_func.cpp │ ├── socket_func.h │ └── thread_pool.h └── xmake.lua ├── README.md └── assets └── README ├── 001.png ├── 002.png ├── 003.png └── 004.png /.gitignore: -------------------------------------------------------------------------------- 1 | GobangServer/build 2 | GobangServer/.xmake 3 | Gobang/build 4 | -------------------------------------------------------------------------------- /Gobang/Gobang.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | CONFIG += c++11 6 | 7 | # The following define makes your compiler emit warnings if you use 8 | # any Qt feature that has been marked deprecated (the exact warnings 9 | # depend on your compiler). Please consult the documentation of the 10 | # deprecated API in order to know how to port your code away from it. 11 | DEFINES += QT_DEPRECATED_WARNINGS 12 | 13 | # You can also make your code fail to compile if it uses deprecated APIs. 14 | # In order to do so, uncomment the following line. 15 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 16 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 17 | 18 | #win32 { 19 | # LIBS += -lpthread libwsock32 libws2_32 20 | #} 21 | 22 | # jsoncpp 1.9.2 23 | INCLUDEPATH += inc/json 24 | 25 | SOURCES += \ 26 | inc/json/json_reader.cpp \ 27 | inc/json/json_value.cpp \ 28 | inc/json/json_writer.cpp \ 29 | src/chess/base.cpp \ 30 | src/chess/chessboard.cpp \ 31 | src/chess/chessboardvs.cpp \ 32 | src/dialog/chessonline.cpp \ 33 | src/dialog/createroomdialog.cpp \ 34 | src/dialog/joinroomdialog.cpp \ 35 | src/dialog/settingpanel.cpp \ 36 | src/dialog/watchchessonline.cpp \ 37 | src/environment.cpp \ 38 | src/main.cpp \ 39 | src/mainwindow.cpp \ 40 | src/network/api.cpp \ 41 | src/network/client.cpp \ 42 | src/widget/chathistory.cpp \ 43 | src/widget/chatinput.cpp \ 44 | src/widget/imagecropperlabel.cpp 45 | 46 | HEADERS += \ 47 | inc/json/json/allocator.h \ 48 | inc/json/json/assertions.h \ 49 | inc/json/json/autolink.h \ 50 | inc/json/json/config.h \ 51 | inc/json/json/forwards.h \ 52 | inc/json/json/json.h \ 53 | inc/json/json/json_features.h \ 54 | inc/json/json/reader.h \ 55 | inc/json/json/value.h \ 56 | inc/json/json/version.h \ 57 | inc/json/json/writer.h \ 58 | inc/json/json_tool.h \ 59 | inc/json/json_valueiterator.inl \ 60 | src/chess/base.h \ 61 | src/chess/chessboard.h \ 62 | src/chess/chessboardvs.h \ 63 | src/chess/player.h \ 64 | src/dialog/chessonline.h \ 65 | src/dialog/createroomdialog.h \ 66 | src/dialog/imagecropperdialog.h \ 67 | src/dialog/joinroomdialog.h \ 68 | src/dialog/settingpanel.h \ 69 | src/dialog/watchchessonline.h \ 70 | src/environment.h \ 71 | src/mainwindow.h \ 72 | src/network/api.h \ 73 | src/network/client.h \ 74 | src/widget/chathistory.h \ 75 | src/widget/chatinput.h \ 76 | src/widget/imagecropperlabel.h 77 | 78 | # Default rules for deployment. 79 | qnx: target.path = /tmp/$${TARGET}/bin 80 | else: unix:!android: target.path = /opt/$${TARGET}/bin 81 | !isEmpty(target.path): INSTALLS += target 82 | -------------------------------------------------------------------------------- /Gobang/data/cache/latest_server.json: -------------------------------------------------------------------------------- 1 | { 2 | "server_ip" : "120.76.56.226", 3 | "server_port" : "10032" 4 | } 5 | -------------------------------------------------------------------------------- /Gobang/data/environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "BG_COLOR" : 4291335780, 3 | "BG_TRANSPARENT" : 220, 4 | "BG_TYPE" : 1, 5 | "NAME" : "Leopard-C" 6 | } 7 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/allocator.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED 7 | #define CPPTL_JSON_ALLOCATOR_H_INCLUDED 8 | 9 | #include 10 | #include 11 | 12 | #pragma pack(push, 8) 13 | 14 | namespace Json { 15 | template class SecureAllocator { 16 | public: 17 | // Type definitions 18 | using value_type = T; 19 | using pointer = T*; 20 | using const_pointer = const T*; 21 | using reference = T&; 22 | using const_reference = const T&; 23 | using size_type = std::size_t; 24 | using difference_type = std::ptrdiff_t; 25 | 26 | /** 27 | * Allocate memory for N items using the standard allocator. 28 | */ 29 | pointer allocate(size_type n) { 30 | // allocate using "global operator new" 31 | return static_cast(::operator new(n * sizeof(T))); 32 | } 33 | 34 | /** 35 | * Release memory which was allocated for N items at pointer P. 36 | * 37 | * The memory block is filled with zeroes before being released. 38 | * The pointer argument is tagged as "volatile" to prevent the 39 | * compiler optimizing out this critical step. 40 | */ 41 | void deallocate(volatile pointer p, size_type n) { 42 | std::memset(p, 0, n * sizeof(T)); 43 | // free using "global operator delete" 44 | ::operator delete(p); 45 | } 46 | 47 | /** 48 | * Construct an item in-place at pointer P. 49 | */ 50 | template void construct(pointer p, Args&&... args) { 51 | // construct using "placement new" and "perfect forwarding" 52 | ::new (static_cast(p)) T(std::forward(args)...); 53 | } 54 | 55 | size_type max_size() const { return size_t(-1) / sizeof(T); } 56 | 57 | pointer address(reference x) const { return std::addressof(x); } 58 | 59 | const_pointer address(const_reference x) const { return std::addressof(x); } 60 | 61 | /** 62 | * Destroy an item in-place at pointer P. 63 | */ 64 | void destroy(pointer p) { 65 | // destroy using "explicit destructor" 66 | p->~T(); 67 | } 68 | 69 | // Boilerplate 70 | SecureAllocator() {} 71 | template SecureAllocator(const SecureAllocator&) {} 72 | template struct rebind { using other = SecureAllocator; }; 73 | }; 74 | 75 | template 76 | bool operator==(const SecureAllocator&, const SecureAllocator&) { 77 | return true; 78 | } 79 | 80 | template 81 | bool operator!=(const SecureAllocator&, const SecureAllocator&) { 82 | return false; 83 | } 84 | 85 | } // namespace Json 86 | 87 | #pragma pack(pop) 88 | 89 | #endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED 90 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/assertions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED 7 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED 8 | 9 | #include 10 | #include 11 | 12 | #if !defined(JSON_IS_AMALGAMATION) 13 | #include "config.h" 14 | #endif // if !defined(JSON_IS_AMALGAMATION) 15 | 16 | /** It should not be possible for a maliciously designed file to 17 | * cause an abort() or seg-fault, so these macros are used only 18 | * for pre-condition violations and internal logic errors. 19 | */ 20 | #if JSON_USE_EXCEPTION 21 | 22 | // @todo <= add detail about condition in exception 23 | #define JSON_ASSERT(condition) \ 24 | { \ 25 | if (!(condition)) { \ 26 | Json::throwLogicError("assert json failed"); \ 27 | } \ 28 | } 29 | 30 | #define JSON_FAIL_MESSAGE(message) \ 31 | { \ 32 | OStringStream oss; \ 33 | oss << message; \ 34 | Json::throwLogicError(oss.str()); \ 35 | abort(); \ 36 | } 37 | 38 | #else // JSON_USE_EXCEPTION 39 | 40 | #define JSON_ASSERT(condition) assert(condition) 41 | 42 | // The call to assert() will show the failure message in debug builds. In 43 | // release builds we abort, for a core-dump or debugger. 44 | #define JSON_FAIL_MESSAGE(message) \ 45 | { \ 46 | OStringStream oss; \ 47 | oss << message; \ 48 | assert(false && oss.str().c_str()); \ 49 | abort(); \ 50 | } 51 | 52 | #endif 53 | 54 | #define JSON_ASSERT_MESSAGE(condition, message) \ 55 | if (!(condition)) { \ 56 | JSON_FAIL_MESSAGE(message); \ 57 | } 58 | 59 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED 60 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/autolink.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_AUTOLINK_H_INCLUDED 7 | #define JSON_AUTOLINK_H_INCLUDED 8 | 9 | #include "config.h" 10 | 11 | #ifdef JSON_IN_CPPTL 12 | #include 13 | #endif 14 | 15 | #if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ 16 | !defined(JSON_IN_CPPTL) 17 | #define CPPTL_AUTOLINK_NAME "json" 18 | #undef CPPTL_AUTOLINK_DLL 19 | #ifdef JSON_DLL 20 | #define CPPTL_AUTOLINK_DLL 21 | #endif 22 | #include "autolink.h" 23 | #endif 24 | 25 | #endif // JSON_AUTOLINK_H_INCLUDED 26 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_CONFIG_H_INCLUDED 7 | #define JSON_CONFIG_H_INCLUDED 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /// If defined, indicates that json library is embedded in CppTL library. 18 | //# define JSON_IN_CPPTL 1 19 | 20 | /// If defined, indicates that json may leverage CppTL library 21 | //# define JSON_USE_CPPTL 1 22 | /// If defined, indicates that cpptl vector based map should be used instead of 23 | /// std::map 24 | /// as Value container. 25 | //# define JSON_USE_CPPTL_SMALLMAP 1 26 | 27 | // If non-zero, the library uses exceptions to report bad input instead of C 28 | // assertion macros. The default is to use exceptions. 29 | #ifndef JSON_USE_EXCEPTION 30 | #define JSON_USE_EXCEPTION 1 31 | #endif 32 | 33 | // Temporary, tracked for removal with issue #982. 34 | #ifndef JSON_USE_NULLREF 35 | #define JSON_USE_NULLREF 1 36 | #endif 37 | 38 | /// If defined, indicates that the source file is amalgamated 39 | /// to prevent private header inclusion. 40 | /// Remarks: it is automatically defined in the generated amalgamated header. 41 | // #define JSON_IS_AMALGAMATION 42 | 43 | #ifdef JSON_IN_CPPTL 44 | #include 45 | #ifndef JSON_USE_CPPTL 46 | #define JSON_USE_CPPTL 1 47 | #endif 48 | #endif 49 | 50 | #ifdef JSON_IN_CPPTL 51 | #define JSON_API CPPTL_API 52 | #elif defined(JSON_DLL_BUILD) 53 | #if defined(_MSC_VER) || defined(__MINGW32__) 54 | #define JSON_API __declspec(dllexport) 55 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 56 | #elif defined(__GNUC__) || defined(__clang__) 57 | #define JSON_API __attribute__((visibility("default"))) 58 | #endif // if defined(_MSC_VER) 59 | #elif defined(JSON_DLL) 60 | #if defined(_MSC_VER) || defined(__MINGW32__) 61 | #define JSON_API __declspec(dllimport) 62 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 63 | #endif // if defined(_MSC_VER) 64 | #endif // ifdef JSON_IN_CPPTL 65 | #if !defined(JSON_API) 66 | #define JSON_API 67 | #endif 68 | 69 | #if defined(_MSC_VER) && _MSC_VER < 1800 70 | #error \ 71 | "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" 72 | #endif 73 | 74 | #if defined(_MSC_VER) && _MSC_VER < 1900 75 | // As recommended at 76 | // https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 77 | extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, 78 | const char* format, ...); 79 | #define jsoncpp_snprintf msvc_pre1900_c99_snprintf 80 | #else 81 | #define jsoncpp_snprintf std::snprintf 82 | #endif 83 | 84 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 85 | // integer 86 | // Storages, and 64 bits integer support is disabled. 87 | // #define JSON_NO_INT64 1 88 | 89 | // JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. 90 | // C++11 should be used directly in JSONCPP. 91 | #define JSONCPP_OVERRIDE override 92 | 93 | #if __cplusplus >= 201103L 94 | #define JSONCPP_NOEXCEPT noexcept 95 | #define JSONCPP_OP_EXPLICIT explicit 96 | #elif defined(_MSC_VER) && _MSC_VER < 1900 97 | #define JSONCPP_NOEXCEPT throw() 98 | #define JSONCPP_OP_EXPLICIT explicit 99 | #elif defined(_MSC_VER) && _MSC_VER >= 1900 100 | #define JSONCPP_NOEXCEPT noexcept 101 | #define JSONCPP_OP_EXPLICIT explicit 102 | #else 103 | #define JSONCPP_NOEXCEPT throw() 104 | #define JSONCPP_OP_EXPLICIT 105 | #endif 106 | 107 | #ifdef __clang__ 108 | #if __has_extension(attribute_deprecated_with_message) 109 | #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) 110 | #endif 111 | #elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) 112 | #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) 113 | #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) 114 | #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) 115 | #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) 116 | #endif // GNUC version 117 | #elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates 118 | // MSVC) 119 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 120 | #endif // __clang__ || __GNUC__ || _MSC_VER 121 | 122 | #if !defined(JSONCPP_DEPRECATED) 123 | #define JSONCPP_DEPRECATED(message) 124 | #endif // if !defined(JSONCPP_DEPRECATED) 125 | 126 | #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) 127 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 128 | #endif 129 | 130 | #if !defined(JSON_IS_AMALGAMATION) 131 | 132 | #include "allocator.h" 133 | #include "version.h" 134 | 135 | #endif // if !defined(JSON_IS_AMALGAMATION) 136 | 137 | namespace Json { 138 | typedef int Int; 139 | typedef unsigned int UInt; 140 | #if defined(JSON_NO_INT64) 141 | typedef int LargestInt; 142 | typedef unsigned int LargestUInt; 143 | #undef JSON_HAS_INT64 144 | #else // if defined(JSON_NO_INT64) 145 | // For Microsoft Visual use specific types as long long is not supported 146 | #if defined(_MSC_VER) // Microsoft Visual Studio 147 | typedef __int64 Int64; 148 | typedef unsigned __int64 UInt64; 149 | #else // if defined(_MSC_VER) // Other platforms, use long long 150 | typedef int64_t Int64; 151 | typedef uint64_t UInt64; 152 | #endif // if defined(_MSC_VER) 153 | typedef Int64 LargestInt; 154 | typedef UInt64 LargestUInt; 155 | #define JSON_HAS_INT64 156 | #endif // if defined(JSON_NO_INT64) 157 | 158 | template 159 | using Allocator = 160 | typename std::conditional, 161 | std::allocator>::type; 162 | using String = std::basic_string, Allocator>; 163 | using IStringStream = 164 | std::basic_istringstream; 166 | using OStringStream = 167 | std::basic_ostringstream; 169 | using IStream = std::istream; 170 | using OStream = std::ostream; 171 | } // namespace Json 172 | 173 | // Legacy names (formerly macros). 174 | using JSONCPP_STRING = Json::String; 175 | using JSONCPP_ISTRINGSTREAM = Json::IStringStream; 176 | using JSONCPP_OSTRINGSTREAM = Json::OStringStream; 177 | using JSONCPP_ISTREAM = Json::IStream; 178 | using JSONCPP_OSTREAM = Json::OStream; 179 | 180 | #endif // JSON_CONFIG_H_INCLUDED 181 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/forwards.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_FORWARDS_H_INCLUDED 7 | #define JSON_FORWARDS_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "config.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | namespace Json { 14 | 15 | // writer.h 16 | class StreamWriter; 17 | class StreamWriterBuilder; 18 | class Writer; 19 | class FastWriter; 20 | class StyledWriter; 21 | class StyledStreamWriter; 22 | 23 | // reader.h 24 | class Reader; 25 | class CharReader; 26 | class CharReaderBuilder; 27 | 28 | // json_features.h 29 | class Features; 30 | 31 | // value.h 32 | typedef unsigned int ArrayIndex; 33 | class StaticString; 34 | class Path; 35 | class PathArgument; 36 | class Value; 37 | class ValueIteratorBase; 38 | class ValueIterator; 39 | class ValueConstIterator; 40 | 41 | } // namespace Json 42 | 43 | #endif // JSON_FORWARDS_H_INCLUDED 44 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/json.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_JSON_H_INCLUDED 7 | #define JSON_JSON_H_INCLUDED 8 | 9 | #include "autolink.h" 10 | #include "json_features.h" 11 | #include "reader.h" 12 | #include "value.h" 13 | #include "writer.h" 14 | 15 | #endif // JSON_JSON_H_INCLUDED 16 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/json_features.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED 7 | #define CPPTL_JSON_FEATURES_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "forwards.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | #pragma pack(push, 8) 14 | 15 | namespace Json { 16 | 17 | /** \brief Configuration passed to reader and writer. 18 | * This configuration object can be used to force the Reader or Writer 19 | * to behave in a standard conforming way. 20 | */ 21 | class JSON_API Features { 22 | public: 23 | /** \brief A configuration that allows all features and assumes all strings 24 | * are UTF-8. 25 | * - C & C++ comments are allowed 26 | * - Root object can be any JSON value 27 | * - Assumes Value strings are encoded in UTF-8 28 | */ 29 | static Features all(); 30 | 31 | /** \brief A configuration that is strictly compatible with the JSON 32 | * specification. 33 | * - Comments are forbidden. 34 | * - Root object must be either an array or an object value. 35 | * - Assumes Value strings are encoded in UTF-8 36 | */ 37 | static Features strictMode(); 38 | 39 | /** \brief Initialize the configuration like JsonConfig::allFeatures; 40 | */ 41 | Features(); 42 | 43 | /// \c true if comments are allowed. Default: \c true. 44 | bool allowComments_{true}; 45 | 46 | /// \c true if root must be either an array or an object value. Default: \c 47 | /// false. 48 | bool strictRoot_{false}; 49 | 50 | /// \c true if dropped null placeholders are allowed. Default: \c false. 51 | bool allowDroppedNullPlaceholders_{false}; 52 | 53 | /// \c true if numeric object key are allowed. Default: \c false. 54 | bool allowNumericKeys_{false}; 55 | }; 56 | 57 | } // namespace Json 58 | 59 | #pragma pack(pop) 60 | 61 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED 62 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/version.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_VERSION_H_INCLUDED 2 | #define JSON_VERSION_H_INCLUDED 3 | 4 | // Note: version must be updated in three places when doing a release. This 5 | // annoying process ensures that amalgamate, CMake, and meson all report the 6 | // correct version. 7 | // 1. /meson.build 8 | // 2. /include/json/version.h 9 | // 3. /CMakeLists.txt 10 | // IMPORTANT: also update the SOVERSION!! 11 | 12 | #define JSONCPP_VERSION_STRING "1.9.2" 13 | #define JSONCPP_VERSION_MAJOR 1 14 | #define JSONCPP_VERSION_MINOR 9 15 | #define JSONCPP_VERSION_PATCH 2 16 | #define JSONCPP_VERSION_QUALIFIER 17 | #define JSONCPP_VERSION_HEXA \ 18 | ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ 19 | (JSONCPP_VERSION_PATCH << 8)) 20 | 21 | #ifdef JSONCPP_USING_SECURE_MEMORY 22 | #undef JSONCPP_USING_SECURE_MEMORY 23 | #endif 24 | #define JSONCPP_USING_SECURE_MEMORY 0 25 | // If non-zero, the library zeroes any memory that it has allocated before 26 | // it frees its memory. 27 | 28 | #endif // JSON_VERSION_H_INCLUDED 29 | -------------------------------------------------------------------------------- /Gobang/inc/json/json/writer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_WRITER_H_INCLUDED 7 | #define JSON_WRITER_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "value.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | #include 13 | #include 14 | #include 15 | 16 | // Disable warning C4251: : needs to have dll-interface to 17 | // be used by... 18 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) 19 | #pragma warning(push) 20 | #pragma warning(disable : 4251) 21 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 22 | 23 | #pragma pack(push, 8) 24 | 25 | namespace Json { 26 | 27 | class Value; 28 | 29 | /** 30 | * 31 | * Usage: 32 | * \code 33 | * using namespace Json; 34 | * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) 35 | * { std::unique_ptr const writer( factory.newStreamWriter()); 36 | * writer->write(value, &std::cout); 37 | * std::cout << std::endl; // add lf and flush 38 | * } 39 | * \endcode 40 | */ 41 | class JSON_API StreamWriter { 42 | protected: 43 | OStream* sout_; // not owned; will not delete 44 | public: 45 | StreamWriter(); 46 | virtual ~StreamWriter(); 47 | /** Write Value into document as configured in sub-class. 48 | * Do not take ownership of sout, but maintain a reference during function. 49 | * \pre sout != NULL 50 | * \return zero on success (For now, we always return zero, so check the 51 | * stream instead.) \throw std::exception possibly, depending on 52 | * configuration 53 | */ 54 | virtual int write(Value const& root, OStream* sout) = 0; 55 | 56 | /** \brief A simple abstract factory. 57 | */ 58 | class JSON_API Factory { 59 | public: 60 | virtual ~Factory(); 61 | /** \brief Allocate a CharReader via operator new(). 62 | * \throw std::exception if something goes wrong (e.g. invalid settings) 63 | */ 64 | virtual StreamWriter* newStreamWriter() const = 0; 65 | }; // Factory 66 | }; // StreamWriter 67 | 68 | /** \brief Write into stringstream, then return string, for convenience. 69 | * A StreamWriter will be created from the factory, used, and then deleted. 70 | */ 71 | String JSON_API writeString(StreamWriter::Factory const& factory, 72 | Value const& root); 73 | 74 | /** \brief Build a StreamWriter implementation. 75 | 76 | * Usage: 77 | * \code 78 | * using namespace Json; 79 | * Value value = ...; 80 | * StreamWriterBuilder builder; 81 | * builder["commentStyle"] = "None"; 82 | * builder["indentation"] = " "; // or whatever you like 83 | * std::unique_ptr writer( 84 | * builder.newStreamWriter()); 85 | * writer->write(value, &std::cout); 86 | * std::cout << std::endl; // add lf and flush 87 | * \endcode 88 | */ 89 | class JSON_API StreamWriterBuilder : public StreamWriter::Factory { 90 | public: 91 | // Note: We use a Json::Value so that we can add data-members to this class 92 | // without a major version bump. 93 | /** Configuration of this builder. 94 | * Available settings (case-sensitive): 95 | * - "commentStyle": "None" or "All" 96 | * - "indentation": "". 97 | * - Setting this to an empty string also omits newline characters. 98 | * - "enableYAMLCompatibility": false or true 99 | * - slightly change the whitespace around colons 100 | * - "dropNullPlaceholders": false or true 101 | * - Drop the "null" string from the writer's output for nullValues. 102 | * Strictly speaking, this is not valid JSON. But when the output is being 103 | * fed to a browser's JavaScript, it makes for smaller output and the 104 | * browser can handle the output just fine. 105 | * - "useSpecialFloats": false or true 106 | * - If true, outputs non-finite floating point values in the following way: 107 | * NaN values as "NaN", positive infinity as "Infinity", and negative 108 | * infinity as "-Infinity". 109 | * - "precision": int 110 | * - Number of precision digits for formatting of real values. 111 | * - "precisionType": "significant"(default) or "decimal" 112 | * - Type of precision for formatting of real values. 113 | 114 | * You can examine 'settings_` yourself 115 | * to see the defaults. You can also write and read them just like any 116 | * JSON Value. 117 | * \sa setDefaults() 118 | */ 119 | Json::Value settings_; 120 | 121 | StreamWriterBuilder(); 122 | ~StreamWriterBuilder() override; 123 | 124 | /** 125 | * \throw std::exception if something goes wrong (e.g. invalid settings) 126 | */ 127 | StreamWriter* newStreamWriter() const override; 128 | 129 | /** \return true if 'settings' are legal and consistent; 130 | * otherwise, indicate bad settings via 'invalid'. 131 | */ 132 | bool validate(Json::Value* invalid) const; 133 | /** A simple way to update a specific setting. 134 | */ 135 | Value& operator[](const String& key); 136 | 137 | /** Called by ctor, but you can use this to reset settings_. 138 | * \pre 'settings' != NULL (but Json::null is fine) 139 | * \remark Defaults: 140 | * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults 141 | */ 142 | static void setDefaults(Json::Value* settings); 143 | }; 144 | 145 | /** \brief Abstract class for writers. 146 | * \deprecated Use StreamWriter. (And really, this is an implementation detail.) 147 | */ 148 | class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { 149 | public: 150 | virtual ~Writer(); 151 | 152 | virtual String write(const Value& root) = 0; 153 | }; 154 | 155 | /** \brief Outputs a Value in JSON format 156 | *without formatting (not human friendly). 157 | * 158 | * The JSON document is written in a single line. It is not intended for 'human' 159 | *consumption, 160 | * but may be useful to support feature such as RPC where bandwidth is limited. 161 | * \sa Reader, Value 162 | * \deprecated Use StreamWriterBuilder. 163 | */ 164 | #if defined(_MSC_VER) 165 | #pragma warning(push) 166 | #pragma warning(disable : 4996) // Deriving from deprecated class 167 | #endif 168 | class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter 169 | : public Writer { 170 | public: 171 | FastWriter(); 172 | ~FastWriter() override = default; 173 | 174 | void enableYAMLCompatibility(); 175 | 176 | /** \brief Drop the "null" string from the writer's output for nullValues. 177 | * Strictly speaking, this is not valid JSON. But when the output is being 178 | * fed to a browser's JavaScript, it makes for smaller output and the 179 | * browser can handle the output just fine. 180 | */ 181 | void dropNullPlaceholders(); 182 | 183 | void omitEndingLineFeed(); 184 | 185 | public: // overridden from Writer 186 | String write(const Value& root) override; 187 | 188 | private: 189 | void writeValue(const Value& value); 190 | 191 | String document_; 192 | bool yamlCompatibilityEnabled_{false}; 193 | bool dropNullPlaceholders_{false}; 194 | bool omitEndingLineFeed_{false}; 195 | }; 196 | #if defined(_MSC_VER) 197 | #pragma warning(pop) 198 | #endif 199 | 200 | /** \brief Writes a Value in JSON format in a 201 | *human friendly way. 202 | * 203 | * The rules for line break and indent are as follow: 204 | * - Object value: 205 | * - if empty then print {} without indent and line break 206 | * - if not empty the print '{', line break & indent, print one value per 207 | *line 208 | * and then unindent and line break and print '}'. 209 | * - Array value: 210 | * - if empty then print [] without indent and line break 211 | * - if the array contains no object value, empty array or some other value 212 | *types, 213 | * and all the values fit on one lines, then print the array on a single 214 | *line. 215 | * - otherwise, it the values do not fit on one line, or the array contains 216 | * object or non empty array, then print one value per line. 217 | * 218 | * If the Value have comments then they are outputed according to their 219 | *#CommentPlacement. 220 | * 221 | * \sa Reader, Value, Value::setComment() 222 | * \deprecated Use StreamWriterBuilder. 223 | */ 224 | #if defined(_MSC_VER) 225 | #pragma warning(push) 226 | #pragma warning(disable : 4996) // Deriving from deprecated class 227 | #endif 228 | class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API 229 | StyledWriter : public Writer { 230 | public: 231 | StyledWriter(); 232 | ~StyledWriter() override = default; 233 | 234 | public: // overridden from Writer 235 | /** \brief Serialize a Value in JSON format. 236 | * \param root Value to serialize. 237 | * \return String containing the JSON document that represents the root value. 238 | */ 239 | String write(const Value& root) override; 240 | 241 | private: 242 | void writeValue(const Value& value); 243 | void writeArrayValue(const Value& value); 244 | bool isMultilineArray(const Value& value); 245 | void pushValue(const String& value); 246 | void writeIndent(); 247 | void writeWithIndent(const String& value); 248 | void indent(); 249 | void unindent(); 250 | void writeCommentBeforeValue(const Value& root); 251 | void writeCommentAfterValueOnSameLine(const Value& root); 252 | static bool hasCommentForValue(const Value& value); 253 | static String normalizeEOL(const String& text); 254 | 255 | typedef std::vector ChildValues; 256 | 257 | ChildValues childValues_; 258 | String document_; 259 | String indentString_; 260 | unsigned int rightMargin_{74}; 261 | unsigned int indentSize_{3}; 262 | bool addChildValues_{false}; 263 | }; 264 | #if defined(_MSC_VER) 265 | #pragma warning(pop) 266 | #endif 267 | 268 | /** \brief Writes a Value in JSON format in a 269 | human friendly way, 270 | to a stream rather than to a string. 271 | * 272 | * The rules for line break and indent are as follow: 273 | * - Object value: 274 | * - if empty then print {} without indent and line break 275 | * - if not empty the print '{', line break & indent, print one value per 276 | line 277 | * and then unindent and line break and print '}'. 278 | * - Array value: 279 | * - if empty then print [] without indent and line break 280 | * - if the array contains no object value, empty array or some other value 281 | types, 282 | * and all the values fit on one lines, then print the array on a single 283 | line. 284 | * - otherwise, it the values do not fit on one line, or the array contains 285 | * object or non empty array, then print one value per line. 286 | * 287 | * If the Value have comments then they are outputed according to their 288 | #CommentPlacement. 289 | * 290 | * \sa Reader, Value, Value::setComment() 291 | * \deprecated Use StreamWriterBuilder. 292 | */ 293 | #if defined(_MSC_VER) 294 | #pragma warning(push) 295 | #pragma warning(disable : 4996) // Deriving from deprecated class 296 | #endif 297 | class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API 298 | StyledStreamWriter { 299 | public: 300 | /** 301 | * \param indentation Each level will be indented by this amount extra. 302 | */ 303 | StyledStreamWriter(String indentation = "\t"); 304 | ~StyledStreamWriter() = default; 305 | 306 | public: 307 | /** \brief Serialize a Value in JSON format. 308 | * \param out Stream to write to. (Can be ostringstream, e.g.) 309 | * \param root Value to serialize. 310 | * \note There is no point in deriving from Writer, since write() should not 311 | * return a value. 312 | */ 313 | void write(OStream& out, const Value& root); 314 | 315 | private: 316 | void writeValue(const Value& value); 317 | void writeArrayValue(const Value& value); 318 | bool isMultilineArray(const Value& value); 319 | void pushValue(const String& value); 320 | void writeIndent(); 321 | void writeWithIndent(const String& value); 322 | void indent(); 323 | void unindent(); 324 | void writeCommentBeforeValue(const Value& root); 325 | void writeCommentAfterValueOnSameLine(const Value& root); 326 | static bool hasCommentForValue(const Value& value); 327 | static String normalizeEOL(const String& text); 328 | 329 | typedef std::vector ChildValues; 330 | 331 | ChildValues childValues_; 332 | OStream* document_; 333 | String indentString_; 334 | unsigned int rightMargin_{74}; 335 | String indentation_; 336 | bool addChildValues_ : 1; 337 | bool indented_ : 1; 338 | }; 339 | #if defined(_MSC_VER) 340 | #pragma warning(pop) 341 | #endif 342 | 343 | #if defined(JSON_HAS_INT64) 344 | String JSON_API valueToString(Int value); 345 | String JSON_API valueToString(UInt value); 346 | #endif // if defined(JSON_HAS_INT64) 347 | String JSON_API valueToString(LargestInt value); 348 | String JSON_API valueToString(LargestUInt value); 349 | String JSON_API valueToString( 350 | double value, unsigned int precision = Value::defaultRealPrecision, 351 | PrecisionType precisionType = PrecisionType::significantDigits); 352 | String JSON_API valueToString(bool value); 353 | String JSON_API valueToQuotedString(const char* value); 354 | 355 | /// \brief Output using the StyledStreamWriter. 356 | /// \see Json::operator>>() 357 | JSON_API OStream& operator<<(OStream&, const Value& root); 358 | 359 | } // namespace Json 360 | 361 | #pragma pack(pop) 362 | 363 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 364 | #pragma warning(pop) 365 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 366 | 367 | #endif // JSON_WRITER_H_INCLUDED 368 | -------------------------------------------------------------------------------- /Gobang/inc/json/json_tool.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 7 | #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include 11 | #endif 12 | 13 | // Also support old flag NO_LOCALE_SUPPORT 14 | #ifdef NO_LOCALE_SUPPORT 15 | #define JSONCPP_NO_LOCALE_SUPPORT 16 | #endif 17 | 18 | #ifndef JSONCPP_NO_LOCALE_SUPPORT 19 | #include 20 | #endif 21 | 22 | /* This header provides common string manipulation support, such as UTF-8, 23 | * portable conversion from/to string... 24 | * 25 | * It is an internal header that must not be exposed. 26 | */ 27 | 28 | namespace Json { 29 | static inline char getDecimalPoint() { 30 | #ifdef JSONCPP_NO_LOCALE_SUPPORT 31 | return '\0'; 32 | #else 33 | struct lconv* lc = localeconv(); 34 | return lc ? *(lc->decimal_point) : '\0'; 35 | #endif 36 | } 37 | 38 | /// Converts a unicode code-point to UTF-8. 39 | static inline String codePointToUTF8(unsigned int cp) { 40 | String result; 41 | 42 | // based on description from http://en.wikipedia.org/wiki/UTF-8 43 | 44 | if (cp <= 0x7f) { 45 | result.resize(1); 46 | result[0] = static_cast(cp); 47 | } else if (cp <= 0x7FF) { 48 | result.resize(2); 49 | result[1] = static_cast(0x80 | (0x3f & cp)); 50 | result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); 51 | } else if (cp <= 0xFFFF) { 52 | result.resize(3); 53 | result[2] = static_cast(0x80 | (0x3f & cp)); 54 | result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); 55 | result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); 56 | } else if (cp <= 0x10FFFF) { 57 | result.resize(4); 58 | result[3] = static_cast(0x80 | (0x3f & cp)); 59 | result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); 60 | result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); 61 | result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); 62 | } 63 | 64 | return result; 65 | } 66 | 67 | enum { 68 | /// Constant that specify the size of the buffer that must be passed to 69 | /// uintToString. 70 | uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 71 | }; 72 | 73 | // Defines a char buffer for use with uintToString(). 74 | typedef char UIntToStringBuffer[uintToStringBufferSize]; 75 | 76 | /** Converts an unsigned integer to string. 77 | * @param value Unsigned integer to convert to string 78 | * @param current Input/Output string buffer. 79 | * Must have at least uintToStringBufferSize chars free. 80 | */ 81 | static inline void uintToString(LargestUInt value, char*& current) { 82 | *--current = 0; 83 | do { 84 | *--current = static_cast(value % 10U + static_cast('0')); 85 | value /= 10; 86 | } while (value != 0); 87 | } 88 | 89 | /** Change ',' to '.' everywhere in buffer. 90 | * 91 | * We had a sophisticated way, but it did not work in WinCE. 92 | * @see https://github.com/open-source-parsers/jsoncpp/pull/9 93 | */ 94 | template Iter fixNumericLocale(Iter begin, Iter end) { 95 | for (; begin != end; ++begin) { 96 | if (*begin == ',') { 97 | *begin = '.'; 98 | } 99 | } 100 | return begin; 101 | } 102 | 103 | template void fixNumericLocaleInput(Iter begin, Iter end) { 104 | char decimalPoint = getDecimalPoint(); 105 | if (decimalPoint == '\0' || decimalPoint == '.') { 106 | return; 107 | } 108 | for (; begin != end; ++begin) { 109 | if (*begin == '.') { 110 | *begin = decimalPoint; 111 | } 112 | } 113 | } 114 | 115 | /** 116 | * Return iterator that would be the new end of the range [begin,end), if we 117 | * were to delete zeros in the end of string, but not the last zero before '.'. 118 | */ 119 | template Iter fixZerosInTheEnd(Iter begin, Iter end) { 120 | for (; begin != end; --end) { 121 | if (*(end - 1) != '0') { 122 | return end; 123 | } 124 | // Don't delete the last zero before the decimal point. 125 | if (begin != (end - 1) && *(end - 2) == '.') { 126 | return end; 127 | } 128 | } 129 | return end; 130 | } 131 | 132 | } // namespace Json 133 | 134 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 135 | -------------------------------------------------------------------------------- /Gobang/inc/json/json_valueiterator.inl: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | // included by json_value.cpp 7 | 8 | namespace Json { 9 | 10 | // ////////////////////////////////////////////////////////////////// 11 | // ////////////////////////////////////////////////////////////////// 12 | // ////////////////////////////////////////////////////////////////// 13 | // class ValueIteratorBase 14 | // ////////////////////////////////////////////////////////////////// 15 | // ////////////////////////////////////////////////////////////////// 16 | // ////////////////////////////////////////////////////////////////// 17 | 18 | ValueIteratorBase::ValueIteratorBase() : current_() {} 19 | 20 | ValueIteratorBase::ValueIteratorBase( 21 | const Value::ObjectValues::iterator& current) 22 | : current_(current), isNull_(false) {} 23 | 24 | Value& ValueIteratorBase::deref() { return current_->second; } 25 | const Value& ValueIteratorBase::deref() const { return current_->second; } 26 | 27 | void ValueIteratorBase::increment() { ++current_; } 28 | 29 | void ValueIteratorBase::decrement() { --current_; } 30 | 31 | ValueIteratorBase::difference_type 32 | ValueIteratorBase::computeDistance(const SelfType& other) const { 33 | #ifdef JSON_USE_CPPTL_SMALLMAP 34 | return other.current_ - current_; 35 | #else 36 | // Iterator for null value are initialized using the default 37 | // constructor, which initialize current_ to the default 38 | // std::map::iterator. As begin() and end() are two instance 39 | // of the default std::map::iterator, they can not be compared. 40 | // To allow this, we handle this comparison specifically. 41 | if (isNull_ && other.isNull_) { 42 | return 0; 43 | } 44 | 45 | // Usage of std::distance is not portable (does not compile with Sun Studio 12 46 | // RogueWave STL, 47 | // which is the one used by default). 48 | // Using a portable hand-made version for non random iterator instead: 49 | // return difference_type( std::distance( current_, other.current_ ) ); 50 | difference_type myDistance = 0; 51 | for (Value::ObjectValues::iterator it = current_; it != other.current_; 52 | ++it) { 53 | ++myDistance; 54 | } 55 | return myDistance; 56 | #endif 57 | } 58 | 59 | bool ValueIteratorBase::isEqual(const SelfType& other) const { 60 | if (isNull_) { 61 | return other.isNull_; 62 | } 63 | return current_ == other.current_; 64 | } 65 | 66 | void ValueIteratorBase::copy(const SelfType& other) { 67 | current_ = other.current_; 68 | isNull_ = other.isNull_; 69 | } 70 | 71 | Value ValueIteratorBase::key() const { 72 | const Value::CZString czstring = (*current_).first; 73 | if (czstring.data()) { 74 | if (czstring.isStaticString()) 75 | return Value(StaticString(czstring.data())); 76 | return Value(czstring.data(), czstring.data() + czstring.length()); 77 | } 78 | return Value(czstring.index()); 79 | } 80 | 81 | UInt ValueIteratorBase::index() const { 82 | const Value::CZString czstring = (*current_).first; 83 | if (!czstring.data()) 84 | return czstring.index(); 85 | return Value::UInt(-1); 86 | } 87 | 88 | String ValueIteratorBase::name() const { 89 | char const* keey; 90 | char const* end; 91 | keey = memberName(&end); 92 | if (!keey) 93 | return String(); 94 | return String(keey, end); 95 | } 96 | 97 | char const* ValueIteratorBase::memberName() const { 98 | const char* cname = (*current_).first.data(); 99 | return cname ? cname : ""; 100 | } 101 | 102 | char const* ValueIteratorBase::memberName(char const** end) const { 103 | const char* cname = (*current_).first.data(); 104 | if (!cname) { 105 | *end = nullptr; 106 | return nullptr; 107 | } 108 | *end = cname + (*current_).first.length(); 109 | return cname; 110 | } 111 | 112 | // ////////////////////////////////////////////////////////////////// 113 | // ////////////////////////////////////////////////////////////////// 114 | // ////////////////////////////////////////////////////////////////// 115 | // class ValueConstIterator 116 | // ////////////////////////////////////////////////////////////////// 117 | // ////////////////////////////////////////////////////////////////// 118 | // ////////////////////////////////////////////////////////////////// 119 | 120 | ValueConstIterator::ValueConstIterator() = default; 121 | 122 | ValueConstIterator::ValueConstIterator( 123 | const Value::ObjectValues::iterator& current) 124 | : ValueIteratorBase(current) {} 125 | 126 | ValueConstIterator::ValueConstIterator(ValueIterator const& other) 127 | : ValueIteratorBase(other) {} 128 | 129 | ValueConstIterator& ValueConstIterator:: 130 | operator=(const ValueIteratorBase& other) { 131 | copy(other); 132 | return *this; 133 | } 134 | 135 | // ////////////////////////////////////////////////////////////////// 136 | // ////////////////////////////////////////////////////////////////// 137 | // ////////////////////////////////////////////////////////////////// 138 | // class ValueIterator 139 | // ////////////////////////////////////////////////////////////////// 140 | // ////////////////////////////////////////////////////////////////// 141 | // ////////////////////////////////////////////////////////////////// 142 | 143 | ValueIterator::ValueIterator() = default; 144 | 145 | ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 146 | : ValueIteratorBase(current) {} 147 | 148 | ValueIterator::ValueIterator(const ValueConstIterator& other) 149 | : ValueIteratorBase(other) { 150 | throwRuntimeError("ConstIterator to Iterator should never be allowed."); 151 | } 152 | 153 | ValueIterator::ValueIterator(const ValueIterator& other) = default; 154 | 155 | ValueIterator& ValueIterator::operator=(const SelfType& other) { 156 | copy(other); 157 | return *this; 158 | } 159 | 160 | } // namespace Json 161 | -------------------------------------------------------------------------------- /Gobang/res/bgcolor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/bgcolor.png -------------------------------------------------------------------------------- /Gobang/res/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/black.png -------------------------------------------------------------------------------- /Gobang/res/color-palette.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/color-palette.ico -------------------------------------------------------------------------------- /Gobang/res/copy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/copy.ico -------------------------------------------------------------------------------- /Gobang/res/disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/disconnect.png -------------------------------------------------------------------------------- /Gobang/res/exchange.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/exchange.ico -------------------------------------------------------------------------------- /Gobang/res/paste.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/paste.ico -------------------------------------------------------------------------------- /Gobang/res/preparing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/preparing.png -------------------------------------------------------------------------------- /Gobang/res/reset.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/reset.ico -------------------------------------------------------------------------------- /Gobang/res/reset_defalut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/reset_defalut.png -------------------------------------------------------------------------------- /Gobang/res/screenshot.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/screenshot.ico -------------------------------------------------------------------------------- /Gobang/res/select-file.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/select-file.ico -------------------------------------------------------------------------------- /Gobang/res/setting.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/setting.ico -------------------------------------------------------------------------------- /Gobang/res/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/Gobang/res/white.png -------------------------------------------------------------------------------- /Gobang/src/chess/base.cpp: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | ChessType reverse(ChessType typeIn) { 4 | return ChessType(-1 * typeIn); 5 | } 6 | -------------------------------------------------------------------------------- /Gobang/src/chess/base.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE_H 2 | #define BASE_H 3 | 4 | enum ChessType { 5 | CHESS_BLACK = -1, 6 | CHESS_NULL = 0, 7 | CHESS_WHITE = 1 8 | }; 9 | 10 | enum BackgroundType { 11 | BG_PURE_COLOR = 1, 12 | BG_PICTURE = 2 13 | }; 14 | 15 | ChessType reverse(ChessType typeIn); 16 | 17 | 18 | #endif // BASE_H 19 | -------------------------------------------------------------------------------- /Gobang/src/chess/chessboard.cpp: -------------------------------------------------------------------------------- 1 | #include "chessboard.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | 11 | ChessBoard::ChessBoard(QWidget *parent) : 12 | QWidget(parent) 13 | { 14 | imgLabel = new QLabel(this); 15 | imgLabel->setFixedSize(625, 625); 16 | this->setFixedSize(625, 625); 17 | 18 | pixmap = QPixmap(); 19 | lastPiece = { 0, 0, CHESS_NULL }; 20 | init(); 21 | } 22 | 23 | void ChessBoard::init() { 24 | numPieces = 0; 25 | lastPiece = { 0, 0, CHESS_NULL }; 26 | for (int row = 0; row < ROWS; ++row) { 27 | for (int col = 0; col < ROWS; ++col) { 28 | chessPieces[row][col] = CHESS_NULL; 29 | } 30 | } 31 | drawChessboard(); 32 | } 33 | 34 | void ChessBoard::init(int pieces[][ROWS], ChessPieceInfo lastPieceInfo) { 35 | numPieces = 0; 36 | lastPiece = lastPieceInfo; 37 | for (int row = 0; row < ROWS; ++row) { 38 | for (int col = 0; col < ROWS; ++col) { 39 | chessPieces[row][col] = pieces[row][col]; 40 | if (chessPieces[row][col] != CHESS_NULL) 41 | numPieces++; 42 | } 43 | } 44 | flush(); 45 | } 46 | 47 | void ChessBoard::flush() { 48 | drawChessboard(); 49 | 50 | for (int row = 0; row < ROWS; ++row) { 51 | for (int col = 0; col < ROWS; ++col) { 52 | drawPiece(row, col, ChessType(chessPieces[row][col]), false); 53 | } 54 | } 55 | 56 | drawPiece(lastPiece.row, lastPiece.col, lastPiece.type, true); 57 | imgLabel->setPixmap(pixmap); 58 | } 59 | 60 | void ChessBoard::drawChessboard() { 61 | // Background 62 | // 1. pure color 63 | // 2. picture 64 | fillBackground(); 65 | 66 | // Draw chess board 67 | QPainter painter(&pixmap); 68 | painter.setRenderHint(QPainter::Antialiasing, true); 69 | painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); 70 | 71 | int left = startX + boardWidth; 72 | int right = left + gridWidth * (ROWS - 1); 73 | int top = startY + boardWidth; 74 | int bottom = top + gridWidth * (ROWS - 1); 75 | 76 | for (int i = 0; i < ROWS; ++i) { 77 | // Horizontal lines 78 | painter.drawLine(left, top + gridWidth * i, right, top + gridWidth * i); 79 | // vertical lines 80 | painter.drawLine(left + gridWidth * i, top, left + gridWidth * i, bottom); 81 | 82 | // top & bottom text (A, B, C, ... , S) 83 | painter.drawText(QPoint(left + gridWidth * i, startY * 2 / 3), QString('A' + i)); 84 | painter.drawText(QPoint(left + gridWidth * i, bottom + boardWidth + startY / 2), QString('A' + i)); 85 | 86 | // left & right text (1, 2, 3, ... , 15) 87 | painter.drawText(QPoint(startX / 3, top + gridWidth * i), QString::number(1 + i)); 88 | painter.drawText(QPoint(right + boardWidth + startX / 3, top + gridWidth * i), QString::number(1 + i)); 89 | } 90 | 91 | // board internal lines 92 | left = startX; 93 | top = startY; 94 | right = left + boardWidth * 2 + gridWidth * (ROWS - 1); 95 | bottom = top + boardWidth * 2 + gridWidth * (ROWS - 1); 96 | painter.drawLine(left, top, right, top); 97 | painter.drawLine(right, top, right, bottom); 98 | painter.drawLine(left, bottom, right, bottom); 99 | painter.drawLine(left, top, left, bottom); 100 | 101 | // five control points 102 | painter.setPen(QColor(Qt::black)); 103 | painter.setBrush(QBrush(Qt::black)); 104 | int centerX = startX + boardWidth + (ROWS / 2) * gridWidth; 105 | int centerY = startY + boardWidth + (ROWS / 2) * gridWidth; 106 | painter.drawEllipse(QPoint(centerX, centerY), 4, 4); 107 | painter.drawEllipse(QPoint(centerX - 4 * gridWidth, centerY - 4 * gridWidth), 4, 4); 108 | painter.drawEllipse(QPoint(centerX + 4 * gridWidth, centerY - 4 * gridWidth), 4, 4); 109 | painter.drawEllipse(QPoint(centerX - 4 * gridWidth, centerY + 4 * gridWidth), 4, 4); 110 | painter.drawEllipse(QPoint(centerX + 4 * gridWidth, centerY + 4 * gridWidth), 4, 4); 111 | 112 | imgLabel->setPixmap(pixmap); 113 | painter.end(); 114 | } 115 | 116 | // Place a piece 117 | void ChessBoard::setPiece(int row, int col, ChessType type) { 118 | chessPieces[row][col] = type; 119 | 120 | drawPiece(lastPiece.row, lastPiece.col, lastPiece.type, false); 121 | drawPiece(row, col, type, true); 122 | 123 | lastPiece = { row, col, type }; 124 | 125 | // judge 126 | if (type != CHESS_NULL) { 127 | int status = judge(row, col); 128 | if (status == S_WIN) 129 | emit sigWin(type); 130 | else if (status == S_DRAW) 131 | emit sigDraw(); 132 | } 133 | } 134 | 135 | bool ChessBoard::isValid(int row, int col) { 136 | return (row >= 0 && row < ROWS && col >= 0 && col < ROWS && 137 | chessPieces[row][col] == CHESS_NULL); 138 | } 139 | 140 | bool ChessBoard::getRowCol(QPoint cursorPos, int &row, int &col) { 141 | int left = startX + boardWidth; 142 | int right = left + gridWidth * (ROWS - 1); 143 | int top = startY + boardWidth; 144 | int bottom = top + gridWidth * (ROWS - 1); 145 | 146 | int x = cursorPos.x(); 147 | int y = cursorPos.y(); 148 | 149 | if (x < left - EPS || x > right + EPS) 150 | return false; 151 | if (y < top - EPS || y > bottom + EPS) 152 | return false; 153 | 154 | int countX = abs(x - left) / gridWidth; 155 | int countY = abs(y - top) / gridWidth; 156 | 157 | int gridLeft = left + countX * gridWidth; 158 | int gridRight = gridLeft + gridWidth; 159 | int gridTop = top + countY * gridWidth; 160 | int gridBottom = gridTop + gridWidth; 161 | 162 | if (abs(x - gridLeft) <= EPS) { 163 | if (abs(y - gridTop) <= EPS) { 164 | row = countY; 165 | col = countX; 166 | return true; 167 | } 168 | else if (abs(y - gridBottom) <= EPS) { 169 | row = countY + 1; 170 | col = countX; 171 | return true; 172 | } 173 | else { 174 | return false; 175 | } 176 | } 177 | else if (abs(x - gridRight) <= EPS) { 178 | if (abs(y - gridTop) <= EPS) { 179 | row = countY; 180 | col = countX + 1; 181 | return true; 182 | } 183 | else if (abs(y - gridBottom) <= EPS) { 184 | row = countY + 1; 185 | col = countX + 1; 186 | return true; 187 | } 188 | else { 189 | return false; 190 | } 191 | } 192 | else { 193 | return false; 194 | } 195 | } 196 | 197 | 198 | // Background 199 | // 1. pure color 200 | // 2. picture 201 | void ChessBoard::fillBackground() { 202 | if (bgType == BG_PURE_COLOR) { 203 | pixmap = QPixmap(imgLabel->size()); 204 | pixmap.fill(bgColor); 205 | } 206 | else { 207 | pixmap = bgPicture; 208 | QPixmap temp(pixmap.size()); 209 | temp.fill(Qt::transparent); 210 | QPainter painter(&temp); 211 | 212 | painter.setCompositionMode(QPainter::CompositionMode_Source); 213 | painter.drawPixmap(0, 0, pixmap); 214 | painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); 215 | painter.fillRect(temp.rect(), QColor(0, 0, 0, bgTransparency)); 216 | painter.end(); 217 | 218 | pixmap = temp.scaled(625, 625, Qt::KeepAspectRatio, Qt::SmoothTransformation); 219 | imgLabel->setScaledContents(true); 220 | } 221 | 222 | imgLabel->setPixmap(pixmap); 223 | } 224 | 225 | 226 | void ChessBoard::drawPiece(int row, int col, ChessType type, bool highlight) { 227 | QPainter painter(&pixmap); 228 | painter.setRenderHint(QPainter::Antialiasing, true); 229 | painter.setRenderHint(QPainter::TextAntialiasing, true); 230 | 231 | if (type == CHESS_NULL) 232 | return; 233 | else if (type == CHESS_BLACK) { 234 | painter.setPen(Qt::black); 235 | painter.setBrush(Qt::black); 236 | } 237 | else { 238 | painter.setPen(Qt::white); 239 | painter.setBrush(Qt::white); 240 | } 241 | 242 | int x = startX + boardWidth + gridWidth * col; 243 | int y = startY + boardWidth + gridWidth * row; 244 | 245 | // chess piece 246 | painter.drawEllipse(QPoint(x, y), pieceRadius, pieceRadius); 247 | 248 | // highlight: draw a cross-shape 249 | if (highlight) { 250 | QPen pen; 251 | pen.setWidth(3); 252 | if (type == CHESS_BLACK) 253 | pen.setColor(Qt::white); 254 | else 255 | pen.setColor(Qt::black); 256 | painter.setPen(pen); 257 | painter.drawLine(x + 4, y, x + 6, y); 258 | painter.drawLine(x - 4, y, x - 6, y); 259 | painter.drawLine(x, y + 4, x, y + 6); 260 | painter.drawLine(x, y - 4, x, y - 6); 261 | } 262 | 263 | painter.end(); 264 | imgLabel->setPixmap(pixmap); 265 | numPieces++; 266 | } 267 | 268 | int ChessBoard::judge(int row, int col) { 269 | int chessType = chessPieces[row][col]; 270 | 271 | bool ret= (judgeInRow(row, col, chessType) || 272 | judgeInCol(row, col, chessType) || 273 | judgeFromTopleftToBottomRight(row, col, chessType) || 274 | judgeFromBottomleftToTopright(row, col, chessType) 275 | ); 276 | 277 | if (ret) 278 | return S_WIN; 279 | if (numPieces == ROWS * ROWS) 280 | return S_DRAW; 281 | else 282 | return S_CONTINUE; 283 | } 284 | 285 | //int ChessBoard::judge() { 286 | // 287 | // return 0; 288 | //} 289 | 290 | // Five in row 291 | bool ChessBoard::judgeInRow(int row, int col, int chessType) { 292 | int count = 1; 293 | int l = col - 1, r = col + 1; 294 | while (l > -1 || r < ROWS) { 295 | if (l > -1) { 296 | if (chessPieces[row][l] == chessType) { 297 | count++; 298 | l--; 299 | } 300 | else { 301 | l = -1; 302 | } 303 | } 304 | if (r < ROWS) { 305 | if (chessPieces[row][r] == chessType) { 306 | count++; 307 | r++; 308 | } 309 | else { 310 | r = ROWS; 311 | } 312 | } 313 | } 314 | 315 | return count >= 5; 316 | } 317 | 318 | // Five in column 319 | bool ChessBoard::judgeInCol(int row, int col, int chessType) { 320 | int count = 1; 321 | int t = row - 1, b = row + 1; 322 | while (t > -1 || b < ROWS) { 323 | if (t > -1) { 324 | if (chessPieces[t][col] == chessType) { 325 | count++; 326 | t--; 327 | } 328 | else { 329 | t = -1; 330 | } 331 | } 332 | if (b < ROWS) { 333 | if (chessPieces[b][col] == chessType) { 334 | count++; 335 | b++; 336 | } 337 | else { 338 | b = ROWS; 339 | } 340 | } 341 | } 342 | 343 | return count >= 5; 344 | } 345 | 346 | // topLeft -> bottomRight 347 | bool ChessBoard::judgeFromTopleftToBottomRight(int row, int col, int chessType) { 348 | int count = 1; 349 | int l = col - 1, r = col + 1; 350 | int t = row - 1, b = row + 1; 351 | bool bTL = (t > -1 && l > -1); 352 | bool bBR = (b < ROWS && r < ROWS); 353 | 354 | while (bTL || bBR) { 355 | if (bTL) { 356 | if (chessPieces[t][l] == chessType) { 357 | count++; 358 | t--; 359 | l--; 360 | } 361 | else { 362 | t = -1; 363 | } 364 | } 365 | if (bBR) { 366 | if (chessPieces[b][r] == chessType) { 367 | count++; 368 | b++; 369 | r++; 370 | } 371 | else { 372 | b = ROWS; 373 | } 374 | } 375 | bTL = (t > -1 && l > -1); 376 | bBR = (b < ROWS && r < ROWS); 377 | } 378 | 379 | return count >= 5; 380 | } 381 | 382 | // bottomLeft -> topRight 383 | bool ChessBoard::judgeFromBottomleftToTopright(int row, int col, int chessType) { 384 | int count = 1; 385 | int l = col - 1, r = col + 1; 386 | int t = row - 1, b = row + 1; 387 | bool bBL = (b > -1 && l > -1); 388 | bool bTR = (t < ROWS && r < ROWS); 389 | 390 | while (bBL || bTR) { 391 | if (bBL) { 392 | if (chessPieces[b][l] == chessType) { 393 | count++; 394 | b++; 395 | l--; 396 | } 397 | else { 398 | b = -1; 399 | } 400 | } 401 | if (bTR) { 402 | if (chessPieces[t][r] == chessType) { 403 | count++; 404 | t--; 405 | r++; 406 | } 407 | else { 408 | t = ROWS; 409 | } 410 | } 411 | bBL = (b > -1 && l > -1); 412 | bTR = (t < ROWS && r < ROWS); 413 | } 414 | 415 | return count >= 5; 416 | } 417 | -------------------------------------------------------------------------------- /Gobang/src/chess/chessboard.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESSBOARD_H 2 | #define CHESSBOARD_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "base.h" 9 | #include "../environment.h" 10 | 11 | class ChessBoard : public QWidget 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit ChessBoard(QWidget *parent = nullptr); 16 | 17 | enum { ROWS = 15 }; 18 | enum { S_CONTINUE = -2, S_LOSE = -1, S_DRAW = 0, S_WIN = 1 }; 19 | struct ChessPieceInfo { 20 | int row; 21 | int col; 22 | ChessType type; 23 | }; 24 | 25 | public: 26 | // clear all pieces 27 | void init(); 28 | // or fill chessboard with specical pieces 29 | void init(int pieces[][ROWS], ChessPieceInfo lastPieceType); 30 | 31 | // not clear pieces, just repaint 32 | void flush(); 33 | 34 | // place a piece 35 | void setPiece(int row, int col, ChessType type); 36 | 37 | // Set the style of background 38 | // 1. pure color 39 | // 2. picture 40 | BackgroundType getBgType() const { return bgType; } 41 | QPixmap getBgPicture() const { return bgPicture; } 42 | QColor getBgColor() const { return bgColor; } 43 | int getBgTransparency() const { return bgTransparency; } 44 | 45 | void setBgType(BackgroundType type) { bgType = type; } 46 | void setBgPicture(const QPixmap& picture) { bgPicture = picture; } 47 | void setBgColor(const QColor& color) { bgColor = color; } 48 | void setBgTransparecny(int val) { bgTransparency = val; } 49 | 50 | // Get the image of chessboard, include chess pieces 51 | // 52 | QPixmap& getImage() { return pixmap; } 53 | 54 | signals: 55 | void sigWin(int type); 56 | void sigDraw(); 57 | 58 | protected: 59 | void drawChessboard(); 60 | void fillBackground(); 61 | void drawPiece(int row, int col, ChessType type, bool highlight); // (0 <= row, col <= ROWS) 62 | 63 | bool isValid(int row, int col); 64 | bool getRowCol(QPoint cursorPos, int& row, int& col); 65 | 66 | //int judge(); 67 | int judge(int row, int col); 68 | bool judgeInRow(int row, int col, int chessType); 69 | bool judgeInCol(int row, int col, int chessType); 70 | bool judgeFromTopleftToBottomRight(int row, int col, int chessType); 71 | bool judgeFromBottomleftToTopright(int row, int col, int chessType); 72 | 73 | protected: 74 | 75 | // Chess pieces 76 | int chessPieces[ROWS][ROWS]; 77 | int numPieces = 0; 78 | 79 | const int gridWidth = 40; 80 | const int startX = 27; 81 | const int startY = 27; 82 | const int boardWidth = 5; 83 | const int pieceRadius = 13; 84 | const int EPS = 10; 85 | 86 | QPixmap pixmap; // including background image(or color) and chess pieces 87 | QLabel* imgLabel; 88 | 89 | BackgroundType bgType = BG_PURE_COLOR; 90 | QColor bgColor = qRgb(200, 150, 100); 91 | QPixmap bgPicture; 92 | int bgTransparency = 220; 93 | 94 | ChessPieceInfo lastPiece; 95 | }; 96 | 97 | #endif // CHESSBOARD_H 98 | -------------------------------------------------------------------------------- /Gobang/src/chess/chessboardvs.cpp: -------------------------------------------------------------------------------- 1 | #include "chessboardvs.h" 2 | #include 3 | #include 4 | 5 | ChessBoardVS::ChessBoardVS(QWidget* parent) : 6 | ChessBoard(parent) 7 | { 8 | } 9 | 10 | void ChessBoardVS::init() { 11 | ChessBoard::init(); 12 | currentChess = CHESS_BLACK; 13 | } 14 | 15 | // Ignore mouse event 16 | // game start: fasle 17 | // game end: true 18 | void ChessBoardVS::ignoreMouseEvent(bool on) { 19 | this->setAttribute(Qt::WA_TransparentForMouseEvents, on); 20 | } 21 | 22 | void ChessBoardVS::mousePressEvent(QMouseEvent *event) { 23 | startPos = event->pos(); 24 | } 25 | 26 | void ChessBoardVS::mouseReleaseEvent(QMouseEvent *event) { 27 | if (currentChess != yourChess) 28 | return; 29 | 30 | endPos = event->pos(); 31 | if ((endPos - startPos).manhattanLength() <= gridWidth) { 32 | int row, col; 33 | if (getRowCol(endPos, row, col)) { 34 | emit sigSetPieceByCursor(row, col, yourChess); 35 | ChessBoard::setPiece(row, col, yourChess); 36 | currentChess = rivalChess; 37 | } 38 | } 39 | } 40 | 41 | void ChessBoardVS::setPiece(int row, int col) { 42 | ChessBoard::setPiece(row, col, rivalChess); 43 | currentChess = yourChess; 44 | } 45 | 46 | void ChessBoardVS::setYourChessType(ChessType newType) { 47 | yourChess = newType; 48 | rivalChess = reverse(newType); 49 | } 50 | -------------------------------------------------------------------------------- /Gobang/src/chess/chessboardvs.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESSBOARDVS_H 2 | #define CHESSBOARDVS_H 3 | 4 | #include "chessboard.h" 5 | #include "../network/client.h" 6 | 7 | 8 | class ChessBoardVS : public ChessBoard 9 | { 10 | Q_OBJECT 11 | public: 12 | ChessBoardVS(QWidget* parent = nullptr); 13 | 14 | public: 15 | void init(); 16 | void setYourChessType(ChessType newType); 17 | void ignoreMouseEvent(bool on); 18 | ChessType getCurrChessType() const { return currentChess; } 19 | void setPiece(int row, int col); 20 | 21 | signals: 22 | void sigSetPieceByCursor(int row, int col, int type); 23 | 24 | protected: 25 | virtual void mousePressEvent(QMouseEvent *event) override; 26 | virtual void mouseReleaseEvent(QMouseEvent *event) override; 27 | 28 | private: 29 | ChessType currentChess = CHESS_BLACK; 30 | ChessType yourChess = CHESS_NULL; 31 | ChessType rivalChess = CHESS_NULL; 32 | 33 | QPoint startPos; 34 | QPoint endPos; 35 | }; 36 | 37 | #endif // CHESSBOARDVS_H 38 | -------------------------------------------------------------------------------- /Gobang/src/chess/player.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYER_H 2 | #define PLAYER_H 3 | 4 | #include 5 | 6 | #include "base.h" 7 | 8 | 9 | class Player 10 | { 11 | public: 12 | Player() {} 13 | Player(const QString& name, ChessType type, bool isMaster) : 14 | name(name), type(type), is_master(isMaster) {} 15 | 16 | void setName(const QString& newName) { name = newName; } 17 | void setType(ChessType newType) { type = newType; } 18 | void setMaster(bool val) { is_master = val; } 19 | const QString& getName() const { return name; } 20 | ChessType getType() const { return type; } 21 | bool isMaster() const { return is_master; } 22 | 23 | private: 24 | QString name = ""; 25 | ChessType type = CHESS_BLACK; 26 | bool is_master = false; 27 | }; 28 | 29 | #endif // PLAYER_H 30 | -------------------------------------------------------------------------------- /Gobang/src/dialog/chessonline.h: -------------------------------------------------------------------------------- 1 | #ifndef CHESSONLINE_H 2 | #define CHESSONLINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../chess/chessboardvs.h" 11 | #include "../chess/player.h" 12 | #include "../network/client.h" 13 | #include "../widget/chathistory.h" 14 | #include "settingpanel.h" 15 | 16 | 17 | class ChessOnline : public QDialog 18 | { 19 | Q_OBJECT 20 | public: 21 | ChessOnline(Player* you, Player* rival, QWidget* parent = nullptr); 22 | ~ChessOnline(); 23 | 24 | public: 25 | void setClient(Client* clientIn); 26 | void setRoomName(const QString& nameIn) { roomName = nameIn; } 27 | void setRoomId(int idIn) { roomId = idIn; } 28 | void updateInfo(); 29 | 30 | // Using for multi-thread 31 | // QWidget(and subclassed) should only be used or modified in GUI thread 32 | // The program may crash if QWidget was used in other thread 33 | // This problem can be solved by using "signals and slots" 34 | signals: 35 | void sigCritical(QWidget* parent, const QString& title, const QString& text, int button); 36 | void sigInformation(QWidget* parent, const QString& title, const QString& text, int button); 37 | void sigProcessMsgTypeCommand(const Json::Value& root); 38 | void sigProcessMsgTypeNotify(const Json::Value& root); 39 | void sigProcessMsgTypeResponse(const Json::Value& root); 40 | void sigProcessMsgTypeChat(const Json::Value& root); 41 | 42 | public slots: 43 | void onStart(); 44 | void onCopyToClipboard(); 45 | void onShowSettingPanel(); 46 | void onScreenshot(); 47 | void onSetPieceByCursor(int row, int col, int type); 48 | void onGameWin(int type); 49 | void onGameDraw(); 50 | void onSettingsChanged(const SettingsInfo& settings); 51 | void onExchangeChessType(); 52 | 53 | protected: 54 | virtual void closeEvent(QCloseEvent *) override; 55 | virtual bool eventFilter(QObject *watched, QEvent *event) override; 56 | virtual void keyPressEvent(QKeyEvent* event) override; 57 | 58 | private: 59 | void setupLayout(); 60 | void startRecvMsg(); 61 | void changeTurn(); 62 | void gameOver(); 63 | void exchangeChessType(); 64 | 65 | 66 | /******************************* 67 | * Parse and process recv msg 68 | *******************************/ 69 | public: 70 | void parseJsonMsg(const Json::Value& root); 71 | 72 | public slots: 73 | void processMsgTypeCommand(const Json::Value& root); 74 | void processMsgTypeNotify(const Json::Value& root); 75 | void processMsgTypeResponse(const Json::Value& root); 76 | void processMsgTypeChat(const Json::Value& root); 77 | 78 | private: 79 | enum GameStatus { GAME_RUNNING = 1, GAME_PREPARE = 2, GAME_END = 3 }; 80 | 81 | GameStatus gameStatus = GAME_END; 82 | bool activeDisconnect = false; 83 | 84 | ChessBoardVS* chessBoard = nullptr; 85 | Player* playerYou = nullptr; 86 | Player* playerRival = nullptr; 87 | Client* client = nullptr; 88 | QString roomName; 89 | int roomId; 90 | 91 | QPushButton* btnSetting = nullptr; 92 | QPushButton* btnStart = nullptr; 93 | QPushButton* btnScreenshot = nullptr; 94 | QPushButton* btnExchange = nullptr; 95 | 96 | QLabel* labelRoomId; 97 | QLabel* labelRoomName; 98 | QLabel* labelServerIp; 99 | QLabel* labelServerPort; 100 | QLabel* labelYourName1; 101 | QLabel* labelYourName2; 102 | QLabel* labelRivalName; 103 | QLabel* labelYourTurn; 104 | QLabel* labelRivalTurn; 105 | 106 | QPixmap whiteChess; 107 | QPixmap blackChess; 108 | QPixmap inPreparation; 109 | QPixmap sameColorWithBg; 110 | QPixmap rivalDisconnect; 111 | QPixmap* yourChess; 112 | QPixmap* rivalChess; 113 | 114 | bool isQuit = false; 115 | bool isForceQuit = false; 116 | bool isYourTurn = false; 117 | 118 | ChatHistory* chatHistory; 119 | QTextEdit* chatInput; 120 | }; 121 | 122 | #endif // CHESSONLINE_H 123 | -------------------------------------------------------------------------------- /Gobang/src/dialog/createroomdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "createroomdialog.h" 2 | #include "../network/client.h" 3 | #include "../network/api.h" 4 | #include "../environment.h" 5 | #include "chessonline.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | 19 | CreateRoomDialog::CreateRoomDialog(QWidget* parent) : 20 | QDialog(parent) 21 | { 22 | this->setAttribute(Qt::WA_DeleteOnClose, true); 23 | this->setWindowTitle("Create a room"); 24 | this->setFixedWidth(300); 25 | 26 | setupLayout(); 27 | readConfig("data/cache/latest_server.json"); 28 | } 29 | 30 | void CreateRoomDialog::setupLayout() { 31 | QVBoxLayout* mainLayout = new QVBoxLayout(this); 32 | 33 | editRoomName = new QLineEdit(this); 34 | editYourName = new QLineEdit(this); 35 | editServerIp = new QLineEdit(this); 36 | editServerPort = new QLineEdit(this); 37 | 38 | QHBoxLayout* serverInfoLayout = new QHBoxLayout(); 39 | serverInfoLayout->addWidget(editServerIp, 3); 40 | serverInfoLayout->addWidget(editServerPort, 1); 41 | 42 | QFormLayout* formLayout = new QFormLayout(); 43 | formLayout->addRow(new QLabel("Room Name: ", this), editRoomName); 44 | formLayout->addRow(new QLabel("Your Name: ", this), editYourName); 45 | formLayout->addRow(new QLabel("Server Addr: ", this), serverInfoLayout); 46 | mainLayout->addLayout(formLayout); 47 | 48 | QHBoxLayout* btnLayout = new QHBoxLayout(); 49 | btnCreate = new QPushButton("Create", this); 50 | btnCancel = new QPushButton("Cancel", this); 51 | editRoomName->setFocus(); 52 | btnCreate->setDefault(true); 53 | connect(btnCreate, &QPushButton::clicked, this, &CreateRoomDialog::onCreateRoom); 54 | connect(btnCancel, &QPushButton::clicked, this, &CreateRoomDialog::close); 55 | btnLayout->addStretch(); 56 | btnLayout->addWidget(btnCreate); 57 | btnLayout->addStretch(); 58 | btnLayout->addWidget(btnCancel); 59 | btnLayout->addStretch(); 60 | mainLayout->addLayout(btnLayout); 61 | } 62 | 63 | 64 | void CreateRoomDialog::onCreateRoom() { 65 | if (editRoomName->text().isEmpty()) { 66 | QMessageBox::critical(this, "Error", "Please input room name", QMessageBox::Ok); 67 | return; 68 | } 69 | if (editYourName->text().isEmpty()) { 70 | QMessageBox::critical(this, "Error", "Please input your name", QMessageBox::Ok); 71 | return; 72 | } 73 | if (editServerIp->text().isEmpty()) { 74 | QMessageBox::critical(this, "Error", "Please input server ip", QMessageBox::Ok); 75 | return; 76 | } 77 | if (editServerPort->text().isEmpty()) { 78 | QMessageBox::critical(this, "Error", "Please input server port", QMessageBox::Ok); 79 | return; 80 | } 81 | 82 | QString roomName = editRoomName->text(); 83 | QString yourName = editYourName->text(); 84 | QString serverIp = editServerIp->text(); 85 | int serverPort = editServerPort->text().toInt(); 86 | 87 | if (yourName.length() > 10) { 88 | QMessageBox::critical(this, "Error", "Your name is too long.\n[MAX: 10]", QMessageBox::Ok); 89 | return; 90 | } 91 | if (editYourName->text().compare("NULL", Qt::CaseInsensitive) == 0 || 92 | editYourName->text().compare("System", Qt::CaseInsensitive) == 0) 93 | { 94 | QMessageBox::critical(this, "Error", "Change name failed. Please try another name.", 95 | QMessageBox::Ok); 96 | return; 97 | } 98 | 99 | Client* client = new Client(); 100 | if (!client->connectServer(serverIp.toStdString().c_str(), serverPort)) { 101 | QMessageBox::critical(this, "Error", "Connect to server failed", QMessageBox::Ok); 102 | delete client; 103 | return; 104 | } 105 | 106 | API::createRoom(client, roomName, yourName); 107 | 108 | Json::Value res; 109 | int ret = client->recvJsonMsg(res); 110 | if (ret <= 0 || !API::isTypeResponse(res, "create_room") || res["room_id"].isNull()) { 111 | QMessageBox::critical(this, "Error", "Create room failed", QMessageBox::Ok); 112 | delete client; 113 | return; 114 | } 115 | 116 | int roomId = res["room_id"].asInt(); 117 | Player* playerYou = new Player(yourName, CHESS_BLACK, true); 118 | Player* playerRival = new Player("NULL", CHESS_WHITE, false); 119 | 120 | ChessOnline* onlineChess = new ChessOnline(playerYou, playerRival, nullptr); 121 | onlineChess->setClient(client); 122 | onlineChess->setRoomId(roomId); 123 | onlineChess->setRoomName(roomName); 124 | onlineChess->updateInfo(); 125 | onlineChess->show(); 126 | 127 | writeConfig("data/cache/latest_server.json"); 128 | this->close(); 129 | } 130 | 131 | 132 | void CreateRoomDialog::readConfig(const char *filename) { 133 | Json::Reader reader; 134 | Json::Value root; 135 | std::ifstream ifs(filename); 136 | 137 | if (!ifs.is_open()) 138 | return; 139 | 140 | // Environment::load(); 141 | editYourName->setText(Env::NAME); 142 | 143 | if (reader.parse(ifs, root, false)) { 144 | if (!root["server_ip"].isNull()) 145 | editServerIp->setText(QString::fromStdString(root["server_ip"].asString())); 146 | if (!root["server_port"].isNull()) 147 | editServerPort->setText(QString::fromStdString(root["server_port"].asString())); 148 | } 149 | 150 | ifs.close(); 151 | } 152 | 153 | void CreateRoomDialog::writeConfig(const char *filename) { 154 | Json::Value root; 155 | std::ofstream ofs(filename); 156 | 157 | if (!ofs.is_open()) 158 | return; 159 | 160 | if (!editServerIp->text().isEmpty()) 161 | root["server_ip"] = editServerIp->text().toStdString(); 162 | if (!editServerPort->text().isEmpty()) 163 | root["server_port"] = editServerPort->text().toStdString(); 164 | 165 | ofs << root.toStyledString(); 166 | ofs.close(); 167 | } 168 | -------------------------------------------------------------------------------- /Gobang/src/dialog/createroomdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef CREATEROOMDIALOG_H 2 | #define CREATEROOMDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../chess/player.h" 9 | 10 | class CreateRoomDialog : public QDialog 11 | { 12 | Q_OBJECT 13 | public: 14 | CreateRoomDialog(QWidget* parent = nullptr); 15 | 16 | public: 17 | void setupLayout(); 18 | 19 | public slots: 20 | void onCreateRoom(); 21 | 22 | private: 23 | void readConfig(const char* filename); 24 | void writeConfig(const char* filename); 25 | 26 | private: 27 | QLineEdit* editRoomName; 28 | QLineEdit* editYourName; 29 | QLineEdit* editServerIp; 30 | QLineEdit* editServerPort; 31 | 32 | QPushButton* btnCreate; 33 | QPushButton* btnCancel; 34 | }; 35 | 36 | #endif // CREATEROOMDIALOG_H 37 | -------------------------------------------------------------------------------- /Gobang/src/dialog/imagecropperdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGECROPPER_H 2 | #define IMAGECROPPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../widget/imagecropperlabel.h" 16 | 17 | /******************************************************* 18 | * Loacl private class, which do image-cropping 19 | * Used in class ImageCropper 20 | *******************************************************/ 21 | class ImageCropperDialogPrivate : public QDialog { 22 | Q_OBJECT 23 | public: 24 | ImageCropperDialogPrivate(const QPixmap& imageIn, QPixmap& outputImage, 25 | int windowWidth, int windowHeight, 26 | CropperShape shape, QSize cropperSize = QSize()) : 27 | QDialog(nullptr), outputImage(outputImage) 28 | { 29 | this->setAttribute(Qt::WA_DeleteOnClose, true); 30 | this->setWindowTitle("Image Cropper"); 31 | this->setMouseTracking(true); 32 | this->setModal(true); 33 | 34 | imageLabel = new ImageCropperLabel(windowWidth, windowHeight, this); 35 | imageLabel->setCropper(shape, cropperSize); 36 | imageLabel->setOutputShape(OutputShape::RECT); 37 | imageLabel->setOriginalImage(imageIn); 38 | imageLabel->enableOpacity(true); 39 | 40 | QHBoxLayout* btnLayout = new QHBoxLayout(); 41 | btnOk = new QPushButton("OK", this); 42 | btnCancel = new QPushButton("Cancel", this); 43 | btnLayout->addStretch(); 44 | btnLayout->addWidget(btnOk); 45 | btnLayout->addWidget(btnCancel); 46 | 47 | QVBoxLayout* mainLayout = new QVBoxLayout(this); 48 | mainLayout->addWidget(imageLabel); 49 | mainLayout->addLayout(btnLayout); 50 | 51 | connect(btnOk, &QPushButton::clicked, this, [this](){ 52 | this->outputImage = this->imageLabel->getCroppedImage(); 53 | this->close(); 54 | }); 55 | connect(btnCancel, &QPushButton::clicked, this, [this](){ 56 | this->outputImage = QPixmap(); 57 | this->close(); 58 | }); 59 | } 60 | 61 | private: 62 | ImageCropperLabel* imageLabel; 63 | QPushButton* btnOk; 64 | QPushButton* btnCancel; 65 | QPixmap& outputImage; 66 | }; 67 | 68 | 69 | /******************************************************************* 70 | * class ImageCropperDialog 71 | * create a instane of class ImageCropperDialogPrivate 72 | * and get cropped image from the instance(after closing) 73 | ********************************************************************/ 74 | class ImageCropperDialog : QObject { 75 | public: 76 | static QPixmap getCroppedImage(const QString& filename,int windowWidth, int windowHeight, 77 | CropperShape cropperShape, QSize crooperSize = QSize()) 78 | { 79 | QPixmap inputImage; 80 | QPixmap outputImage; 81 | 82 | if (!inputImage.load(filename)) { 83 | QMessageBox::critical(nullptr, "Error", "Load image failed!", QMessageBox::Ok); 84 | return outputImage; 85 | } 86 | 87 | ImageCropperDialogPrivate* imageCropperDo = 88 | new ImageCropperDialogPrivate(inputImage, outputImage, 89 | windowWidth, windowHeight, 90 | cropperShape, crooperSize); 91 | imageCropperDo->exec(); 92 | 93 | return outputImage; 94 | } 95 | }; 96 | 97 | 98 | 99 | #endif // IMAGECROPPER_H 100 | -------------------------------------------------------------------------------- /Gobang/src/dialog/joinroomdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "joinroomdialog.h" 2 | #include "../network/api.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include "../network/client.h" 18 | #include "../environment.h" 19 | #include "chessonline.h" 20 | #include "watchchessonline.h" 21 | 22 | 23 | JoinRoomDialog::JoinRoomDialog(GameRole role, QWidget* parent) : 24 | QDialog(parent), role(role) 25 | { 26 | this->setAttribute(Qt::WA_DeleteOnClose, true); 27 | if (role == GameRole::PLAYER) 28 | this->setWindowTitle("Join a room"); 29 | else 30 | this->setWindowTitle("Watch a game"); 31 | this->setFixedWidth(300); 32 | setupLayout(); 33 | readConfig("data/cache/latest_server.json"); 34 | } 35 | 36 | void JoinRoomDialog::setupLayout() { 37 | QVBoxLayout* mainLayout = new QVBoxLayout(this); 38 | 39 | editRoomId = new QLineEdit(this); 40 | editServerIp = new QLineEdit(this); 41 | editServerPort = new QLineEdit(this); 42 | editYourName = new QLineEdit(this); 43 | editRoomId->setValidator(new QIntValidator(1000, 9999, this)); 44 | editRoomId->setFocus(); 45 | 46 | QHBoxLayout* roomIdLayout = new QHBoxLayout(); 47 | roomIdLayout->addWidget(editRoomId); 48 | roomIdLayout->addWidget(new QLabel("(1000 ~ 9999)", this)); 49 | 50 | QHBoxLayout* serverInfoLayout = new QHBoxLayout(); 51 | serverInfoLayout->addWidget(editServerIp, 3); 52 | serverInfoLayout->addWidget(editServerPort, 1); 53 | 54 | QFormLayout* formLayout = new QFormLayout(); 55 | formLayout->addRow(new QLabel("Room ID:", this), roomIdLayout); 56 | formLayout->addRow(new QLabel("Server Addr:", this), serverInfoLayout); 57 | formLayout->addRow(new QLabel("Your Name:", this), editYourName); 58 | mainLayout->addLayout(formLayout); 59 | 60 | btnJoin = new QPushButton("Join", this); 61 | btnCancel = new QPushButton("Cancel", this); 62 | btnPaste = new QPushButton(this); 63 | btnPaste->setIcon(QIcon("res/paste.ico")); 64 | btnPaste->setFlat(true); 65 | btnJoin->setDefault(true); 66 | 67 | QHBoxLayout* btnLayout = new QHBoxLayout(); 68 | btnLayout->addWidget(btnPaste); 69 | btnLayout->addStretch(); 70 | btnLayout->addWidget(btnJoin); 71 | btnLayout->addStretch(); 72 | btnLayout->addStretch(); 73 | btnLayout->addWidget(btnCancel); 74 | btnLayout->addStretch(); 75 | mainLayout->addLayout(btnLayout); 76 | 77 | if (role == GameRole::PLAYER) 78 | connect(btnJoin, &QPushButton::clicked, this, &JoinRoomDialog::onJoinRoomAsPlayer); 79 | else 80 | connect(btnJoin, &QPushButton::clicked, this, &JoinRoomDialog::onJoinRoomAsWatcher); 81 | connect(btnCancel, &QPushButton::clicked, this, &JoinRoomDialog::close); 82 | connect(btnPaste, &QPushButton::clicked, this, &JoinRoomDialog::onPasteFromClipboard); 83 | } 84 | 85 | bool JoinRoomDialog::checkEmpty() { 86 | if (editRoomId->text().isEmpty()) { 87 | QMessageBox::critical(this, "Error", "Please input room id", QMessageBox::Ok); 88 | return false; 89 | } 90 | if (editYourName->text().isEmpty()) { 91 | QMessageBox::critical(this, "Error", "Please input your name", QMessageBox::Ok); 92 | return false; 93 | } 94 | if (editServerIp->text().isEmpty()) { 95 | QMessageBox::critical(this, "Error", "Please input server ip", QMessageBox::Ok); 96 | return false; 97 | } 98 | if (editServerPort->text().isEmpty()) { 99 | QMessageBox::critical(this, "Error", "Please input server port", QMessageBox::Ok); 100 | return false; 101 | } 102 | return true; 103 | } 104 | 105 | void JoinRoomDialog::onJoinRoomAsPlayer() { 106 | if (!checkEmpty()) 107 | return; 108 | 109 | int roomId = editRoomId->text().toInt(); 110 | QString yourName = editYourName->text(); 111 | QString serverIp = editServerIp->text(); 112 | int serverPort = editServerPort->text().toInt(); 113 | 114 | if (yourName.length() > 10) { 115 | QMessageBox::critical(this, "Error", "Your name is too long.\n[MAX: 10]", QMessageBox::Ok); 116 | return; 117 | } 118 | if (editYourName->text().compare("NULL", Qt::CaseInsensitive) == 0 || 119 | editYourName->text().compare("System", Qt::CaseInsensitive) == 0) 120 | { 121 | QMessageBox::critical(this, "Error", "Change name failed. Please try another name.", 122 | QMessageBox::Ok); 123 | return; 124 | } 125 | 126 | Client* client = new Client(); 127 | if (!client->connectServer(serverIp.toStdString().c_str(), serverPort)) { 128 | QMessageBox::critical(this, "Error", "Connect to server failed", QMessageBox::Ok); 129 | delete client; 130 | return; 131 | } 132 | 133 | // Declared in: api.h 134 | API::joinRoom(client, roomId, yourName); 135 | 136 | Json::Value res; 137 | int ret = client->recvJsonMsg(res); 138 | if (ret <= 0 || !API::isTypeResponse(res, "join_room")) { 139 | QMessageBox::critical(this, "Error", "Join room failed", QMessageBox::Ok); 140 | delete client; 141 | return; 142 | } 143 | 144 | if (res["status"].asInt() == STATUS_ERROR) { 145 | QString errMsg = QString::fromStdString(res["desc"].asString()); 146 | QMessageBox::critical(this, "Error", errMsg, QMessageBox::Ok); 147 | delete client; 148 | return; 149 | } 150 | 151 | QString roomName = QString::fromStdString(res["room_name"].asString()); 152 | QString rivalName = QString::fromStdString(res["rival_name"].asString()); 153 | Player* playerYou = new Player(yourName, CHESS_WHITE, true); 154 | Player* playerRival = new Player(rivalName, CHESS_BLACK, false); 155 | Env::NAME = yourName; 156 | 157 | ChessOnline* onlineChess = new ChessOnline(playerYou, playerRival, nullptr); 158 | onlineChess->setClient(client); 159 | onlineChess->setRoomId(roomId); 160 | onlineChess->setRoomName(roomName); 161 | onlineChess->updateInfo(); 162 | onlineChess->show(); 163 | 164 | writeConfig("data/cache/latest_server.json"); 165 | this->close(); 166 | } 167 | 168 | void JoinRoomDialog::onJoinRoomAsWatcher() { 169 | if (!checkEmpty()) 170 | return; 171 | 172 | int roomId = editRoomId->text().toInt(); 173 | QString yourName = editYourName->text(); 174 | QString serverIp = editServerIp->text(); 175 | int serverPort = editServerPort->text().toInt(); 176 | 177 | Client* client = new Client(); 178 | if (!client->connectServer(serverIp.toStdString().c_str(), serverPort)) { 179 | QMessageBox::critical(this, "Error", "Connect to server failed", QMessageBox::Ok); 180 | delete client; 181 | return; 182 | } 183 | 184 | // Declared in: api.h 185 | API::watchRoom(client, roomId, yourName); 186 | 187 | Json::Value res; 188 | int ret = client->recvJsonMsg(res); 189 | if (ret <= 0 || !API::isTypeResponse(res, "watch_room")) { 190 | QMessageBox::critical(this, "Error", "Join the room failed", QMessageBox::Ok); 191 | delete client; 192 | return; 193 | } 194 | 195 | if (res["status"].asInt() == STATUS_ERROR) { 196 | QString errMsg = QString::fromStdString(res["desc"].asString()); 197 | QMessageBox::critical(this, "Error", errMsg, QMessageBox::Ok); 198 | delete client; 199 | return; 200 | } 201 | 202 | QString roomName = QString::fromStdString(res["room_name"].asString()); 203 | 204 | WatchChessOnline* onlineChess = new WatchChessOnline(yourName, nullptr); 205 | onlineChess->setClient(client); 206 | onlineChess->setRoomId(roomId); 207 | onlineChess->setRoomName(roomName); 208 | onlineChess->updateInfo(); 209 | onlineChess->show(); 210 | 211 | writeConfig("data/cache/latest_server.json"); 212 | this->close(); 213 | } 214 | 215 | 216 | // Paste the roomInfo from system clipboard 217 | // 218 | void JoinRoomDialog::onPasteFromClipboard() { 219 | QClipboard* clipboard = QApplication::clipboard(); 220 | QString content = clipboard->text(); 221 | content.replace('\n', ':'); 222 | QStringList list = content.split(':', QString::SkipEmptyParts); 223 | if (list.length() != 8) 224 | return; 225 | for (int i = 0; i < 8; i += 2) { 226 | if (list.at(i).compare("Room ID", Qt::CaseInsensitive) == 0) 227 | editRoomId->setText(list.at(i+1)); 228 | else if (list.at(i).compare("Server Ip", Qt::CaseInsensitive) == 0) 229 | editServerIp->setText(list.at(i+1)); 230 | else if (list.at(i).compare("Server Port", Qt::CaseInsensitive) == 0) 231 | editServerPort->setText(list.at(i+1)); 232 | } 233 | } 234 | 235 | 236 | void JoinRoomDialog::readConfig(const char *filename) { 237 | Json::Reader reader; 238 | Json::Value root; 239 | std::ifstream ifs(filename); 240 | 241 | if (!ifs.is_open()) 242 | return; 243 | 244 | // Environment::load(); 245 | editYourName->setText(Env::NAME); 246 | 247 | if (reader.parse(ifs, root, false)) { 248 | if (!root["server_ip"].isNull()) 249 | editServerIp->setText(QString::fromStdString(root["server_ip"].asString())); 250 | if (!root["server_port"].isNull()) 251 | editServerPort->setText(QString::fromStdString(root["server_port"].asString())); 252 | } 253 | 254 | ifs.close(); 255 | } 256 | 257 | void JoinRoomDialog::writeConfig(const char *filename) { 258 | Json::Value root; 259 | std::ofstream ofs(filename); 260 | 261 | if (!ofs.is_open()) 262 | return; 263 | 264 | if (!editServerIp->text().isEmpty()) 265 | root["server_ip"] = editServerIp->text().toStdString(); 266 | if (!editServerPort->text().isEmpty()) 267 | root["server_port"] = editServerPort->text().toStdString(); 268 | 269 | ofs << root.toStyledString(); 270 | ofs.close(); 271 | } 272 | 273 | -------------------------------------------------------------------------------- /Gobang/src/dialog/joinroomdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef JOINROOMDIALOG_H 2 | #define JOINROOMDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | enum class GameRole { 11 | PLAYER = 0, 12 | WATCHER = 1 13 | }; 14 | 15 | class JoinRoomDialog : public QDialog 16 | { 17 | Q_OBJECT 18 | public: 19 | JoinRoomDialog(GameRole rol, QWidget* parent = nullptr); 20 | ~JoinRoomDialog() { } 21 | 22 | public slots: 23 | void onJoinRoomAsPlayer(); 24 | void onJoinRoomAsWatcher(); 25 | void onPasteFromClipboard(); 26 | 27 | private: 28 | void setupLayout(); 29 | bool checkEmpty(); 30 | void readConfig(const char* filename); 31 | void writeConfig(const char* filename); 32 | 33 | private: 34 | QLineEdit* editRoomId; 35 | QLineEdit* editYourName; 36 | QLineEdit* editServerIp; 37 | QLineEdit* editServerPort; 38 | 39 | QPushButton* btnPaste; 40 | QPushButton* btnJoin; 41 | QPushButton* btnCancel; 42 | 43 | GameRole role; 44 | }; 45 | 46 | #endif // JOINROOMDIALOG_H 47 | -------------------------------------------------------------------------------- /Gobang/src/dialog/settingpanel.cpp: -------------------------------------------------------------------------------- 1 | #include "settingpanel.h" 2 | //#include "../environment.h" 3 | #include "../chess/player.h" 4 | #include "../chess/base.h" 5 | #include "imagecropperdialog.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | SettingPanel::SettingPanel(QWidget* parent, const SettingsInfo& settingsIn, 16 | Player* playerRivalIn) : 17 | QDialog(parent), settings(settingsIn), playerRival(playerRivalIn) 18 | { 19 | this->setAttribute(Qt::WA_DeleteOnClose, true); 20 | this->setWindowTitle("Setting Panel"); 21 | this->setFixedWidth(300); 22 | 23 | bgImg.load("data/cache/bg.png"); 24 | colorTemp = settings.bgColor; 25 | setupLayout(); 26 | } 27 | 28 | void SettingPanel::setupLayout() { 29 | QVBoxLayout* mainLayout = new QVBoxLayout(this); 30 | 31 | labelColor = new QLabel("Color:", this); 32 | labelPicPath = new QLabel("Picture:", this); 33 | labelColorBox = new QLabel(this); 34 | labelTransparency = new QLabel("Transparency:", this); 35 | setBgColor(settings.bgColor); 36 | 37 | editYourName = new QLineEdit(settings.yourName, this); 38 | 39 | btnChooseColor = new QPushButton(this); 40 | btnChoosePicture = new QPushButton(this); 41 | btnResetColor = new QPushButton(this); 42 | btnChooseColor->setFixedWidth(30); 43 | btnResetColor->setFixedWidth(30); 44 | btnChoosePicture->setFixedWidth(30); 45 | btnResetColor->setIcon(QIcon("res/reset.ico")); 46 | btnChooseColor->setIcon(QIcon("res/color-palette.ico")); 47 | btnChoosePicture->setIcon(QIcon("res/select-file.ico")); 48 | connect(btnChooseColor, &QPushButton::clicked, this, &SettingPanel::onChooseColor); 49 | connect(btnChoosePicture, &QPushButton::clicked, this, &SettingPanel::onChoosePicture); 50 | connect(btnResetColor, &QPushButton::clicked, this, &SettingPanel::onResetColor); 51 | 52 | comboBoxBackgroundType = new QComboBox(this); 53 | comboBoxBackgroundType->addItem("Pure Color"); 54 | comboBoxBackgroundType->addItem("Picture"); 55 | connect(comboBoxBackgroundType, SIGNAL(currentIndexChanged(int)), 56 | this, SLOT(onBgTypeChanged(int))); 57 | 58 | QHBoxLayout* bgColorLayout = new QHBoxLayout(); 59 | bgColorLayout->addWidget(labelColorBox); 60 | bgColorLayout->addWidget(btnChooseColor); 61 | bgColorLayout->addWidget(btnResetColor); 62 | 63 | sliderTransparency = new QSlider(Qt::Horizontal, this); 64 | sliderTransparency->setRange(0, 255); 65 | sliderTransparency->setSingleStep(5); 66 | sliderTransparency->setValue(settings.bgTransparency); 67 | 68 | QHBoxLayout* btnLayout = new QHBoxLayout(); 69 | btnApply = new QPushButton("Apply", this); 70 | btnOk = new QPushButton("Ok", this); 71 | btnCancel = new QPushButton("Cancel", this); 72 | btnOk->setFocus(); 73 | btnOk->setDefault(true); 74 | connect(btnApply, &QPushButton::clicked, this, &SettingPanel::onApply); 75 | connect(btnOk, &QPushButton::clicked, this, &SettingPanel::onOk); 76 | connect(btnCancel, &QPushButton::clicked, this, &SettingPanel::close); 77 | btnLayout->addStretch(); 78 | btnLayout->addWidget(btnApply); 79 | btnLayout->addWidget(btnOk); 80 | btnLayout->addWidget(btnCancel); 81 | 82 | QFormLayout* formLayout = new QFormLayout(); 83 | formLayout->addRow(new QLabel("Your Name:", this), editYourName); 84 | formLayout->addRow(new QLabel("Background: ", this), comboBoxBackgroundType); 85 | formLayout->addRow(labelColor, bgColorLayout); 86 | formLayout->addRow(labelPicPath, btnChoosePicture); 87 | formLayout->addRow(labelTransparency, sliderTransparency); 88 | 89 | mainLayout->addLayout(formLayout); 90 | mainLayout->addLayout(btnLayout); 91 | 92 | if (settings.bgType == BG_PURE_COLOR) { 93 | comboBoxBackgroundType->setCurrentIndex(0); 94 | btnChoosePicture->setEnabled(false); 95 | labelPicPath->setEnabled(false); 96 | sliderTransparency->setEnabled(false); 97 | } 98 | else { 99 | comboBoxBackgroundType->setCurrentIndex(1); 100 | btnChooseColor->setEnabled(false); 101 | labelColorBox->setEnabled(false); 102 | labelColor->setEnabled(false); 103 | } 104 | } 105 | 106 | void SettingPanel::setBgColor(QColor color) { 107 | QPixmap pixmap(150, 20); 108 | pixmap.fill(color); 109 | labelColorBox->setPixmap(pixmap); 110 | } 111 | 112 | void SettingPanel::onBgTypeChanged(int idx) { 113 | if (idx == 0) { 114 | btnChooseColor->setEnabled(true); 115 | labelColorBox->setEnabled(true); 116 | labelColor->setEnabled(true); 117 | btnChoosePicture->setEnabled(false); 118 | labelPicPath->setEnabled(false); 119 | sliderTransparency->setEnabled(false); 120 | } 121 | else { 122 | btnChooseColor->setEnabled(false); 123 | labelColorBox->setEnabled(false); 124 | labelColor->setEnabled(false); 125 | btnChoosePicture->setEnabled(true); 126 | labelPicPath->setEnabled(true); 127 | sliderTransparency->setEnabled(true); 128 | } 129 | } 130 | 131 | void SettingPanel::onApply() { 132 | if (editYourName->text().length() > 10) { 133 | QMessageBox::critical(this, "Error", "Your name is too long.\n[MAX: 10]", QMessageBox::Ok); 134 | return; 135 | } 136 | if (editYourName->text().compare("NULL", Qt::CaseInsensitive) == 0 || 137 | editYourName->text().compare("System", Qt::CaseInsensitive) == 0) 138 | { 139 | QMessageBox::critical(this, "Error", "Change name failed. Please try another name.", 140 | QMessageBox::Ok); 141 | return; 142 | } 143 | if (playerRival && editYourName->text().compare(playerRival->getName(), Qt::CaseInsensitive) == 0) { 144 | QMessageBox::critical(this, "Error", "Your name can't be the same with your rival.", 145 | QMessageBox::Ok); 146 | return; 147 | } 148 | 149 | settings.bgType = (comboBoxBackgroundType->currentIndex() == 0 ? BG_PURE_COLOR : BG_PICTURE); 150 | if (settings.bgType == BG_PICTURE) { 151 | if (bgImg.isNull()) { 152 | QMessageBox::critical(this, "Error", "No picture selected", QMessageBox::Ok); 153 | flagClose = false; 154 | return; 155 | } 156 | else { 157 | bgImg.save("data/cache/bg.png", "PNG"); 158 | flagClose = true; 159 | } 160 | } 161 | 162 | settings.yourName = editYourName->text(); 163 | settings.bgColor = colorTemp; 164 | settings.bgTransparency = sliderTransparency->value(); 165 | 166 | emit sigSettingsChanged(this->settings); 167 | } 168 | 169 | void SettingPanel::onOk() { 170 | onApply(); 171 | if (flagClose) 172 | this->close(); 173 | } 174 | 175 | void SettingPanel::onChooseColor() { 176 | QColor tmp = QColorDialog::getColor(colorTemp); 177 | if (tmp.isValid()) { 178 | colorTemp = tmp; 179 | setBgColor(colorTemp); 180 | } 181 | } 182 | 183 | void SettingPanel::onResetColor() { 184 | colorTemp = QColor(200, 150, 100); 185 | setBgColor(colorTemp); 186 | } 187 | 188 | void SettingPanel::onChoosePicture() { 189 | QString filename = QFileDialog::getOpenFileName(this, "Choose a picture", 190 | "", "picture (*.jpg *.png *.bmp)"); 191 | 192 | if (!filename.isNull()) { 193 | bgImg = ImageCropperDialog::getCroppedImage(filename, 600, 400, CropperShape::SQUARE); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /Gobang/src/dialog/settingpanel.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGPANNEL_H 2 | #define SETTINGPANNEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../chess/base.h" 12 | #include "../chess/player.h" 13 | 14 | 15 | struct SettingsInfo { 16 | BackgroundType bgType; 17 | int bgTransparency; 18 | QColor bgColor; 19 | QString yourName; 20 | }; 21 | 22 | 23 | class SettingPanel : public QDialog 24 | { 25 | Q_OBJECT 26 | public: 27 | SettingPanel(QWidget* parent, const SettingsInfo& settingsIn, Player* playerRival); 28 | 29 | SettingsInfo getSettings() { return settings; } 30 | 31 | signals: 32 | void sigSettingsChanged(const SettingsInfo&); 33 | public slots: 34 | void onOk(); 35 | void onApply(); 36 | void onBgTypeChanged(int idx); 37 | void onChooseColor(); 38 | void onChoosePicture(); 39 | void onResetColor(); 40 | 41 | private: 42 | void setupLayout(); 43 | void fillContent(); 44 | void setBgColor(QColor color); 45 | 46 | private: 47 | QLineEdit* editYourName; 48 | 49 | QLabel* labelColor; 50 | QLabel* labelColorBox; 51 | QLabel* labelPicPath; 52 | QLabel* labelTransparency; 53 | 54 | QComboBox* comboBoxBackgroundType; 55 | QSlider* sliderTransparency; 56 | 57 | QPushButton* btnChoosePicture; 58 | QPushButton* btnChooseColor; 59 | QPushButton* btnResetColor; 60 | QPushButton* btnApply; 61 | QPushButton* btnOk; 62 | QPushButton* btnCancel; 63 | 64 | SettingsInfo settings; 65 | Player* playerRival = nullptr; 66 | 67 | QPixmap bgImg; 68 | QColor colorTemp; 69 | 70 | bool flagClose = false; 71 | }; 72 | 73 | #endif // SETTINGPANNEL_H 74 | -------------------------------------------------------------------------------- /Gobang/src/dialog/watchchessonline.h: -------------------------------------------------------------------------------- 1 | #ifndef WATCHCHESSONLINE_H 2 | #define WATCHCHESSONLINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../chess/chessboard.h" 11 | #include "../chess/player.h" 12 | #include "../network/client.h" 13 | #include "../widget/chathistory.h" 14 | #include "settingpanel.h" 15 | 16 | 17 | class WatchChessOnline : public QDialog 18 | { 19 | Q_OBJECT 20 | public: 21 | WatchChessOnline(const QString& yourName, QWidget* parent = nullptr); 22 | ~WatchChessOnline(); 23 | 24 | public: 25 | void setClient(Client* clientIn); 26 | void setRoomName(const QString& nameIn) { roomName = nameIn; } 27 | void setRoomId(int idIn) { roomId = idIn; } 28 | 29 | void updateInfo(); 30 | 31 | // Using for multi-thread 32 | // QWidget(and subclassed) should only be used or modified in GUI thread 33 | // The program may crash if QWidget was used in other thread 34 | // This problem can be solved by using "signals and slots" 35 | signals: 36 | void sigProcessMsgTypeCommand(const Json::Value& root); 37 | void sigProcessMsgTypeNotify(const Json::Value& root); 38 | void sigProcessMsgTypeResponse(const Json::Value& root); 39 | void sigProcessMsgTypeChat(const Json::Value& root); 40 | 41 | public slots: 42 | void onCopyToClipboard(); 43 | void onScreenshot(); 44 | void onShowSettingPanel(); 45 | void onGameWin(int type); 46 | void onGameDraw(); 47 | void onSettingsChanged(const SettingsInfo& settings); 48 | 49 | protected: 50 | virtual void closeEvent(QCloseEvent *) override; 51 | virtual bool eventFilter(QObject *watched, QEvent *event) override; 52 | virtual void keyPressEvent(QKeyEvent* event) override; 53 | 54 | private: 55 | void setupLayout(); 56 | void startRecvMsg(); 57 | void exchangeChessType(); 58 | void gameOver(); 59 | 60 | /******************************* 61 | * Parse and process recv msg 62 | *******************************/ 63 | private: 64 | void parseJsonMsg(const Json::Value& root); 65 | private slots: 66 | void processMsgTypeCommand(const Json::Value& root); 67 | void processMsgTypeNotify(const Json::Value& root); 68 | void processMsgTypeResponse(const Json::Value& root); 69 | void processMsgTypeChat(const Json::Value& root); 70 | 71 | private: 72 | ChessBoard* chessBoard = nullptr; 73 | Client* client = nullptr; 74 | Player player1; 75 | Player player2; 76 | 77 | int roomId; 78 | QString roomName; 79 | QString yourName; 80 | 81 | QPushButton* btnScreenshot = nullptr; 82 | QPushButton* btnSetting = nullptr; 83 | 84 | QLabel* labelRoomId; 85 | QLabel* labelRoomName; 86 | QLabel* labelServerIp; 87 | QLabel* labelServerPort; 88 | QLabel* labelYourName; 89 | QLabel* labelPlayer1Name; 90 | QLabel* labelPlayer2Name; 91 | QLabel* labelPlayer1Turn; 92 | QLabel* labelPlayer2Turn; 93 | 94 | QPixmap whiteChess; 95 | QPixmap blackChess; 96 | QPixmap inPreparation; 97 | QPixmap sameColorWithBg; 98 | QPixmap playerDisconnect; 99 | QPixmap* player1Chess; 100 | QPixmap* player2Chess; 101 | 102 | bool isQuit = false; 103 | bool isForceQuit = false; 104 | bool activeDisconnect = false; 105 | 106 | bool isPlayer1Turn = false; 107 | 108 | ChatHistory* chatHistory; 109 | QTextEdit* chatInput; 110 | }; 111 | 112 | #endif // WATCHCHESSONLINE_H 113 | -------------------------------------------------------------------------------- /Gobang/src/environment.cpp: -------------------------------------------------------------------------------- 1 | #include "environment.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | QString Env::NAME = "player"; 8 | BackgroundType Env::BG_TYPE = BG_PURE_COLOR; 9 | QColor Env::BG_COLOR = QColor(200, 150, 100); 10 | int Env::BG_TRANSPARENCY = 255; 11 | 12 | bool Env::load() { 13 | Json::Value root; 14 | Json::Reader reader; 15 | std::ifstream ifs("data/environment.json"); 16 | if (!ifs.is_open()) { 17 | return true; 18 | } 19 | if (!reader.parse(ifs, root, false)) { 20 | ifs.close(); 21 | return false; 22 | } 23 | 24 | if (!root["NAME"].isNull()) 25 | NAME = QString::fromStdString(root["NAME"].asString()); 26 | if (!root["BG_TYPE"].isNull()) 27 | BG_TYPE = BackgroundType(root["BG_TYPE"].asInt()); 28 | if (!root["BG_COLOR"].isNull()) 29 | BG_COLOR = root["BG_COLOR"].asUInt(); 30 | if (!root["BG_TRANSPARENT"].isNull()) 31 | BG_TRANSPARENCY = root["BG_TRANSPARENT"].asInt(); 32 | 33 | ifs.close(); 34 | return true; 35 | } 36 | 37 | bool Env::save() { 38 | Json::Value root; 39 | std::ofstream ofs("data/environment.json"); 40 | if (!ofs.is_open()) 41 | return false; 42 | 43 | root["NAME"] = NAME.toStdString(); 44 | root["BG_TYPE"] = int(BG_TYPE); 45 | root["BG_COLOR"] = BG_COLOR.rgb(); 46 | root["BG_TRANSPARENT"] =BG_TRANSPARENCY; 47 | 48 | ofs << root.toStyledString(); 49 | ofs.close(); 50 | return true; 51 | } 52 | -------------------------------------------------------------------------------- /Gobang/src/environment.h: -------------------------------------------------------------------------------- 1 | #ifndef ENVIRONMENT_H 2 | #define ENVIRONMENT_H 3 | 4 | #include 5 | #include 6 | #include "chess/base.h" 7 | 8 | class Env { 9 | public: 10 | static QString NAME; 11 | static BackgroundType BG_TYPE; 12 | static QColor BG_COLOR; 13 | static int BG_TRANSPARENCY; 14 | 15 | public: 16 | static bool load(); 17 | static bool save(); 18 | }; 19 | 20 | 21 | #endif // ENVIRONMENT_H 22 | -------------------------------------------------------------------------------- /Gobang/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "network/client.h" 3 | 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | Client::InitNetwork(); 9 | 10 | QApplication a(argc, argv); 11 | MainWindow w; 12 | w.show(); 13 | return a.exec(); 14 | } 15 | -------------------------------------------------------------------------------- /Gobang/src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "environment.h" 3 | 4 | #include "dialog/createroomdialog.h" 5 | #include "dialog/joinroomdialog.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) 12 | { 13 | this->setWindowTitle("Gobang"); 14 | //this->setFixedSize(260, 130); 15 | Env::load(); 16 | 17 | init(); 18 | setupLayout(); 19 | } 20 | 21 | MainWindow::~MainWindow() { 22 | Env::save(); 23 | } 24 | 25 | void MainWindow::init() { 26 | QDir dir; 27 | if (!dir.exists("data")) 28 | dir.mkdir("data"); 29 | if (!dir.exists("data/cache")) 30 | dir.mkdir("data/cache"); 31 | } 32 | 33 | void MainWindow::setupLayout() { 34 | QWidget* centralWidget = new QWidget(this); 35 | this->setCentralWidget(centralWidget); 36 | btnCreateRoom = new QPushButton("Create New Room", centralWidget); 37 | btnJoinRoom = new QPushButton("Join a Room", centralWidget); 38 | btnWatchLive = new QPushButton("Watch a live", centralWidget); 39 | 40 | QVBoxLayout* mainLayout = new QVBoxLayout(centralWidget); 41 | mainLayout->addWidget(btnCreateRoom); 42 | mainLayout->addWidget(btnJoinRoom); 43 | mainLayout->addWidget(btnWatchLive); 44 | 45 | connect(btnCreateRoom, &QPushButton::clicked, this, []{ 46 | CreateRoomDialog* dialogCreateRoom = new CreateRoomDialog(nullptr); 47 | dialogCreateRoom->show(); 48 | }); 49 | connect(btnJoinRoom, &QPushButton::clicked, this, []{ 50 | JoinRoomDialog* dialogJoinRoom = new JoinRoomDialog(GameRole::PLAYER, nullptr); 51 | dialogJoinRoom->show(); 52 | }); 53 | connect(btnWatchLive, &QPushButton::clicked, this, []{ 54 | JoinRoomDialog* dialogJoinRoom = new JoinRoomDialog(GameRole::WATCHER, nullptr); 55 | dialogJoinRoom->show(); 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /Gobang/src/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | 7 | 8 | class MainWindow : public QMainWindow 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit MainWindow(QWidget *parent = nullptr); 13 | ~MainWindow(); 14 | 15 | void init(); 16 | void setupLayout(); 17 | 18 | private: 19 | QPushButton* btnCreateRoom; 20 | QPushButton* btnJoinRoom; 21 | QPushButton* btnWatchLive; 22 | }; 23 | 24 | #endif // MAINWINDOW_H 25 | -------------------------------------------------------------------------------- /Gobang/src/network/api.cpp: -------------------------------------------------------------------------------- 1 | #include "api.h" 2 | 3 | #include 4 | 5 | namespace API { 6 | 7 | /*********************** 8 | * Local functions 9 | ***********************/ 10 | static bool sendSimpleCmd(Client* client, const std::string& cmd) { 11 | Json::Value root; 12 | root["type"] = "command"; 13 | root["cmd"] = cmd; 14 | return client->sendJsonMsg(root); 15 | } 16 | 17 | /****************************************** 18 | * Check recieved message's type 19 | ******************************************/ 20 | bool isTypeCommand(const Json::Value& root, const std::string& cmd_name) { 21 | return !root["type"].isNull() && root["type"].asString() == "command" && 22 | !root["cmd"].isNull() && root["cmd"].asString() == cmd_name; 23 | } 24 | 25 | bool isTypeNotify(const Json::Value& root, const std::string& sub_type) { 26 | return !root["type"].isNull() && root["type"].asString() == "notify" && 27 | !root["sub_type"].isNull() && root["sub_type"].asString() == sub_type; 28 | } 29 | 30 | bool isTypeResponse(const Json::Value& root, const std::string& res_cmd) { 31 | return !root["type"].isNull() && root["type"].asString() == "response" && 32 | !root["res_cmd"].isNull() && root["res_cmd"].asString() == res_cmd && 33 | !root["status"].isNull(); 34 | } 35 | 36 | bool createRoom(Client* client, const QString& room_name, const QString& your_name) { 37 | Json::Value root; 38 | root["type"] = "command"; 39 | root["cmd"] = "create_room"; 40 | root["room_name"] = room_name.toStdString(); 41 | root["player_name"] = your_name.toStdString(); 42 | return client->sendJsonMsg(root); 43 | } 44 | 45 | bool joinRoom(Client* client, int room_id, const QString& your_name) { 46 | Json::Value root; 47 | root["type"] = "command"; 48 | root["cmd"] = "join_room"; 49 | root["room_id"] = room_id; 50 | root["player_name"] = your_name.toStdString(); 51 | return client->sendJsonMsg(root); 52 | } 53 | 54 | bool watchRoom(Client* client, int room_id, const QString& your_name) { 55 | Json::Value root; 56 | root["type"] = "command"; 57 | root["cmd"] = "watch_room"; 58 | root["room_id"] = room_id; 59 | root["player_name"] = your_name.toStdString(); 60 | return client->sendJsonMsg(root); 61 | } 62 | 63 | bool exchangeChessType(Client* client) { 64 | return sendSimpleCmd(client, "exchange"); 65 | } 66 | 67 | bool prepareGame(Client* client, const QString& player_name) { 68 | Json::Value root; 69 | root["type"] = "command"; 70 | root["cmd"] = "prepare"; 71 | root["player_name"] = player_name.toStdString(); 72 | return client->sendJsonMsg(root); 73 | } 74 | 75 | bool cancelPrepareGame(Client* client, const QString& player_name) { 76 | Json::Value root; 77 | root["type"] = "command"; 78 | root["cmd"] = "cancel_prepare"; 79 | root["player_name"] = player_name.toStdString(); 80 | return client->sendJsonMsg(root); 81 | } 82 | 83 | 84 | /*********************** 85 | * Type: Response 86 | ***********************/ 87 | bool responseExchageChessType(Client* client, bool yesOrNo) { 88 | Json::Value root; 89 | root["type"] = "response"; 90 | root["res_cmd"] = "exchange"; 91 | root["accept"] = yesOrNo; 92 | return client->sendJsonMsg(root); 93 | } 94 | 95 | /************************* 96 | * Type: Notify 97 | *************************/ 98 | bool notifyNewPiece(Client* client, int row, int col, int chess_type) { 99 | Json::Value root; 100 | root["type"] = "notify"; 101 | root["sub_type"] = "new_piece"; 102 | root["row"] = row; 103 | root["col"] = col; 104 | root["chess_type"] = chess_type; 105 | return client->sendJsonMsg(root); 106 | } 107 | 108 | bool notifyRivalInfo(Client* client, const QString& player_name) { 109 | Json::Value root; 110 | root["type"] = "notify"; 111 | root["sub_type"] = "rival_info"; 112 | root["player_name"] = player_name.toStdString(); 113 | return client->sendJsonMsg(root); 114 | } 115 | 116 | bool notifyGameOverWin(Client* client, int chess_type) { 117 | Json::Value root; 118 | root["type"] = "notify"; 119 | root["sub_type"] = "game_over"; 120 | root["game_result"] = "win"; 121 | root["chess_type"] = chess_type; 122 | return client->sendJsonMsg(root); 123 | } 124 | 125 | bool notifyGameOverDraw(Client* client) { 126 | Json::Value root; 127 | root["type"] = "notify"; 128 | root["sub_type"] = "game_over"; 129 | root["game_result"] = "draw"; 130 | root["chess_type"] = 0; // 0 == CHESS_NULL 131 | return client->sendJsonMsg(root); 132 | } 133 | 134 | bool sendChatMessage(Client* client, const QString& msg, const QString& sender) { 135 | Json::Value root; 136 | root["type"] = "chat"; 137 | root["message"] = msg.toStdString(); 138 | root["sender"] = sender.toStdString(); 139 | return client->sendJsonMsg(root); 140 | } 141 | 142 | } // namespace API 143 | -------------------------------------------------------------------------------- /Gobang/src/network/api.h: -------------------------------------------------------------------------------- 1 | #ifndef API_H 2 | #define API_H 3 | 4 | #include 5 | #include 6 | #include "client.h" 7 | 8 | const int STATUS_OK = 0; 9 | const int STATUS_ERROR = 1; 10 | 11 | namespace API { 12 | 13 | bool isTypeCommand(const Json::Value& root, const std::string& cmd_name); 14 | bool isTypeNotify(const Json::Value& root, const std::string& sub_type); 15 | bool isTypeResponse(const Json::Value& root, const std::string& res_cmd); 16 | 17 | bool createRoom(Client* client, const QString& room_name, const QString& your_name); 18 | bool joinRoom(Client* client, int room_id, const QString& your_name); 19 | bool watchRoom(Client* client, int room_id, const QString& your_name); 20 | bool exchangeChessType(Client* client); 21 | bool prepareGame(Client* client, const QString& player_name); 22 | bool cancelPrepareGame(Client* client, const QString& player_name); 23 | 24 | bool responseExchageChessType(Client* client, bool yesOrNo); 25 | 26 | bool notifyNewPiece(Client* client, int row, int col, int chess_type); 27 | bool notifyRivalInfo(Client* client, const QString& player_name); 28 | bool notifyGameOverWin(Client* client, int chess_type); 29 | bool notifyGameOverDraw(Client* client); 30 | 31 | bool sendChatMessage(Client* client, const QString& msg, const QString& sender); 32 | 33 | } 34 | 35 | #endif // API_H 36 | -------------------------------------------------------------------------------- /Gobang/src/network/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #ifdef WIN32 9 | #include 10 | #include 11 | #pragma comment(lib, "ws2_32.lib") 12 | #else 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #endif 19 | 20 | 21 | Client::~Client() { 22 | } 23 | 24 | // Just for win32 25 | // 26 | bool Client::InitNetwork() { 27 | #ifdef WIN32 28 | WORD sockVersion = MAKEWORD(2, 2); 29 | WSADATA wsaData; 30 | return WSAStartup(sockVersion, &wsaData) == 0; 31 | #endif 32 | } 33 | 34 | void Client::disconnect() { 35 | if (socketfd > 0) { 36 | //this->closesocket(); 37 | shutdown(socketfd, 2); 38 | this->closesocket(); 39 | qDebug() << "disconnectd"; 40 | } 41 | } 42 | 43 | void Client::closesocket() { 44 | #ifdef WIN32 45 | ::closesocket(socketfd); 46 | #else 47 | close(socketfd); 48 | #endif 49 | } 50 | 51 | bool Client::connectServer(const char* servAddrStr, int port) { 52 | if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) 53 | return false; 54 | 55 | struct sockaddr_in servAddr; 56 | memset(&servAddr, 0, sizeof(servAddr)); 57 | servAddr.sin_family = AF_INET; 58 | servAddr.sin_port = htons(port); 59 | servAddr.sin_addr.s_addr = inet_addr(servAddrStr); 60 | 61 | if (connect(socketfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0) { 62 | this->closesocket(); 63 | return false; 64 | } 65 | 66 | serverIp = servAddrStr; 67 | serverPort = port; 68 | return true; 69 | } 70 | 71 | bool Client::sendJsonMsg(const Json::Value &json) { 72 | return sendJsonMsg(Json::FastWriter().write(json)); 73 | } 74 | 75 | bool Client::sendJsonMsg(const std::string& msg) { 76 | if (msg.empty()) 77 | return false; 78 | 79 | int len = msg.length(); 80 | std::string msgSend; 81 | msgSend.reserve(12 + len); 82 | msgSend += "length:"; 83 | msgSend += std::to_string(len); 84 | if (len < 10) 85 | msgSend += " "; 86 | else if (len < 100) 87 | msgSend += " "; 88 | else if (len < 1000) 89 | msgSend += " "; 90 | msgSend += "\n"; 91 | msgSend += msg; 92 | 93 | qDebug() << "Sending Msg: "; 94 | qDebug() << "**************************************"; 95 | qDebug() << QString::fromStdString(msgSend); 96 | qDebug() << "**************************************"; 97 | 98 | send(socketfd, msgSend.c_str(), len + 12, 0); 99 | return true; 100 | } 101 | 102 | 103 | int Client::recvJsonMsg(Json::Value& root) { 104 | char temp[8] = { 0 }; 105 | char lengthStr[5] = { 0 }; 106 | char msgLengthInfo[13] = { 0 }; 107 | 108 | int n = recv(socketfd, msgLengthInfo, 12, 0); 109 | if (n <= 0) 110 | return -1; 111 | if (n < 12) 112 | return 0; 113 | 114 | memcpy(temp, msgLengthInfo, 7); 115 | memcpy(lengthStr, msgLengthInfo+7, 4); 116 | temp[7] = 0; 117 | if (strcmp(temp, "length:") != 0) 118 | return 0; 119 | 120 | int msgLength = 0; 121 | sscanf(lengthStr, "%d", &msgLength); 122 | 123 | char* jsonMsg = new char[msgLength+1]; 124 | jsonMsg[msgLength] = 0; 125 | n = recv(socketfd, jsonMsg, msgLength, 0); 126 | 127 | bool ret = 0; 128 | 129 | do { 130 | if (n <= 0) { 131 | ret = -1; 132 | break; 133 | } 134 | if (n < msgLength) { 135 | break; 136 | } 137 | 138 | Json::Reader reader; 139 | if (!reader.parse(jsonMsg, root)) 140 | break; 141 | 142 | ret = 1; 143 | } while (false); 144 | 145 | if (ret == 1) { 146 | qDebug() << "Recving Msg: "; 147 | qDebug() << "**************************************"; 148 | qDebug() << QString(jsonMsg); 149 | qDebug() << "**************************************"; 150 | } 151 | 152 | delete[] jsonMsg; 153 | return ret; 154 | } 155 | -------------------------------------------------------------------------------- /Gobang/src/network/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | 7 | class Client { 8 | public: 9 | Client() {} 10 | ~Client(); 11 | public: 12 | static bool InitNetwork(); 13 | 14 | bool connectServer(const char* servAddr, int port); 15 | void closesocket(); 16 | void disconnect(); 17 | 18 | bool sendJsonMsg(const Json::Value& json); 19 | bool sendJsonMsg(const std::string& msg); 20 | int recvJsonMsg(Json::Value& root); 21 | 22 | const char* getServerIp() const { return serverIp.c_str(); } 23 | int getServerPort() const { return serverPort; } 24 | 25 | private: 26 | 27 | #ifdef WIN32 28 | unsigned long long socketfd = 0; 29 | #else 30 | int socketfd = 0; 31 | #endif 32 | std::string serverIp; 33 | int serverPort; 34 | }; 35 | 36 | #endif // CLIENT_H 37 | 38 | -------------------------------------------------------------------------------- /Gobang/src/widget/chathistory.cpp: -------------------------------------------------------------------------------- 1 | #include "chathistory.h" 2 | #include 3 | #include 4 | 5 | ChatHistory::ChatHistory(QWidget* parent) : 6 | QTextEdit(parent) 7 | { 8 | this->setReadOnly(true); 9 | } 10 | 11 | void ChatHistory::addNewChat(const QString &name, const QString &chatContent, 12 | const QColor& headerColor, const QColor& contentColor) { 13 | time_t t = time(nullptr); 14 | char now[16]; 15 | strftime(now, sizeof(now), "%H:%M:%S", localtime(&t)); 16 | 17 | QString header = QString("%1 [%2]\n ").arg(name).arg(now); 18 | 19 | this->moveCursor(QTextCursor::End); 20 | this->setTextColor(headerColor); 21 | this->insertPlainText(header); 22 | this->setTextColor(contentColor); 23 | this->insertPlainText(chatContent); 24 | this->insertPlainText("\n"); 25 | this->moveCursor(QTextCursor::End); 26 | } 27 | -------------------------------------------------------------------------------- /Gobang/src/widget/chathistory.h: -------------------------------------------------------------------------------- 1 | #ifndef CHATHISTORY_H 2 | #define CHATHISTORY_H 3 | 4 | #include 5 | #include 6 | 7 | class ChatHistory : public QTextEdit { 8 | public: 9 | ChatHistory(QWidget* parent = nullptr); 10 | 11 | void addNewChat(const QString& name, const QString& chatContent, 12 | const QColor& color = Qt::blue, const QColor& contentColor = Qt::black); 13 | }; 14 | 15 | #endif // CHATHISTORY_H 16 | -------------------------------------------------------------------------------- /Gobang/src/widget/chatinput.cpp: -------------------------------------------------------------------------------- 1 | #include "chatinput.h" 2 | 3 | ChatInput::ChatInput() 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /Gobang/src/widget/chatinput.h: -------------------------------------------------------------------------------- 1 | #ifndef CHATINPUT_H 2 | #define CHATINPUT_H 3 | 4 | #include 5 | #include 6 | 7 | class ChatInput : public QTextEdit 8 | { 9 | Q_OBJECT 10 | public: 11 | ChatInput(); 12 | }; 13 | 14 | #endif // CHATINPUT_H 15 | -------------------------------------------------------------------------------- /Gobang/src/widget/imagecropperlabel.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * class: ImageCropperLabel 3 | * author: github@Leopard-C 4 | * email: leopard.c@outlook.com 5 | * last change: 2020-03-06 6 | *************************************************************************/ 7 | #ifndef IMAGECROPPERLABEL_H 8 | #define IMAGECROPPERLABEL_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | enum class CropperShape { 15 | UNDEFINED = 0, 16 | RECT = 1, 17 | SQUARE = 2, 18 | FIXED_RECT = 3, 19 | ELLIPSE = 4, 20 | CIRCLE = 5, 21 | FIXED_ELLIPSE = 6 22 | }; 23 | 24 | enum class OutputShape { 25 | RECT = 0, 26 | ELLIPSE = 1 27 | }; 28 | 29 | enum class SizeType { 30 | fixedSize = 0, 31 | fitToMaxWidth = 1, 32 | fitToMaxHeight = 2, 33 | fitToMaxWidthHeight = 3, 34 | }; 35 | 36 | 37 | class ImageCropperLabel : public QLabel { 38 | Q_OBJECT 39 | public: 40 | ImageCropperLabel(int width, int height, QWidget* parent); 41 | 42 | void setOriginalImage(const QPixmap& pixmap); 43 | void setOutputShape(OutputShape shape) { outputShape = shape; } 44 | QPixmap getCroppedImage(); 45 | QPixmap getCroppedImage(OutputShape shape); 46 | 47 | /***************************************** 48 | * Set cropper's shape 49 | *****************************************/ 50 | void setRectCropper(); 51 | void setSquareCropper(); 52 | void setEllipseCropper(); 53 | void setCircleCropper(); 54 | void setFixedRectCropper(QSize size); 55 | void setFixedEllipseCropper(QSize size); 56 | void setCropper(CropperShape shape, QSize size); // not recommended 57 | 58 | /***************************************************************************** 59 | * Set cropper's fixed size 60 | *****************************************************************************/ 61 | void setCropperFixedSize(int fixedWidth, int fixedHeight); 62 | void setCropperFixedWidth(int fixedWidht); 63 | void setCropperFixedHeight(int fixedHeight); 64 | 65 | /***************************************************************************** 66 | * Set cropper's minimum size 67 | * default: the twice of minimum of the edge lenght of drag square 68 | *****************************************************************************/ 69 | void setCropperMinimumSize(int minWidth, int minHeight) 70 | { cropperMinimumWidth = minWidth; cropperMinimumHeight = minHeight; } 71 | void setCropperMinimumWidth(int minWidth) { cropperMinimumWidth = minWidth; } 72 | void setCropperMinimumHeight(int minHeight) { cropperMinimumHeight = minHeight; } 73 | 74 | /************************************************* 75 | * Set the size, color, visibility of rectangular border 76 | *************************************************/ 77 | void setShowRectBorder(bool show) { isShowRectBorder = show; } 78 | QPen getBorderPen() { return borderPen; } 79 | void setBorderPen(const QPen& pen) { borderPen = pen; } 80 | 81 | /************************************************* 82 | * Set the size, color of drag square 83 | *************************************************/ 84 | void setShowDragSquare(bool show) { isShowDragSquare = show; } 85 | void setDragSquareEdge(int edge) { dragSquareEdge = (edge >= 3 ? edge : 3); } 86 | void setDragSquareColor(const QColor& color) { dragSquareColor = color; } 87 | 88 | /***************************************** 89 | * Opacity Effect 90 | *****************************************/ 91 | void enableOpacity(bool b = true) { isShowOpacityEffect = b; } 92 | void setOpacity(double newOpacity) { opacity = newOpacity; } 93 | 94 | signals: 95 | void croppedImageChanged(); 96 | 97 | protected: 98 | /***************************************** 99 | * Event 100 | *****************************************/ 101 | virtual void paintEvent(QPaintEvent *event) override; 102 | virtual void mousePressEvent(QMouseEvent *e) override; 103 | virtual void mouseMoveEvent(QMouseEvent *e) override; 104 | virtual void mouseReleaseEvent(QMouseEvent *e) override; 105 | 106 | private: 107 | /*************************************** 108 | * Draw shapes 109 | ***************************************/ 110 | void drawFillRect(QPoint centralPoint, int edge, QColor color); 111 | void drawRectOpacity(); 112 | void drawEllipseOpacity(); 113 | void drawOpacity(const QPainterPath& path); // shadow effect 114 | void drawSquareEdge(bool onlyFourCorners); 115 | 116 | /*************************************** 117 | * Other utility methods 118 | ***************************************/ 119 | int getPosInCropperRect(const QPoint& pt); 120 | bool isPosNearDragSquare(const QPoint& pt1, const QPoint& pt2); 121 | void resetCropperPos(); 122 | void changeCursor(); 123 | 124 | enum { 125 | RECT_OUTSIZD = 0, 126 | RECT_INSIDE = 1, 127 | RECT_TOP_LEFT, RECT_TOP, RECT_TOP_RIGHT, RECT_RIGHT, 128 | RECT_BOTTOM_RIGHT, RECT_BOTTOM, RECT_BOTTOM_LEFT, RECT_LEFT 129 | }; 130 | 131 | const bool ONLY_FOUR_CORNERS = true; 132 | 133 | private: 134 | QPixmap originalImage; 135 | QPixmap tempImage; 136 | 137 | bool isShowRectBorder = true; 138 | QPen borderPen; 139 | 140 | CropperShape cropperShape = CropperShape::UNDEFINED; 141 | OutputShape outputShape = OutputShape::RECT; 142 | 143 | QRect imageRect; // the whole image area in the label (not real size) 144 | QRect cropperRect; // a rectangle frame to choose image area (not real size) 145 | QRect cropperRect_; // cropper rect (real size) 146 | double scaledRate = 1.0; 147 | 148 | bool isLButtonPressed = false; 149 | bool isCursorPosCalculated = false; 150 | int cursorPosInCropperRect = RECT_OUTSIZD; 151 | QPoint lastPos; 152 | QPoint currPos; 153 | 154 | bool isShowDragSquare = true; 155 | int dragSquareEdge = 8; 156 | QColor dragSquareColor = Qt::white; 157 | 158 | int cropperMinimumWidth = dragSquareEdge * 2; 159 | int cropperMinimumHeight = dragSquareEdge * 2; 160 | 161 | bool isShowOpacityEffect = false; 162 | double opacity = 0.6; 163 | }; 164 | 165 | #endif // IMAGECROPPERLABEL_H 166 | -------------------------------------------------------------------------------- /GobangServer/src/api.cpp: -------------------------------------------------------------------------------- 1 | #include "api.h" 2 | #include "socket_func.h" 3 | 4 | #include "jsoncpp/json/writer.h" 5 | #include 6 | 7 | namespace API { 8 | 9 | 10 | /*********************** 11 | * Local functions 12 | ***********************/ static bool sendSimpleCmd(SocketFD fd, const std::string& cmd) { Json::Value root; 13 | root["type"] = "command"; 14 | root["cmd"] = cmd; 15 | return sendJsonMsg(root, fd); 16 | } 17 | 18 | static bool sendSimpleRes(SocketFD fd, const std::string& res_cmd, 19 | int status_code, const std::string desc) { 20 | Json::Value root; 21 | root["type"] = "response"; 22 | root["res_cmd"] = res_cmd; 23 | root["status"] = status_code; 24 | root["desc"] = desc; 25 | return sendJsonMsg(root, fd); 26 | } 27 | 28 | static bool sendSimpleNotify(SocketFD fd, const std::string& sub_type) { 29 | Json::Value root; 30 | root["type"] = "notify"; 31 | root["sub_type"] = sub_type; 32 | return sendJsonMsg(root, fd); 33 | } 34 | 35 | 36 | /****************************************** 37 | * Check recieved message's type 38 | ******************************************/ 39 | bool isTypeCommand(const Json::Value& root, const std::string& cmd) { 40 | return !root["type"].isNull() && root["type"].asString() == "command" 41 | && !root["cmd"].isNull() && root["cmd"].asString() == cmd; 42 | } 43 | 44 | bool isTypeNotify(const Json::Value& root, const std::string& sub_type) { 45 | return !root["type"].isNull() && root["type"].asString() == "notify" 46 | && !root["sub_type"].isNull() && root["sub_type"] == sub_type; 47 | } 48 | 49 | 50 | /************************************** 51 | * Just forward to the other player 52 | **************************************/ 53 | bool forward(SocketFD fd, const Json::Value& root) { 54 | return sendJsonMsg(root, fd); 55 | } 56 | 57 | 58 | /*********************** 59 | * Type: Response 60 | ***********************/ 61 | bool responseCreateRoom(SocketFD fd, int status_code, const std::string& desc, int room_id) { 62 | Json::Value root; 63 | root["type"] = "response"; 64 | root["res_cmd"] = "create_room"; 65 | root["status"] = status_code; 66 | root["desc"] = desc; 67 | root["room_id"] = room_id; 68 | return sendJsonMsg(root, fd); 69 | } 70 | 71 | bool responseJoinRoom(SocketFD fd, int status_code, const std::string &desc, 72 | const std::string room_name, const std::string rival_name) { 73 | Json::Value root; 74 | root["type"] = "response"; 75 | root["res_cmd"] = "join_room"; 76 | root["status"] = status_code; 77 | root["desc"] = desc; 78 | root["room_name"] = room_name; 79 | root["rival_name"] = rival_name; 80 | return sendJsonMsg(root, fd); 81 | } 82 | 83 | bool responseWatchRoom(SocketFD fd, int status_code, const std::string& desc, 84 | const std::string room_name) { 85 | Json::Value root; 86 | root["type"] = "response"; 87 | root["res_cmd"] = "watch_room"; 88 | root["status"] = status_code; 89 | root["desc"] = desc; 90 | root["room_name"] = room_name; 91 | return sendJsonMsg(root, fd); 92 | } 93 | 94 | bool responsePrepare(SocketFD fd, int status_code, const std::string& desc) { 95 | return sendSimpleRes(fd, "prepare", status_code, desc); 96 | } 97 | 98 | 99 | /************************* 100 | * Type: Notify 101 | *************************/ 102 | bool sendChessBoard(SocketFD fd, int chessPieces[][15], ChessPieceInfo last_piece) { 103 | Json::Value root; 104 | Json::Value chessboard; 105 | Json::Value lastChess; 106 | root["type"] = "notify"; 107 | root["sub_type"] = "chessboard"; 108 | 109 | for (int row = 0; row < 15; ++row) { 110 | for (int col = 0; col < 15; ++col) { 111 | chessboard.append(chessPieces[row][col]); 112 | } 113 | } 114 | root["layout"] = chessboard; 115 | 116 | lastChess["row"] = last_piece.row; 117 | lastChess["col"] = last_piece.col; 118 | lastChess["type"] = last_piece.type; 119 | root["last_piece"] = lastChess; 120 | 121 | return sendJsonMsg(root, fd); 122 | } 123 | 124 | bool notifyRivalInfo(SocketFD fd, const std::string& player_name) { 125 | Json::Value root; 126 | root["type"] = "notify"; 127 | root["sub_type"] = "rival_info"; 128 | root["player_name"] = player_name; 129 | return sendJsonMsg(root, fd); 130 | } 131 | 132 | bool notifyNewPiece(SocketFD fd, int row, int col, int chess_type) { 133 | Json::Value root; 134 | root["type"] = "notify"; 135 | root["sub_type"] = "new_piece"; 136 | root["row"] = row; 137 | root["col"] = col; 138 | root["chess_type"] = chess_type; 139 | return sendJsonMsg(root, fd); 140 | } 141 | 142 | bool notifyGameStart(SocketFD fd) { 143 | return sendSimpleNotify(fd, "game_start"); 144 | } 145 | 146 | bool notifyGameCancelPrepare(SocketFD fd) { 147 | return sendSimpleNotify(fd, "cancel_prepare"); 148 | } 149 | 150 | bool notifyDisconnect(SocketFD fd, const std::string& player_name) { 151 | Json::Value root; 152 | root["type"] = "notify"; 153 | root["sub_type"] = "disconnect"; 154 | root["player_name"] = player_name; 155 | return sendJsonMsg(root, fd); 156 | } 157 | 158 | bool notifyPlayerInfo(SocketFD fd, const std::string& player1_name, int player1_chess_type, 159 | const std::string& player2_name, int player2_chess_type) { 160 | Json::Value root; 161 | root["type"] = "notify"; 162 | root["sub_type"] = "player_info"; 163 | root["player1_name"] = player1_name; 164 | root["player1_chess_type"] = player1_chess_type; 165 | root["player2_name"] = player2_name; 166 | root["player2_chess_type"] = player2_chess_type; 167 | return sendJsonMsg(root, fd); 168 | } 169 | 170 | 171 | }; // namespace API 172 | 173 | -------------------------------------------------------------------------------- /GobangServer/src/api.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "jsoncpp/json/json.h" 3 | #include "socket_func.h" 4 | #include "base.h" 5 | 6 | const int STATUS_OK = 0; 7 | const int STATUS_ERROR = 1; 8 | 9 | namespace API { 10 | 11 | bool isTypeCommand(const Json::Value& root, const std::string& cmd); 12 | bool isTypeNotify(const Json::Value& root, const std::string& sub_type); 13 | 14 | bool forward(SocketFD fd, const Json::Value& root); 15 | 16 | // Type: Response 17 | bool responseCreateRoom(SocketFD fd, int status_code, const std::string& desc, int room_id); 18 | bool responseJoinRoom(SocketFD fd, int status_code, const std::string& desc, 19 | const std::string room_name, const std::string rival_name); 20 | bool responseWatchRoom(SocketFD fd, int status_code, const std::string& desc, 21 | const std::string room_name); 22 | bool responsePrepare(SocketFD fd, int status_code, const std::string& desc); 23 | 24 | // Type: command 25 | bool sendChessBoard(SocketFD fd, int chessPieces[][15], ChessPieceInfo last_piece); 26 | 27 | // Tyep: Notify 28 | bool notifyRivalInfo(SocketFD fd, const std::string& player_name); 29 | bool notifyNewPiece(SocketFD fd, int row, int col, int chess_type); 30 | bool notifyGameStart(SocketFD fd); 31 | bool notifyGameCancelPrepare(SocketFD fd); 32 | bool notifyDisconnect(SocketFD fd, const std::string& player_name); 33 | bool notifyPlayerInfo(SocketFD fd, const std::string& player1_name, int player1_chess_type, 34 | const std::string& player2_name, int player2_chess_type); 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /GobangServer/src/base.cpp: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | ChessType reverse(ChessType typeIn) { 4 | return ChessType(-1 * typeIn); 5 | } 6 | -------------------------------------------------------------------------------- /GobangServer/src/base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum ChessType { 4 | CHESS_BLACK = -1, 5 | CHESS_NULL = 0, 6 | CHESS_WHITE = 1 7 | }; 8 | 9 | struct ChessPieceInfo { 10 | int row; 11 | int col; 12 | int type; 13 | }; 14 | 15 | ChessType reverse(ChessType typeIn); 16 | 17 | -------------------------------------------------------------------------------- /GobangServer/src/gobangserver.cpp: -------------------------------------------------------------------------------- 1 | #include "gobangserver.h" 2 | 3 | #include "api.h" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | GobangServer::GobangServer() : 15 | pool(10) 16 | { 17 | #ifdef WIN32 18 | WORD sockVersion = MAKEWORD(2, 2); 19 | WSADATA wsaData; 20 | WSAStartup(sockVersion, &wsaData); 21 | #endif 22 | 23 | pool.enqueue([this](){ 24 | while (isRunning) { 25 | std::cout << "Rooms in use: " << rooms.size() << std::endl; 26 | for (auto it = rooms.begin(); it != rooms.end(); ) { 27 | if ((*it)->shouldDelete()) { 28 | std::cout << "Deleting room: " << (*it)->getId() << std::endl; 29 | delete (*it); 30 | it = rooms.erase(it); 31 | } 32 | else { 33 | ++it; 34 | } 35 | } 36 | 37 | if (rooms.size() == 0) 38 | std::this_thread::sleep_for(std::chrono::seconds(5)); 39 | else 40 | std::this_thread::sleep_for(std::chrono::seconds(1)); 41 | } 42 | }); 43 | } 44 | 45 | 46 | void GobangServer::stop() { 47 | std::cout << "\nStopping server" << std::endl; 48 | shutdown(socketfd, 2); 49 | std::this_thread::sleep_for(std::chrono::seconds(1)); 50 | std::cout << "Closing socket" << std::endl; 51 | closeSocket(socketfd); 52 | isRunning = false; 53 | std::this_thread::sleep_for(std::chrono::seconds(2)); 54 | std::cout << "Quit successfully" << std::endl; 55 | } 56 | 57 | 58 | bool GobangServer::start(int port) { 59 | socketfd = socket(AF_INET, SOCK_STREAM, 0); 60 | if (socketfd <= 0) { 61 | printf("create socket error: %s(errno: %d)\n", strerror(errno), errno); 62 | return false; 63 | } 64 | 65 | struct sockaddr_in servaddr; 66 | servaddr.sin_family = AF_INET; 67 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 68 | servaddr.sin_port = htons(port); 69 | 70 | if (bind(socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) { 71 | printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno); 72 | closeSocket(socketfd); 73 | return false; 74 | } 75 | 76 | if (listen(socketfd, 10) == -1) { 77 | printf("listen socket error: %s(errno: %d)\n", strerror(errno), errno); 78 | closeSocket(socketfd); 79 | return false; 80 | } 81 | 82 | printf("Running...\n"); 83 | 84 | while (isRunning) { 85 | SocketFD connectfd = 0; 86 | if ((connectfd = accept(socketfd, (struct sockaddr*)NULL, NULL)) <= 0) { 87 | printf("accept socket error %s(errno: %d)\n", strerror(errno), errno); 88 | continue; 89 | } 90 | 91 | printf("Accept one connection.\n"); 92 | 93 | pool.enqueue([this, connectfd](){ 94 | Json::Value root; 95 | int ret = recvJsonMsg(root, connectfd); 96 | std::cout << "Recv Ret: " << ret << std::endl;; 97 | 98 | if (ret == -1) { 99 | closeSocket(connectfd); 100 | return; 101 | } 102 | else if (ret > 0){ 103 | parseJsonMsg(root, connectfd); 104 | } 105 | }); 106 | } 107 | 108 | return true; 109 | } 110 | 111 | bool GobangServer::parseJsonMsg(const Json::Value& root, SocketFD fd) { 112 | if (root["type"].isNull()) { 113 | return false; 114 | } 115 | 116 | std::string type = root["type"].asString(); 117 | if (type == "command") { 118 | return processMsgTypeCmd(root, fd); 119 | } 120 | 121 | return true; 122 | } 123 | 124 | bool GobangServer::processMsgTypeCmd(const Json::Value& root, SocketFD fd) { 125 | if (root["cmd"].isNull()) 126 | return false; 127 | 128 | std::string cmd = root["cmd"].asString(); 129 | 130 | if (cmd == "create_room") 131 | return processCreateRoom(root, fd); 132 | if (cmd == "join_room") 133 | return processJoinRoom(root, fd); 134 | if (cmd == "watch_room") 135 | return processWatchRoom(root, fd); 136 | 137 | return false; 138 | } 139 | 140 | 141 | bool GobangServer::processCreateRoom(const Json::Value& root, SocketFD fd) { 142 | if (root["room_name"].isNull() || root["player_name"].isNull()) 143 | return false; 144 | 145 | Room* room = createRoom(); 146 | rooms.push_back(room); 147 | room->setName(root["room_name"].asString()); 148 | room->addPlayer(root["player_name"].asString(), fd); 149 | 150 | return API::responseCreateRoom(fd, 0, "OK", room->getId()); 151 | } 152 | 153 | bool GobangServer::processJoinRoom(const Json::Value& root, SocketFD fd) { 154 | if (root["room_id"].isNull() || root["player_name"].isNull()) 155 | return false; 156 | 157 | int roomId = root["room_id"].asInt(); 158 | std::string playerName = root["player_name"].asString(); 159 | Room* room = getRoomById(roomId); 160 | 161 | int statusCode = STATUS_ERROR; 162 | std::string desc, roomName, rivalname; 163 | 164 | do { 165 | // The room is not exist 166 | if (!room) { 167 | desc = "The room is not exist"; 168 | break; 169 | } 170 | 171 | int numPlayers = room->getNumPlayers(); 172 | 173 | // The room is full 174 | if (numPlayers == 2) { 175 | desc = "The room is full"; 176 | break; 177 | } 178 | else if (numPlayers == 1) { 179 | Player& player1 = room->getPlayer1(); 180 | // Error: The name of two players is same 181 | if (player1.name == playerName) { 182 | desc = "The name of two players cant't be same"; 183 | break; 184 | } 185 | roomName = room->getName(); 186 | rivalname = player1.name; 187 | } 188 | else { 189 | desc = "Server Internal Error. Please try to join another room"; 190 | break; 191 | } 192 | 193 | room->addPlayer(playerName, fd); 194 | statusCode = STATUS_OK; 195 | } while (false); 196 | 197 | // response new player 198 | API::responseJoinRoom(fd, statusCode, desc, roomName, rivalname); 199 | 200 | if (room && statusCode == STATUS_OK) 201 | // notify old player 202 | return API::notifyRivalInfo(room->getPlayer1().socketfd, playerName); 203 | else 204 | return false; 205 | } 206 | 207 | bool GobangServer::processWatchRoom(const Json::Value& root, SocketFD fd) { 208 | if (root["room_id"].isNull() || root["player_name"].isNull()) 209 | return false; 210 | 211 | int roomId = root["room_id"].asInt(); 212 | std::string playerName = root["player_name"].asString(); 213 | Room* room = getRoomById(roomId); 214 | if (room) { 215 | API::responseWatchRoom(fd, STATUS_OK, "", room->getName()); 216 | room->addWatcher(playerName, fd); 217 | } 218 | else{ 219 | API::responseWatchRoom(fd, STATUS_ERROR, "The room is not exist", ""); 220 | } 221 | 222 | return true; 223 | } 224 | 225 | bool GobangServer::processDeleteRoom(const Json::Value& root, SocketFD fd) { 226 | 227 | return true; 228 | } 229 | 230 | 231 | /*****************************************************************************/ 232 | /*****************************************************************************/ 233 | 234 | Room* GobangServer::createRoom() { 235 | if (rooms.size() > 100) 236 | return nullptr; 237 | 238 | Room* room = new Room(); 239 | 240 | while (true) { 241 | int randNum = rand() % 9000 + 1000; 242 | auto iter = std::find(roomsId.begin(), roomsId.end(), randNum); 243 | if (iter == roomsId.end()) { 244 | roomsId.push_back(randNum); 245 | room->setId(randNum); 246 | break; 247 | } 248 | } 249 | 250 | return room; 251 | } 252 | 253 | Room* GobangServer::getRoomById(int id) { 254 | for (int i = 0, size = rooms.size(); i < size; ++i) { 255 | if (rooms[i]->getId() == id) 256 | return rooms[i]; 257 | } 258 | return nullptr; 259 | } 260 | 261 | 262 | -------------------------------------------------------------------------------- /GobangServer/src/gobangserver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "jsoncpp/json/json.h" 4 | #include "room.h" 5 | #include "socket_func.h" 6 | #include "thread_pool.h" 7 | 8 | 9 | #include 10 | 11 | class GobangServer { 12 | public: 13 | GobangServer(); 14 | 15 | public: 16 | bool start(int port); 17 | void stop(); 18 | 19 | private: 20 | Room* createRoom(); 21 | 22 | bool parseJsonMsg(const Json::Value& root, SocketFD fd); 23 | 24 | bool processMsgTypeCmd(const Json::Value& root, SocketFD fd); 25 | 26 | bool processCreateRoom(const Json::Value& root, SocketFD fd); 27 | bool processJoinRoom(const Json::Value& root, SocketFD fd); 28 | bool processWatchRoom(const Json::Value& root, SocketFD fd); 29 | bool processDeleteRoom(const Json::Value& root, SocketFD fd); 30 | 31 | Room* getRoomById(int id); 32 | 33 | private: 34 | ThreadPool pool; 35 | 36 | std::vector rooms; 37 | std::vector roomsId; 38 | 39 | SocketFD socketfd = 0; 40 | 41 | bool isRunning = true; 42 | }; 43 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/allocator.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED 7 | #define CPPTL_JSON_ALLOCATOR_H_INCLUDED 8 | 9 | #include 10 | #include 11 | 12 | #pragma pack(push, 8) 13 | 14 | namespace Json { 15 | template class SecureAllocator { 16 | public: 17 | // Type definitions 18 | using value_type = T; 19 | using pointer = T*; 20 | using const_pointer = const T*; 21 | using reference = T&; 22 | using const_reference = const T&; 23 | using size_type = std::size_t; 24 | using difference_type = std::ptrdiff_t; 25 | 26 | /** 27 | * Allocate memory for N items using the standard allocator. 28 | */ 29 | pointer allocate(size_type n) { 30 | // allocate using "global operator new" 31 | return static_cast(::operator new(n * sizeof(T))); 32 | } 33 | 34 | /** 35 | * Release memory which was allocated for N items at pointer P. 36 | * 37 | * The memory block is filled with zeroes before being released. 38 | * The pointer argument is tagged as "volatile" to prevent the 39 | * compiler optimizing out this critical step. 40 | */ 41 | void deallocate(volatile pointer p, size_type n) { 42 | std::memset(p, 0, n * sizeof(T)); 43 | // free using "global operator delete" 44 | ::operator delete(p); 45 | } 46 | 47 | /** 48 | * Construct an item in-place at pointer P. 49 | */ 50 | template void construct(pointer p, Args&&... args) { 51 | // construct using "placement new" and "perfect forwarding" 52 | ::new (static_cast(p)) T(std::forward(args)...); 53 | } 54 | 55 | size_type max_size() const { return size_t(-1) / sizeof(T); } 56 | 57 | pointer address(reference x) const { return std::addressof(x); } 58 | 59 | const_pointer address(const_reference x) const { return std::addressof(x); } 60 | 61 | /** 62 | * Destroy an item in-place at pointer P. 63 | */ 64 | void destroy(pointer p) { 65 | // destroy using "explicit destructor" 66 | p->~T(); 67 | } 68 | 69 | // Boilerplate 70 | SecureAllocator() {} 71 | template SecureAllocator(const SecureAllocator&) {} 72 | template struct rebind { using other = SecureAllocator; }; 73 | }; 74 | 75 | template 76 | bool operator==(const SecureAllocator&, const SecureAllocator&) { 77 | return true; 78 | } 79 | 80 | template 81 | bool operator!=(const SecureAllocator&, const SecureAllocator&) { 82 | return false; 83 | } 84 | 85 | } // namespace Json 86 | 87 | #pragma pack(pop) 88 | 89 | #endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED 90 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/assertions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED 7 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED 8 | 9 | #include 10 | #include 11 | 12 | #if !defined(JSON_IS_AMALGAMATION) 13 | #include "config.h" 14 | #endif // if !defined(JSON_IS_AMALGAMATION) 15 | 16 | /** It should not be possible for a maliciously designed file to 17 | * cause an abort() or seg-fault, so these macros are used only 18 | * for pre-condition violations and internal logic errors. 19 | */ 20 | #if JSON_USE_EXCEPTION 21 | 22 | // @todo <= add detail about condition in exception 23 | #define JSON_ASSERT(condition) \ 24 | { \ 25 | if (!(condition)) { \ 26 | Json::throwLogicError("assert json failed"); \ 27 | } \ 28 | } 29 | 30 | #define JSON_FAIL_MESSAGE(message) \ 31 | { \ 32 | OStringStream oss; \ 33 | oss << message; \ 34 | Json::throwLogicError(oss.str()); \ 35 | abort(); \ 36 | } 37 | 38 | #else // JSON_USE_EXCEPTION 39 | 40 | #define JSON_ASSERT(condition) assert(condition) 41 | 42 | // The call to assert() will show the failure message in debug builds. In 43 | // release builds we abort, for a core-dump or debugger. 44 | #define JSON_FAIL_MESSAGE(message) \ 45 | { \ 46 | OStringStream oss; \ 47 | oss << message; \ 48 | assert(false && oss.str().c_str()); \ 49 | abort(); \ 50 | } 51 | 52 | #endif 53 | 54 | #define JSON_ASSERT_MESSAGE(condition, message) \ 55 | if (!(condition)) { \ 56 | JSON_FAIL_MESSAGE(message); \ 57 | } 58 | 59 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED 60 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/autolink.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_AUTOLINK_H_INCLUDED 7 | #define JSON_AUTOLINK_H_INCLUDED 8 | 9 | #include "config.h" 10 | 11 | #ifdef JSON_IN_CPPTL 12 | #include 13 | #endif 14 | 15 | #if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ 16 | !defined(JSON_IN_CPPTL) 17 | #define CPPTL_AUTOLINK_NAME "json" 18 | #undef CPPTL_AUTOLINK_DLL 19 | #ifdef JSON_DLL 20 | #define CPPTL_AUTOLINK_DLL 21 | #endif 22 | #include "autolink.h" 23 | #endif 24 | 25 | #endif // JSON_AUTOLINK_H_INCLUDED 26 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_CONFIG_H_INCLUDED 7 | #define JSON_CONFIG_H_INCLUDED 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /// If defined, indicates that json library is embedded in CppTL library. 18 | //# define JSON_IN_CPPTL 1 19 | 20 | /// If defined, indicates that json may leverage CppTL library 21 | //# define JSON_USE_CPPTL 1 22 | /// If defined, indicates that cpptl vector based map should be used instead of 23 | /// std::map 24 | /// as Value container. 25 | //# define JSON_USE_CPPTL_SMALLMAP 1 26 | 27 | // If non-zero, the library uses exceptions to report bad input instead of C 28 | // assertion macros. The default is to use exceptions. 29 | #ifndef JSON_USE_EXCEPTION 30 | #define JSON_USE_EXCEPTION 1 31 | #endif 32 | 33 | // Temporary, tracked for removal with issue #982. 34 | #ifndef JSON_USE_NULLREF 35 | #define JSON_USE_NULLREF 1 36 | #endif 37 | 38 | /// If defined, indicates that the source file is amalgamated 39 | /// to prevent private header inclusion. 40 | /// Remarks: it is automatically defined in the generated amalgamated header. 41 | // #define JSON_IS_AMALGAMATION 42 | 43 | #ifdef JSON_IN_CPPTL 44 | #include 45 | #ifndef JSON_USE_CPPTL 46 | #define JSON_USE_CPPTL 1 47 | #endif 48 | #endif 49 | 50 | #ifdef JSON_IN_CPPTL 51 | #define JSON_API CPPTL_API 52 | #elif defined(JSON_DLL_BUILD) 53 | #if defined(_MSC_VER) || defined(__MINGW32__) 54 | #define JSON_API __declspec(dllexport) 55 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 56 | #elif defined(__GNUC__) || defined(__clang__) 57 | #define JSON_API __attribute__((visibility("default"))) 58 | #endif // if defined(_MSC_VER) 59 | #elif defined(JSON_DLL) 60 | #if defined(_MSC_VER) || defined(__MINGW32__) 61 | #define JSON_API __declspec(dllimport) 62 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 63 | #endif // if defined(_MSC_VER) 64 | #endif // ifdef JSON_IN_CPPTL 65 | #if !defined(JSON_API) 66 | #define JSON_API 67 | #endif 68 | 69 | #if defined(_MSC_VER) && _MSC_VER < 1800 70 | #error \ 71 | "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" 72 | #endif 73 | 74 | #if defined(_MSC_VER) && _MSC_VER < 1900 75 | // As recommended at 76 | // https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 77 | extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, 78 | const char* format, ...); 79 | #define jsoncpp_snprintf msvc_pre1900_c99_snprintf 80 | #else 81 | #define jsoncpp_snprintf std::snprintf 82 | #endif 83 | 84 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 85 | // integer 86 | // Storages, and 64 bits integer support is disabled. 87 | // #define JSON_NO_INT64 1 88 | 89 | // JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. 90 | // C++11 should be used directly in JSONCPP. 91 | #define JSONCPP_OVERRIDE override 92 | 93 | #if __cplusplus >= 201103L 94 | #define JSONCPP_NOEXCEPT noexcept 95 | #define JSONCPP_OP_EXPLICIT explicit 96 | #elif defined(_MSC_VER) && _MSC_VER < 1900 97 | #define JSONCPP_NOEXCEPT throw() 98 | #define JSONCPP_OP_EXPLICIT explicit 99 | #elif defined(_MSC_VER) && _MSC_VER >= 1900 100 | #define JSONCPP_NOEXCEPT noexcept 101 | #define JSONCPP_OP_EXPLICIT explicit 102 | #else 103 | #define JSONCPP_NOEXCEPT throw() 104 | #define JSONCPP_OP_EXPLICIT 105 | #endif 106 | 107 | #ifdef __clang__ 108 | #if __has_extension(attribute_deprecated_with_message) 109 | #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) 110 | #endif 111 | #elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) 112 | #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) 113 | #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) 114 | #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) 115 | #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) 116 | #endif // GNUC version 117 | #elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates 118 | // MSVC) 119 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 120 | #endif // __clang__ || __GNUC__ || _MSC_VER 121 | 122 | #if !defined(JSONCPP_DEPRECATED) 123 | #define JSONCPP_DEPRECATED(message) 124 | #endif // if !defined(JSONCPP_DEPRECATED) 125 | 126 | #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) 127 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 128 | #endif 129 | 130 | #if !defined(JSON_IS_AMALGAMATION) 131 | 132 | #include "allocator.h" 133 | #include "version.h" 134 | 135 | #endif // if !defined(JSON_IS_AMALGAMATION) 136 | 137 | namespace Json { 138 | typedef int Int; 139 | typedef unsigned int UInt; 140 | #if defined(JSON_NO_INT64) 141 | typedef int LargestInt; 142 | typedef unsigned int LargestUInt; 143 | #undef JSON_HAS_INT64 144 | #else // if defined(JSON_NO_INT64) 145 | // For Microsoft Visual use specific types as long long is not supported 146 | #if defined(_MSC_VER) // Microsoft Visual Studio 147 | typedef __int64 Int64; 148 | typedef unsigned __int64 UInt64; 149 | #else // if defined(_MSC_VER) // Other platforms, use long long 150 | typedef int64_t Int64; 151 | typedef uint64_t UInt64; 152 | #endif // if defined(_MSC_VER) 153 | typedef Int64 LargestInt; 154 | typedef UInt64 LargestUInt; 155 | #define JSON_HAS_INT64 156 | #endif // if defined(JSON_NO_INT64) 157 | 158 | template 159 | using Allocator = 160 | typename std::conditional, 161 | std::allocator>::type; 162 | using String = std::basic_string, Allocator>; 163 | using IStringStream = 164 | std::basic_istringstream; 166 | using OStringStream = 167 | std::basic_ostringstream; 169 | using IStream = std::istream; 170 | using OStream = std::ostream; 171 | } // namespace Json 172 | 173 | // Legacy names (formerly macros). 174 | using JSONCPP_STRING = Json::String; 175 | using JSONCPP_ISTRINGSTREAM = Json::IStringStream; 176 | using JSONCPP_OSTRINGSTREAM = Json::OStringStream; 177 | using JSONCPP_ISTREAM = Json::IStream; 178 | using JSONCPP_OSTREAM = Json::OStream; 179 | 180 | #endif // JSON_CONFIG_H_INCLUDED 181 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/forwards.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_FORWARDS_H_INCLUDED 7 | #define JSON_FORWARDS_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "config.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | namespace Json { 14 | 15 | // writer.h 16 | class StreamWriter; 17 | class StreamWriterBuilder; 18 | class Writer; 19 | class FastWriter; 20 | class StyledWriter; 21 | class StyledStreamWriter; 22 | 23 | // reader.h 24 | class Reader; 25 | class CharReader; 26 | class CharReaderBuilder; 27 | 28 | // json_features.h 29 | class Features; 30 | 31 | // value.h 32 | typedef unsigned int ArrayIndex; 33 | class StaticString; 34 | class Path; 35 | class PathArgument; 36 | class Value; 37 | class ValueIteratorBase; 38 | class ValueIterator; 39 | class ValueConstIterator; 40 | 41 | } // namespace Json 42 | 43 | #endif // JSON_FORWARDS_H_INCLUDED 44 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/json.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_JSON_H_INCLUDED 7 | #define JSON_JSON_H_INCLUDED 8 | 9 | #include "autolink.h" 10 | #include "json_features.h" 11 | #include "reader.h" 12 | #include "value.h" 13 | #include "writer.h" 14 | 15 | #endif // JSON_JSON_H_INCLUDED 16 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/json_features.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED 7 | #define CPPTL_JSON_FEATURES_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "forwards.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | 13 | #pragma pack(push, 8) 14 | 15 | namespace Json { 16 | 17 | /** \brief Configuration passed to reader and writer. 18 | * This configuration object can be used to force the Reader or Writer 19 | * to behave in a standard conforming way. 20 | */ 21 | class JSON_API Features { 22 | public: 23 | /** \brief A configuration that allows all features and assumes all strings 24 | * are UTF-8. 25 | * - C & C++ comments are allowed 26 | * - Root object can be any JSON value 27 | * - Assumes Value strings are encoded in UTF-8 28 | */ 29 | static Features all(); 30 | 31 | /** \brief A configuration that is strictly compatible with the JSON 32 | * specification. 33 | * - Comments are forbidden. 34 | * - Root object must be either an array or an object value. 35 | * - Assumes Value strings are encoded in UTF-8 36 | */ 37 | static Features strictMode(); 38 | 39 | /** \brief Initialize the configuration like JsonConfig::allFeatures; 40 | */ 41 | Features(); 42 | 43 | /// \c true if comments are allowed. Default: \c true. 44 | bool allowComments_{true}; 45 | 46 | /// \c true if root must be either an array or an object value. Default: \c 47 | /// false. 48 | bool strictRoot_{false}; 49 | 50 | /// \c true if dropped null placeholders are allowed. Default: \c false. 51 | bool allowDroppedNullPlaceholders_{false}; 52 | 53 | /// \c true if numeric object key are allowed. Default: \c false. 54 | bool allowNumericKeys_{false}; 55 | }; 56 | 57 | } // namespace Json 58 | 59 | #pragma pack(pop) 60 | 61 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED 62 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/version.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_VERSION_H_INCLUDED 2 | #define JSON_VERSION_H_INCLUDED 3 | 4 | // Note: version must be updated in three places when doing a release. This 5 | // annoying process ensures that amalgamate, CMake, and meson all report the 6 | // correct version. 7 | // 1. /meson.build 8 | // 2. /include/json/version.h 9 | // 3. /CMakeLists.txt 10 | // IMPORTANT: also update the SOVERSION!! 11 | 12 | #define JSONCPP_VERSION_STRING "1.9.2" 13 | #define JSONCPP_VERSION_MAJOR 1 14 | #define JSONCPP_VERSION_MINOR 9 15 | #define JSONCPP_VERSION_PATCH 2 16 | #define JSONCPP_VERSION_QUALIFIER 17 | #define JSONCPP_VERSION_HEXA \ 18 | ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ 19 | (JSONCPP_VERSION_PATCH << 8)) 20 | 21 | #ifdef JSONCPP_USING_SECURE_MEMORY 22 | #undef JSONCPP_USING_SECURE_MEMORY 23 | #endif 24 | #define JSONCPP_USING_SECURE_MEMORY 0 25 | // If non-zero, the library zeroes any memory that it has allocated before 26 | // it frees its memory. 27 | 28 | #endif // JSON_VERSION_H_INCLUDED 29 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json/writer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef JSON_WRITER_H_INCLUDED 7 | #define JSON_WRITER_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include "value.h" 11 | #endif // if !defined(JSON_IS_AMALGAMATION) 12 | #include 13 | #include 14 | #include 15 | 16 | // Disable warning C4251: : needs to have dll-interface to 17 | // be used by... 18 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) 19 | #pragma warning(push) 20 | #pragma warning(disable : 4251) 21 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 22 | 23 | #pragma pack(push, 8) 24 | 25 | namespace Json { 26 | 27 | class Value; 28 | 29 | /** 30 | * 31 | * Usage: 32 | * \code 33 | * using namespace Json; 34 | * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) 35 | * { std::unique_ptr const writer( factory.newStreamWriter()); 36 | * writer->write(value, &std::cout); 37 | * std::cout << std::endl; // add lf and flush 38 | * } 39 | * \endcode 40 | */ 41 | class JSON_API StreamWriter { 42 | protected: 43 | OStream* sout_; // not owned; will not delete 44 | public: 45 | StreamWriter(); 46 | virtual ~StreamWriter(); 47 | /** Write Value into document as configured in sub-class. 48 | * Do not take ownership of sout, but maintain a reference during function. 49 | * \pre sout != NULL 50 | * \return zero on success (For now, we always return zero, so check the 51 | * stream instead.) \throw std::exception possibly, depending on 52 | * configuration 53 | */ 54 | virtual int write(Value const& root, OStream* sout) = 0; 55 | 56 | /** \brief A simple abstract factory. 57 | */ 58 | class JSON_API Factory { 59 | public: 60 | virtual ~Factory(); 61 | /** \brief Allocate a CharReader via operator new(). 62 | * \throw std::exception if something goes wrong (e.g. invalid settings) 63 | */ 64 | virtual StreamWriter* newStreamWriter() const = 0; 65 | }; // Factory 66 | }; // StreamWriter 67 | 68 | /** \brief Write into stringstream, then return string, for convenience. 69 | * A StreamWriter will be created from the factory, used, and then deleted. 70 | */ 71 | String JSON_API writeString(StreamWriter::Factory const& factory, 72 | Value const& root); 73 | 74 | /** \brief Build a StreamWriter implementation. 75 | 76 | * Usage: 77 | * \code 78 | * using namespace Json; 79 | * Value value = ...; 80 | * StreamWriterBuilder builder; 81 | * builder["commentStyle"] = "None"; 82 | * builder["indentation"] = " "; // or whatever you like 83 | * std::unique_ptr writer( 84 | * builder.newStreamWriter()); 85 | * writer->write(value, &std::cout); 86 | * std::cout << std::endl; // add lf and flush 87 | * \endcode 88 | */ 89 | class JSON_API StreamWriterBuilder : public StreamWriter::Factory { 90 | public: 91 | // Note: We use a Json::Value so that we can add data-members to this class 92 | // without a major version bump. 93 | /** Configuration of this builder. 94 | * Available settings (case-sensitive): 95 | * - "commentStyle": "None" or "All" 96 | * - "indentation": "". 97 | * - Setting this to an empty string also omits newline characters. 98 | * - "enableYAMLCompatibility": false or true 99 | * - slightly change the whitespace around colons 100 | * - "dropNullPlaceholders": false or true 101 | * - Drop the "null" string from the writer's output for nullValues. 102 | * Strictly speaking, this is not valid JSON. But when the output is being 103 | * fed to a browser's JavaScript, it makes for smaller output and the 104 | * browser can handle the output just fine. 105 | * - "useSpecialFloats": false or true 106 | * - If true, outputs non-finite floating point values in the following way: 107 | * NaN values as "NaN", positive infinity as "Infinity", and negative 108 | * infinity as "-Infinity". 109 | * - "precision": int 110 | * - Number of precision digits for formatting of real values. 111 | * - "precisionType": "significant"(default) or "decimal" 112 | * - Type of precision for formatting of real values. 113 | 114 | * You can examine 'settings_` yourself 115 | * to see the defaults. You can also write and read them just like any 116 | * JSON Value. 117 | * \sa setDefaults() 118 | */ 119 | Json::Value settings_; 120 | 121 | StreamWriterBuilder(); 122 | ~StreamWriterBuilder() override; 123 | 124 | /** 125 | * \throw std::exception if something goes wrong (e.g. invalid settings) 126 | */ 127 | StreamWriter* newStreamWriter() const override; 128 | 129 | /** \return true if 'settings' are legal and consistent; 130 | * otherwise, indicate bad settings via 'invalid'. 131 | */ 132 | bool validate(Json::Value* invalid) const; 133 | /** A simple way to update a specific setting. 134 | */ 135 | Value& operator[](const String& key); 136 | 137 | /** Called by ctor, but you can use this to reset settings_. 138 | * \pre 'settings' != NULL (but Json::null is fine) 139 | * \remark Defaults: 140 | * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults 141 | */ 142 | static void setDefaults(Json::Value* settings); 143 | }; 144 | 145 | /** \brief Abstract class for writers. 146 | * \deprecated Use StreamWriter. (And really, this is an implementation detail.) 147 | */ 148 | class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { 149 | public: 150 | virtual ~Writer(); 151 | 152 | virtual String write(const Value& root) = 0; 153 | }; 154 | 155 | /** \brief Outputs a Value in JSON format 156 | *without formatting (not human friendly). 157 | * 158 | * The JSON document is written in a single line. It is not intended for 'human' 159 | *consumption, 160 | * but may be useful to support feature such as RPC where bandwidth is limited. 161 | * \sa Reader, Value 162 | * \deprecated Use StreamWriterBuilder. 163 | */ 164 | #if defined(_MSC_VER) 165 | #pragma warning(push) 166 | #pragma warning(disable : 4996) // Deriving from deprecated class 167 | #endif 168 | class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter 169 | : public Writer { 170 | public: 171 | FastWriter(); 172 | ~FastWriter() override = default; 173 | 174 | void enableYAMLCompatibility(); 175 | 176 | /** \brief Drop the "null" string from the writer's output for nullValues. 177 | * Strictly speaking, this is not valid JSON. But when the output is being 178 | * fed to a browser's JavaScript, it makes for smaller output and the 179 | * browser can handle the output just fine. 180 | */ 181 | void dropNullPlaceholders(); 182 | 183 | void omitEndingLineFeed(); 184 | 185 | public: // overridden from Writer 186 | String write(const Value& root) override; 187 | 188 | private: 189 | void writeValue(const Value& value); 190 | 191 | String document_; 192 | bool yamlCompatibilityEnabled_{false}; 193 | bool dropNullPlaceholders_{false}; 194 | bool omitEndingLineFeed_{false}; 195 | }; 196 | #if defined(_MSC_VER) 197 | #pragma warning(pop) 198 | #endif 199 | 200 | /** \brief Writes a Value in JSON format in a 201 | *human friendly way. 202 | * 203 | * The rules for line break and indent are as follow: 204 | * - Object value: 205 | * - if empty then print {} without indent and line break 206 | * - if not empty the print '{', line break & indent, print one value per 207 | *line 208 | * and then unindent and line break and print '}'. 209 | * - Array value: 210 | * - if empty then print [] without indent and line break 211 | * - if the array contains no object value, empty array or some other value 212 | *types, 213 | * and all the values fit on one lines, then print the array on a single 214 | *line. 215 | * - otherwise, it the values do not fit on one line, or the array contains 216 | * object or non empty array, then print one value per line. 217 | * 218 | * If the Value have comments then they are outputed according to their 219 | *#CommentPlacement. 220 | * 221 | * \sa Reader, Value, Value::setComment() 222 | * \deprecated Use StreamWriterBuilder. 223 | */ 224 | #if defined(_MSC_VER) 225 | #pragma warning(push) 226 | #pragma warning(disable : 4996) // Deriving from deprecated class 227 | #endif 228 | class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API 229 | StyledWriter : public Writer { 230 | public: 231 | StyledWriter(); 232 | ~StyledWriter() override = default; 233 | 234 | public: // overridden from Writer 235 | /** \brief Serialize a Value in JSON format. 236 | * \param root Value to serialize. 237 | * \return String containing the JSON document that represents the root value. 238 | */ 239 | String write(const Value& root) override; 240 | 241 | private: 242 | void writeValue(const Value& value); 243 | void writeArrayValue(const Value& value); 244 | bool isMultilineArray(const Value& value); 245 | void pushValue(const String& value); 246 | void writeIndent(); 247 | void writeWithIndent(const String& value); 248 | void indent(); 249 | void unindent(); 250 | void writeCommentBeforeValue(const Value& root); 251 | void writeCommentAfterValueOnSameLine(const Value& root); 252 | static bool hasCommentForValue(const Value& value); 253 | static String normalizeEOL(const String& text); 254 | 255 | typedef std::vector ChildValues; 256 | 257 | ChildValues childValues_; 258 | String document_; 259 | String indentString_; 260 | unsigned int rightMargin_{74}; 261 | unsigned int indentSize_{3}; 262 | bool addChildValues_{false}; 263 | }; 264 | #if defined(_MSC_VER) 265 | #pragma warning(pop) 266 | #endif 267 | 268 | /** \brief Writes a Value in JSON format in a 269 | human friendly way, 270 | to a stream rather than to a string. 271 | * 272 | * The rules for line break and indent are as follow: 273 | * - Object value: 274 | * - if empty then print {} without indent and line break 275 | * - if not empty the print '{', line break & indent, print one value per 276 | line 277 | * and then unindent and line break and print '}'. 278 | * - Array value: 279 | * - if empty then print [] without indent and line break 280 | * - if the array contains no object value, empty array or some other value 281 | types, 282 | * and all the values fit on one lines, then print the array on a single 283 | line. 284 | * - otherwise, it the values do not fit on one line, or the array contains 285 | * object or non empty array, then print one value per line. 286 | * 287 | * If the Value have comments then they are outputed according to their 288 | #CommentPlacement. 289 | * 290 | * \sa Reader, Value, Value::setComment() 291 | * \deprecated Use StreamWriterBuilder. 292 | */ 293 | #if defined(_MSC_VER) 294 | #pragma warning(push) 295 | #pragma warning(disable : 4996) // Deriving from deprecated class 296 | #endif 297 | class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API 298 | StyledStreamWriter { 299 | public: 300 | /** 301 | * \param indentation Each level will be indented by this amount extra. 302 | */ 303 | StyledStreamWriter(String indentation = "\t"); 304 | ~StyledStreamWriter() = default; 305 | 306 | public: 307 | /** \brief Serialize a Value in JSON format. 308 | * \param out Stream to write to. (Can be ostringstream, e.g.) 309 | * \param root Value to serialize. 310 | * \note There is no point in deriving from Writer, since write() should not 311 | * return a value. 312 | */ 313 | void write(OStream& out, const Value& root); 314 | 315 | private: 316 | void writeValue(const Value& value); 317 | void writeArrayValue(const Value& value); 318 | bool isMultilineArray(const Value& value); 319 | void pushValue(const String& value); 320 | void writeIndent(); 321 | void writeWithIndent(const String& value); 322 | void indent(); 323 | void unindent(); 324 | void writeCommentBeforeValue(const Value& root); 325 | void writeCommentAfterValueOnSameLine(const Value& root); 326 | static bool hasCommentForValue(const Value& value); 327 | static String normalizeEOL(const String& text); 328 | 329 | typedef std::vector ChildValues; 330 | 331 | ChildValues childValues_; 332 | OStream* document_; 333 | String indentString_; 334 | unsigned int rightMargin_{74}; 335 | String indentation_; 336 | bool addChildValues_ : 1; 337 | bool indented_ : 1; 338 | }; 339 | #if defined(_MSC_VER) 340 | #pragma warning(pop) 341 | #endif 342 | 343 | #if defined(JSON_HAS_INT64) 344 | String JSON_API valueToString(Int value); 345 | String JSON_API valueToString(UInt value); 346 | #endif // if defined(JSON_HAS_INT64) 347 | String JSON_API valueToString(LargestInt value); 348 | String JSON_API valueToString(LargestUInt value); 349 | String JSON_API valueToString( 350 | double value, unsigned int precision = Value::defaultRealPrecision, 351 | PrecisionType precisionType = PrecisionType::significantDigits); 352 | String JSON_API valueToString(bool value); 353 | String JSON_API valueToQuotedString(const char* value); 354 | 355 | /// \brief Output using the StyledStreamWriter. 356 | /// \see Json::operator>>() 357 | JSON_API OStream& operator<<(OStream&, const Value& root); 358 | 359 | } // namespace Json 360 | 361 | #pragma pack(pop) 362 | 363 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 364 | #pragma warning(pop) 365 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 366 | 367 | #endif // JSON_WRITER_H_INCLUDED 368 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json_tool.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 7 | #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 8 | 9 | #if !defined(JSON_IS_AMALGAMATION) 10 | #include 11 | #endif 12 | 13 | // Also support old flag NO_LOCALE_SUPPORT 14 | #ifdef NO_LOCALE_SUPPORT 15 | #define JSONCPP_NO_LOCALE_SUPPORT 16 | #endif 17 | 18 | #ifndef JSONCPP_NO_LOCALE_SUPPORT 19 | #include 20 | #endif 21 | 22 | /* This header provides common string manipulation support, such as UTF-8, 23 | * portable conversion from/to string... 24 | * 25 | * It is an internal header that must not be exposed. 26 | */ 27 | 28 | namespace Json { 29 | static inline char getDecimalPoint() { 30 | #ifdef JSONCPP_NO_LOCALE_SUPPORT 31 | return '\0'; 32 | #else 33 | struct lconv* lc = localeconv(); 34 | return lc ? *(lc->decimal_point) : '\0'; 35 | #endif 36 | } 37 | 38 | /// Converts a unicode code-point to UTF-8. 39 | static inline String codePointToUTF8(unsigned int cp) { 40 | String result; 41 | 42 | // based on description from http://en.wikipedia.org/wiki/UTF-8 43 | 44 | if (cp <= 0x7f) { 45 | result.resize(1); 46 | result[0] = static_cast(cp); 47 | } else if (cp <= 0x7FF) { 48 | result.resize(2); 49 | result[1] = static_cast(0x80 | (0x3f & cp)); 50 | result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); 51 | } else if (cp <= 0xFFFF) { 52 | result.resize(3); 53 | result[2] = static_cast(0x80 | (0x3f & cp)); 54 | result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); 55 | result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); 56 | } else if (cp <= 0x10FFFF) { 57 | result.resize(4); 58 | result[3] = static_cast(0x80 | (0x3f & cp)); 59 | result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); 60 | result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); 61 | result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); 62 | } 63 | 64 | return result; 65 | } 66 | 67 | enum { 68 | /// Constant that specify the size of the buffer that must be passed to 69 | /// uintToString. 70 | uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 71 | }; 72 | 73 | // Defines a char buffer for use with uintToString(). 74 | typedef char UIntToStringBuffer[uintToStringBufferSize]; 75 | 76 | /** Converts an unsigned integer to string. 77 | * @param value Unsigned integer to convert to string 78 | * @param current Input/Output string buffer. 79 | * Must have at least uintToStringBufferSize chars free. 80 | */ 81 | static inline void uintToString(LargestUInt value, char*& current) { 82 | *--current = 0; 83 | do { 84 | *--current = static_cast(value % 10U + static_cast('0')); 85 | value /= 10; 86 | } while (value != 0); 87 | } 88 | 89 | /** Change ',' to '.' everywhere in buffer. 90 | * 91 | * We had a sophisticated way, but it did not work in WinCE. 92 | * @see https://github.com/open-source-parsers/jsoncpp/pull/9 93 | */ 94 | template Iter fixNumericLocale(Iter begin, Iter end) { 95 | for (; begin != end; ++begin) { 96 | if (*begin == ',') { 97 | *begin = '.'; 98 | } 99 | } 100 | return begin; 101 | } 102 | 103 | template void fixNumericLocaleInput(Iter begin, Iter end) { 104 | char decimalPoint = getDecimalPoint(); 105 | if (decimalPoint == '\0' || decimalPoint == '.') { 106 | return; 107 | } 108 | for (; begin != end; ++begin) { 109 | if (*begin == '.') { 110 | *begin = decimalPoint; 111 | } 112 | } 113 | } 114 | 115 | /** 116 | * Return iterator that would be the new end of the range [begin,end), if we 117 | * were to delete zeros in the end of string, but not the last zero before '.'. 118 | */ 119 | template Iter fixZerosInTheEnd(Iter begin, Iter end) { 120 | for (; begin != end; --end) { 121 | if (*(end - 1) != '0') { 122 | return end; 123 | } 124 | // Don't delete the last zero before the decimal point. 125 | if (begin != (end - 1) && *(end - 2) == '.') { 126 | return end; 127 | } 128 | } 129 | return end; 130 | } 131 | 132 | } // namespace Json 133 | 134 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 135 | -------------------------------------------------------------------------------- /GobangServer/src/jsoncpp/json_valueiterator.inl: -------------------------------------------------------------------------------- 1 | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors 2 | // Distributed under MIT license, or public domain if desired and 3 | // recognized in your jurisdiction. 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5 | 6 | // included by json_value.cpp 7 | 8 | namespace Json { 9 | 10 | // ////////////////////////////////////////////////////////////////// 11 | // ////////////////////////////////////////////////////////////////// 12 | // ////////////////////////////////////////////////////////////////// 13 | // class ValueIteratorBase 14 | // ////////////////////////////////////////////////////////////////// 15 | // ////////////////////////////////////////////////////////////////// 16 | // ////////////////////////////////////////////////////////////////// 17 | 18 | ValueIteratorBase::ValueIteratorBase() : current_() {} 19 | 20 | ValueIteratorBase::ValueIteratorBase( 21 | const Value::ObjectValues::iterator& current) 22 | : current_(current), isNull_(false) {} 23 | 24 | Value& ValueIteratorBase::deref() { return current_->second; } 25 | const Value& ValueIteratorBase::deref() const { return current_->second; } 26 | 27 | void ValueIteratorBase::increment() { ++current_; } 28 | 29 | void ValueIteratorBase::decrement() { --current_; } 30 | 31 | ValueIteratorBase::difference_type 32 | ValueIteratorBase::computeDistance(const SelfType& other) const { 33 | #ifdef JSON_USE_CPPTL_SMALLMAP 34 | return other.current_ - current_; 35 | #else 36 | // Iterator for null value are initialized using the default 37 | // constructor, which initialize current_ to the default 38 | // std::map::iterator. As begin() and end() are two instance 39 | // of the default std::map::iterator, they can not be compared. 40 | // To allow this, we handle this comparison specifically. 41 | if (isNull_ && other.isNull_) { 42 | return 0; 43 | } 44 | 45 | // Usage of std::distance is not portable (does not compile with Sun Studio 12 46 | // RogueWave STL, 47 | // which is the one used by default). 48 | // Using a portable hand-made version for non random iterator instead: 49 | // return difference_type( std::distance( current_, other.current_ ) ); 50 | difference_type myDistance = 0; 51 | for (Value::ObjectValues::iterator it = current_; it != other.current_; 52 | ++it) { 53 | ++myDistance; 54 | } 55 | return myDistance; 56 | #endif 57 | } 58 | 59 | bool ValueIteratorBase::isEqual(const SelfType& other) const { 60 | if (isNull_) { 61 | return other.isNull_; 62 | } 63 | return current_ == other.current_; 64 | } 65 | 66 | void ValueIteratorBase::copy(const SelfType& other) { 67 | current_ = other.current_; 68 | isNull_ = other.isNull_; 69 | } 70 | 71 | Value ValueIteratorBase::key() const { 72 | const Value::CZString czstring = (*current_).first; 73 | if (czstring.data()) { 74 | if (czstring.isStaticString()) 75 | return Value(StaticString(czstring.data())); 76 | return Value(czstring.data(), czstring.data() + czstring.length()); 77 | } 78 | return Value(czstring.index()); 79 | } 80 | 81 | UInt ValueIteratorBase::index() const { 82 | const Value::CZString czstring = (*current_).first; 83 | if (!czstring.data()) 84 | return czstring.index(); 85 | return Value::UInt(-1); 86 | } 87 | 88 | String ValueIteratorBase::name() const { 89 | char const* keey; 90 | char const* end; 91 | keey = memberName(&end); 92 | if (!keey) 93 | return String(); 94 | return String(keey, end); 95 | } 96 | 97 | char const* ValueIteratorBase::memberName() const { 98 | const char* cname = (*current_).first.data(); 99 | return cname ? cname : ""; 100 | } 101 | 102 | char const* ValueIteratorBase::memberName(char const** end) const { 103 | const char* cname = (*current_).first.data(); 104 | if (!cname) { 105 | *end = nullptr; 106 | return nullptr; 107 | } 108 | *end = cname + (*current_).first.length(); 109 | return cname; 110 | } 111 | 112 | // ////////////////////////////////////////////////////////////////// 113 | // ////////////////////////////////////////////////////////////////// 114 | // ////////////////////////////////////////////////////////////////// 115 | // class ValueConstIterator 116 | // ////////////////////////////////////////////////////////////////// 117 | // ////////////////////////////////////////////////////////////////// 118 | // ////////////////////////////////////////////////////////////////// 119 | 120 | ValueConstIterator::ValueConstIterator() = default; 121 | 122 | ValueConstIterator::ValueConstIterator( 123 | const Value::ObjectValues::iterator& current) 124 | : ValueIteratorBase(current) {} 125 | 126 | ValueConstIterator::ValueConstIterator(ValueIterator const& other) 127 | : ValueIteratorBase(other) {} 128 | 129 | ValueConstIterator& ValueConstIterator:: 130 | operator=(const ValueIteratorBase& other) { 131 | copy(other); 132 | return *this; 133 | } 134 | 135 | // ////////////////////////////////////////////////////////////////// 136 | // ////////////////////////////////////////////////////////////////// 137 | // ////////////////////////////////////////////////////////////////// 138 | // class ValueIterator 139 | // ////////////////////////////////////////////////////////////////// 140 | // ////////////////////////////////////////////////////////////////// 141 | // ////////////////////////////////////////////////////////////////// 142 | 143 | ValueIterator::ValueIterator() = default; 144 | 145 | ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 146 | : ValueIteratorBase(current) {} 147 | 148 | ValueIterator::ValueIterator(const ValueConstIterator& other) 149 | : ValueIteratorBase(other) { 150 | throwRuntimeError("ConstIterator to Iterator should never be allowed."); 151 | } 152 | 153 | ValueIterator::ValueIterator(const ValueIterator& other) = default; 154 | 155 | ValueIterator& ValueIterator::operator=(const SelfType& other) { 156 | copy(other); 157 | return *this; 158 | } 159 | 160 | } // namespace Json 161 | -------------------------------------------------------------------------------- /GobangServer/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "gobangserver.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | GobangServer server; 9 | 10 | void handleCtrlC(int num); 11 | void exitFunc(); 12 | 13 | int main(int argc, char** argv) { 14 | atexit(exitFunc); 15 | signal(SIGINT, handleCtrlC); 16 | 17 | srand(time(NULL)); 18 | 19 | if (!server.start(10032)) { 20 | std::cerr << "Start failed!" << std::endl; 21 | return 1; 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | void handleCtrlC(int num) { 28 | exit(0); 29 | } 30 | 31 | void exitFunc() { 32 | server.stop(); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /GobangServer/src/player.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "base.h" 4 | #include 5 | 6 | 7 | struct Player { 8 | Player() {} 9 | Player(const std::string& name, int fd, ChessType type) : 10 | name(name), socketfd(fd), type(type) {} 11 | Player(const Player& rhs) { 12 | name = rhs.name; 13 | socketfd = rhs.socketfd; 14 | type = rhs.type; 15 | prepare = rhs.prepare; 16 | } 17 | Player& operator=(const Player& rhs) { 18 | if (this != &rhs) { 19 | this->name = rhs.name; 20 | this->socketfd = rhs.socketfd; 21 | this->type = rhs.type; 22 | this->prepare = rhs.prepare; 23 | } 24 | return *this; 25 | } 26 | std::string name; 27 | int socketfd = 0; 28 | ChessType type = CHESS_BLACK; 29 | bool prepare = false; 30 | }; 31 | 32 | struct Watcher { 33 | Watcher(const std::string& name, int fd) : 34 | name(name), socketfd(fd) {} 35 | Watcher(const Watcher& rhs) { 36 | name = rhs.name; 37 | socketfd = rhs.socketfd; 38 | } 39 | std::string name; 40 | int socketfd; 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /GobangServer/src/room.cpp: -------------------------------------------------------------------------------- 1 | #include "room.h" 2 | 3 | #include "api.h" 4 | #include "jsoncpp/json/json.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define Log(x) std::cout << (x) << std::endl 11 | 12 | 13 | Room::Room() : 14 | pool(MAX_NUM_WATCHERS + 2) 15 | { 16 | initChessBoard(); 17 | lastChess = { 0, 0, CHESS_NULL }; 18 | } 19 | 20 | void Room::initChessBoard() { 21 | for (int row = 0; row < 15; ++row) { 22 | for (int col = 0; col < 15; ++col) { 23 | chessPieces[row][col] = 0; 24 | } 25 | } 26 | } 27 | 28 | void Room::setPiece(int row, int col, ChessType type) { 29 | if (row < 0 || row > 14 || col < 0 || col > 14) 30 | return; 31 | chessPieces[row][col] = type; 32 | } 33 | 34 | void Room::addPlayer(const std::string& name, SocketFD fd) { 35 | if (numPlayers == 0) { 36 | player1 = Player(name, fd, CHESS_BLACK); 37 | numPlayers++; 38 | } 39 | else { 40 | player2 = Player(name, fd, reverse(player1.type)); 41 | numPlayers++; 42 | } 43 | 44 | for (auto& watcher : watchers) { 45 | API::notifyPlayerInfo(watcher.socketfd, player1.name, player1.type, 46 | player2.name, player2.type); 47 | } 48 | 49 | pool.enqueue([this, fd](){ 50 | while (1) { 51 | Json::Value root; 52 | int ret = recvJsonMsg(root, fd); 53 | if (ret == -1) { 54 | Log("Quit"); 55 | quitPlayer(fd); 56 | return; 57 | } 58 | else if (ret > 0){ 59 | parseJsonMsg(root, fd); 60 | } 61 | } 62 | }); 63 | } 64 | 65 | void Room::addWatcher(const std::string& name, SocketFD fd) { 66 | watchers.emplace_back(name, fd); 67 | API::notifyPlayerInfo(fd, player1.name, player1.type, player2.name, player2.type); 68 | API::sendChessBoard(fd, this->chessPieces, lastChess); 69 | 70 | pool.enqueue([this, fd](){ 71 | std::cout << "add watcher" << std::endl; 72 | while (1) { 73 | Json::Value root; 74 | int ret = recvJsonMsg(root, fd); 75 | std::cout << "recv watcher msg" << std::endl; 76 | if (ret == -1) { 77 | Log("A watcher quit"); 78 | quitWatcher(fd); 79 | return; 80 | } 81 | else if (ret > 0){ 82 | std::cout << "recv watcher msg" << std::endl; 83 | if (root["type"].isNull() || root["type"].asString() != "chat" || 84 | root["message"].isNull() || root["sender"].isNull()) { 85 | return; 86 | } 87 | for (auto& watcher : watchers) { 88 | if (watcher.socketfd != fd) { 89 | API::forward(watcher.socketfd, root); 90 | } 91 | } 92 | if (numPlayers >= 1) 93 | API::forward(player1.socketfd, root); 94 | if (numPlayers == 2) 95 | API::forward(player2.socketfd, root); 96 | } 97 | } 98 | }); 99 | } 100 | 101 | void Room::quitPlayer(SocketFD fd) { 102 | std::cout << "quit player" << std::endl; 103 | std::cout << numPlayers << std::endl; 104 | // won't happen 105 | if (numPlayers <= 0) 106 | return; 107 | 108 | std::string quitPlayerName = getPlayer(fd)->name; 109 | 110 | if (fd == player1.socketfd) { 111 | if (numPlayers == 2) 112 | player1 = player2; // player1 should be the master player 113 | } 114 | 115 | numPlayers--; 116 | if (numPlayers == 0) { 117 | flagShouldDelete = true; 118 | } 119 | else { 120 | API::notifyDisconnect(player1.socketfd, quitPlayerName); 121 | for (auto& watcher : watchers) 122 | API::notifyDisconnect(watcher.socketfd, quitPlayerName); 123 | gameStatus = GAME_END; 124 | lastChess = { 0, 0, CHESS_NULL }; 125 | } 126 | 127 | std::cout << numPlayers << std::endl; 128 | closeSocket(fd); 129 | } 130 | 131 | void Room::quitWatcher(SocketFD fd) { 132 | std::cout << "quit watcher" << std::endl; 133 | std::cout << watchers.size() << std::endl; 134 | 135 | for (auto it = watchers.begin(); it != watchers.end(); ++it) { 136 | if (it->socketfd == fd) { 137 | watchers.erase(it); 138 | return; 139 | } 140 | } 141 | 142 | closeSocket(fd); 143 | std::cout << watchers.size() << std::endl; 144 | } 145 | 146 | bool Room::parseJsonMsg(const Json::Value& root, SocketFD fd) { 147 | if (root["type"].isNull()) 148 | return false; 149 | std::string msgType = root["type"].asString(); 150 | 151 | if (msgType == "command") { 152 | if (root["cmd"].isNull()) 153 | return false; 154 | else 155 | return processMsgTypeCmd(root, fd); 156 | } 157 | if (msgType == "response") { 158 | if (root["res_cmd"].isNull()) 159 | return false; 160 | else 161 | return processMsgTypeResponse(root, fd); 162 | } 163 | if (msgType == "chat") 164 | return processMsgTypeChat(root, fd); 165 | if (msgType == "notify") { 166 | if (root["sub_type"].isNull()) 167 | return false; 168 | else 169 | return processMsgTypeNotify(root, fd); 170 | } 171 | 172 | return false; 173 | } 174 | 175 | bool Room::processMsgTypeCmd(const Json::Value& root, SocketFD fd) { 176 | std::string cmd = root["cmd"].asString(); 177 | if (cmd == "prepare") 178 | return processPrepareGame(root, fd); 179 | if (cmd == "cancel_prepare") 180 | return processCancelPrepareGame(root, fd); 181 | if (cmd == "exchange") 182 | return processExchangeChessType(root, fd); 183 | return true; 184 | } 185 | 186 | bool Room::processMsgTypeResponse(const Json::Value& root, SocketFD fd) { 187 | std::string res_cmd = root["res_cmd"].asString(); 188 | if (res_cmd == "prepare") { 189 | if (root["accept"].isNull()) 190 | return false; 191 | if (root["accept"].asBool()) { 192 | ChessType tmp = player1.type; 193 | player1.type = player2.type; 194 | player2.type = tmp; 195 | } 196 | } 197 | return API::forward(getRival(fd)->socketfd, root); 198 | } 199 | 200 | bool Room::processMsgTypeChat(const Json::Value& root, SocketFD fd) { 201 | for (auto& watcher : watchers) { 202 | if (watcher.socketfd != fd) { 203 | API::forward(watcher.socketfd, root); 204 | } 205 | } 206 | return API::forward(getRival(fd)->socketfd, root); 207 | } 208 | 209 | 210 | bool Room::processMsgTypeNotify(const Json::Value& root, SocketFD fd) { 211 | std::string subType = root["sub_type"].asString(); 212 | if (subType == "new_piece") 213 | return processNewPiece(root, fd); 214 | if (subType == "game_over") 215 | return processGameOver(root, fd); 216 | if (subType == "rival_info") 217 | return processNotifyRivalInfo(root, fd); 218 | return false; 219 | } 220 | 221 | bool Room::processNotifyRivalInfo(const Json::Value& root, SocketFD fd) { 222 | Player* player = getPlayer(fd); 223 | if (!root["player_name"].isNull()) 224 | player->name = root["player_name"].asString(); 225 | 226 | return API::forward(getRival(fd)->socketfd, root); 227 | } 228 | 229 | bool Room::processPrepareGame(const Json::Value& root, SocketFD fd) { 230 | Player* player = getPlayer(fd); 231 | 232 | if (numPlayers == 2) { 233 | player->prepare = true; 234 | if (player1.prepare && player2.prepare) { 235 | gameStatus = GAME_RUNNING; 236 | initChessBoard(); 237 | lastChess = { 0, 0, CHESS_NULL }; 238 | player1.prepare = false; 239 | player2.prepare = false; 240 | API::notifyGameStart(fd); 241 | for (auto& watcher : watchers) 242 | API::notifyGameStart(watcher.socketfd); 243 | return API::notifyGameStart(getRival(fd)->socketfd); 244 | } 245 | else { 246 | gameStatus = GAME_PREPARE; 247 | API::responsePrepare(fd, STATUS_OK, "OK"); 248 | for (auto& watcher : watchers) 249 | API::forward(watcher.socketfd, root); 250 | return API::forward(getRival(fd)->socketfd, root); 251 | } 252 | } 253 | else { 254 | player->prepare = false; 255 | std::string desc = "Please wait for the other player to join"; 256 | return API::responsePrepare(fd, STATUS_ERROR, desc); 257 | } 258 | } 259 | 260 | bool Room::processCancelPrepareGame(const Json::Value& root, SocketFD fd) { 261 | getPlayer(fd)->prepare = false; 262 | for (auto& watcher : watchers) 263 | API::notifyGameCancelPrepare(watcher.socketfd); 264 | return API::notifyGameCancelPrepare(getRival(fd)->socketfd); 265 | } 266 | 267 | 268 | bool Room::processNewPiece(const Json::Value& root, SocketFD fd) { 269 | if (root["row"].isNull() || root["col"].isNull() || root["chess_type"].isNull()) 270 | return false; 271 | int row = root["row"].asInt(); 272 | int col = root["col"].asInt(); 273 | int chessType = root["chess_type"].asInt(); 274 | setPiece(row, col, ChessType(chessType)); 275 | lastChess = { row, col, chessType }; 276 | 277 | for (auto& watcher : watchers) { 278 | API::notifyNewPiece(watcher.socketfd, row, col, chessType); 279 | } 280 | 281 | return API::notifyNewPiece(getRival(fd)->socketfd, row, col, chessType); 282 | } 283 | 284 | bool Room::processGameOver(const Json::Value& root, SocketFD fd) { 285 | if (root["game_result"].isNull()) 286 | return false; 287 | 288 | if (root["game_result"].asString() == "win") { 289 | if (root["chess_type"].isNull()) 290 | return false; 291 | ChessType winChessType = ChessType(root["chess_type"].asInt()); 292 | } 293 | else { //Draw 294 | 295 | } 296 | 297 | gameStatus = GAME_END; 298 | std::cout << "game over" << std::endl; 299 | return true; 300 | } 301 | 302 | bool Room::processExchangeChessType(const Json::Value& root, SocketFD fd) { 303 | if (numPlayers != 2) 304 | return false; 305 | 306 | return API::forward(getRival(fd)->socketfd, root); 307 | } 308 | 309 | Player* Room::getPlayer(SocketFD fd) { 310 | if (player1.socketfd == fd) 311 | return &player1; 312 | else if (player2.socketfd == fd) 313 | return &player2; 314 | else 315 | return nullptr; 316 | } 317 | 318 | Player* Room::getRival(int my_fd) { 319 | if (player1.socketfd == my_fd) 320 | return &player2; 321 | else if (player2.socketfd == my_fd) 322 | return &player1; 323 | return nullptr; 324 | } 325 | 326 | 327 | -------------------------------------------------------------------------------- /GobangServer/src/room.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "base.h" 4 | #include "player.h" 5 | #include "socket_func.h" 6 | #include "thread_pool.h" 7 | #include "jsoncpp/json/json.h" 8 | 9 | #include 10 | #include 11 | 12 | #define MAX_NUM_WATCHERS 20 13 | 14 | 15 | class Room { 16 | public: 17 | Room(); 18 | ~Room() {} 19 | 20 | public: 21 | void initChessBoard(); 22 | 23 | int getId() const { return id; } 24 | void setId(int idIn) { id = idIn; } 25 | const std::string& getName() const { return name; } 26 | void setName(const std::string& nameIn) { name = nameIn; } 27 | 28 | int getNumPlayers() const { return numPlayers; } 29 | int getNumWatchers() const { return watchers.size(); } 30 | bool isFull() const { return watchers.size() >= MAX_NUM_WATCHERS; } 31 | 32 | void addPlayer(const std::string& name, SocketFD fd); 33 | void addWatcher(const std::string& name, SocketFD fd); 34 | void quitPlayer(SocketFD fd); 35 | void quitWatcher(SocketFD fd); 36 | 37 | Player& getPlayer1() { return player1; } 38 | Player& getPlayer2() { return player2; } 39 | Player* getPlayer(SocketFD fd); 40 | Player* getRival(int my_fd); 41 | 42 | bool shouldDelete() const { return flagShouldDelete; } 43 | 44 | private: 45 | void setPiece(int row, int col, ChessType type); 46 | 47 | bool parseJsonMsg(const Json::Value& root, SocketFD fd); 48 | 49 | bool processMsgTypeCmd(const Json::Value& root, SocketFD fd); 50 | bool processMsgTypeResponse(const Json::Value& root, SocketFD fd); 51 | bool processMsgTypeChat(const Json::Value& root, SocketFD fd); 52 | bool processMsgTypeNotify(const Json::Value& root, SocketFD fd); 53 | 54 | bool processNotifyRivalInfo(const Json::Value& root, SocketFD fd); 55 | bool processPrepareGame(const Json::Value& root, SocketFD fd); 56 | bool processCancelPrepareGame(const Json::Value& root, SocketFD fd); 57 | bool processStartGame(const Json::Value& root, SocketFD fd); 58 | bool processNewPiece(const Json::Value& root, SocketFD fd); 59 | bool processGameOver(const Json::Value& root, SocketFD fd); 60 | bool processExchangeChessType(const Json::Value& root, SocketFD fd); 61 | 62 | enum GameStatus { 63 | GAME_RUNNING = 1, 64 | GAME_PREPARE = 2, 65 | GAME_END = 3 66 | }; 67 | 68 | private: 69 | ThreadPool pool; 70 | bool flagShouldDelete = false; 71 | 72 | int chessPieces[15][15]; 73 | GameStatus gameStatus = GAME_END; 74 | ChessPieceInfo lastChess; 75 | 76 | int id = -1; 77 | std::string name; 78 | int numPlayers = 0; 79 | 80 | Player player1; 81 | Player player2; 82 | 83 | std::vector watchers; 84 | }; 85 | 86 | -------------------------------------------------------------------------------- /GobangServer/src/socket_func.cpp: -------------------------------------------------------------------------------- 1 | #include "socket_func.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #include "jsoncpp/json/json_features.h" 7 | #include "jsoncpp/json/writer.h" 8 | 9 | 10 | bool sendJsonMsg(const Json::Value& jsonMsg, SocketFD fd) { 11 | return sendJsonMsg(Json::FastWriter().write(jsonMsg), fd); 12 | } 13 | 14 | bool sendJsonMsg(const std::string& msg, SocketFD fd) { 15 | if (msg.empty()) 16 | return false; 17 | 18 | int len = msg.length(); 19 | std::string msgSend; 20 | msgSend.reserve(12 + len); 21 | msgSend += "length:"; 22 | msgSend += std::to_string(len); 23 | if (len < 10) 24 | msgSend += " "; 25 | else if (len < 100) 26 | msgSend += " "; 27 | else if (len < 1000) 28 | msgSend += " "; 29 | msgSend += "\n"; 30 | msgSend += msg; 31 | 32 | std::cout << "Sending message\n" << msgSend << std::endl; 33 | 34 | send(fd, msgSend.c_str(), len + 12, 0); 35 | return true; 36 | } 37 | 38 | 39 | int recvJsonMsg(Json::Value& root, SocketFD fd) { 40 | char temp[8] = { 0 }; 41 | char lengthStr[5] = { 0 }; 42 | char msgLengthInfo[13] = { 0 }; 43 | 44 | int n = recv(fd, msgLengthInfo, 12, 0); 45 | if (n <= 0) 46 | return -1; 47 | if (n < 12) 48 | return 0; 49 | 50 | memcpy(temp, msgLengthInfo, 7); 51 | memcpy(lengthStr, msgLengthInfo+7, 4); 52 | temp[7] = 0; 53 | if (strcmp(temp, "length:") != 0) 54 | return 0; 55 | 56 | int msgLength = 0; 57 | sscanf(lengthStr, "%d", &msgLength); 58 | 59 | char* jsonMsg = new char[msgLength+1]; 60 | jsonMsg[msgLength] = 0; 61 | n = recv(fd, jsonMsg, msgLength, 0); 62 | 63 | bool ret = 0; 64 | 65 | do { 66 | if (n <= 0) { 67 | ret = -1; 68 | break; 69 | } 70 | if (n < msgLength) { 71 | break; 72 | } 73 | 74 | Json::Reader reader; 75 | if (!reader.parse(jsonMsg, root)) 76 | break; 77 | 78 | ret = 1; 79 | } while (false); 80 | 81 | if (ret == 1) { 82 | printf("Recieved message:\n%s\n", jsonMsg); 83 | } 84 | 85 | delete[] jsonMsg; 86 | return ret; 87 | } 88 | 89 | void closeSocket(SocketFD fd) { 90 | #ifdef _WIN32 91 | closesocket(fd); 92 | #else 93 | close (fd); 94 | #endif 95 | } 96 | 97 | -------------------------------------------------------------------------------- /GobangServer/src/socket_func.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef _WIN32 6 | #include 7 | #include 8 | #pragma comment(lib, "ws2_32.lib") 9 | #define SocketFD unsigned long long 10 | #else 11 | #include 12 | #include 13 | #include 14 | #include 15 | #define SocketFD int 16 | #endif 17 | 18 | 19 | #include "jsoncpp/json/json.h" 20 | 21 | 22 | bool sendJsonMsg(const std::string& msg, SocketFD fd); 23 | bool sendJsonMsg(const Json::Value& jsonMsg, SocketFD fd); 24 | 25 | int recvJsonMsg(Json::Value& root, SocketFD fd); 26 | 27 | void closeSocket(SocketFD fd); 28 | -------------------------------------------------------------------------------- /GobangServer/src/thread_pool.h: -------------------------------------------------------------------------------- 1 | #ifndef THREAD_POOL_H 2 | #define THREAD_POOL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class ThreadPool { 15 | public: 16 | ThreadPool(size_t); 17 | template 18 | auto enqueue(F&& f, Args&&... args) 19 | -> std::future::type>; 20 | ~ThreadPool(); 21 | private: 22 | // need to keep track of threads so we can join them 23 | std::vector< std::thread > workers; 24 | // the task queue 25 | std::queue< std::function > tasks; 26 | 27 | // synchronization 28 | std::mutex queue_mutex; 29 | std::condition_variable condition; 30 | bool stop; 31 | }; 32 | 33 | // the constructor just launches some amount of workers 34 | inline ThreadPool::ThreadPool(size_t threads) 35 | : stop(false) 36 | { 37 | for(size_t i = 0;i task; 44 | 45 | { 46 | std::unique_lock lock(this->queue_mutex); 47 | this->condition.wait(lock, 48 | [this]{ return this->stop || !this->tasks.empty(); }); 49 | if(this->stop && this->tasks.empty()) 50 | return; 51 | task = std::move(this->tasks.front()); 52 | this->tasks.pop(); 53 | } 54 | 55 | task(); 56 | } 57 | } 58 | ); 59 | } 60 | 61 | // add new work item to the pool 62 | template 63 | auto ThreadPool::enqueue(F&& f, Args&&... args) 64 | -> std::future::type> 65 | { 66 | using return_type = typename std::result_of::type; 67 | 68 | auto task = std::make_shared< std::packaged_task >( 69 | std::bind(std::forward(f), std::forward(args)...) 70 | ); 71 | 72 | std::future res = task->get_future(); 73 | { 74 | std::unique_lock lock(queue_mutex); 75 | 76 | // don't allow enqueueing after stopping the pool 77 | if(stop) 78 | throw std::runtime_error("enqueue on stopped ThreadPool"); 79 | 80 | tasks.emplace([task](){ (*task)(); }); 81 | } 82 | condition.notify_one(); 83 | return res; 84 | } 85 | 86 | // the destructor joins all threads 87 | inline ThreadPool::~ThreadPool() 88 | { 89 | { 90 | std::unique_lock lock(queue_mutex); 91 | stop = true; 92 | } 93 | condition.notify_all(); 94 | for(std::thread &worker: workers) 95 | worker.join(); 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /GobangServer/xmake.lua: -------------------------------------------------------------------------------- 1 | target("gobang_server") 2 | set_kind("binary") 3 | 4 | -- std=c++11 5 | set_languages("c99", "cxx14") 6 | 7 | -- jsoncpp 8 | add_includedirs("src/jsoncpp") 9 | 10 | -- source file 11 | add_files("src/*.cpp") 12 | add_files("src/jsoncpp/*.cpp") 13 | 14 | -- link flags 15 | add_links("pthread") 16 | 17 | -- build dir 18 | set_targetdir("$(projectdir)") 19 | set_objectdir("build/objs") 20 | 21 | add_mflags("-g", "-O2", "-DDEBUG") 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 五子棋游戏,游戏双方联网对战。(服务器+客户端) 2 | 3 | ## 简介 4 | 5 | + Gobang:客户端,使用Qt Creator编写和构建。 6 | + GobangServer:服务端,使用xmake构建(就是一般的C++代码,可自行更换其他方式)。 7 | + 客户端和服务端均可以直接在`Linux`和`Windows`平台下构建。 8 | 9 | ## 功能 10 | 11 | + 联网下棋 12 | + 人机对战【暂不支持,后续可能会开发......】 13 | + 观看他人下棋(指定房间号) 14 | + 简单的聊天功能 15 | + 其他:交换黑白棋、更换棋盘背景、截图 16 | 17 | ## 截图 18 | 19 | ![screenshot](assets/README/001.png) 20 | 21 | ![screenshot](assets/README/002.png) 22 | 23 | ![screenshot](assets/README/003.png) 24 | 25 | ![screenshot](assets/README/004.png) 26 | 27 | ## END 28 | 29 | 30 | -------------------------------------------------------------------------------- /assets/README/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/assets/README/001.png -------------------------------------------------------------------------------- /assets/README/002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/assets/README/002.png -------------------------------------------------------------------------------- /assets/README/003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/assets/README/003.png -------------------------------------------------------------------------------- /assets/README/004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leopard-C/Gobang/9bcced54d8090034fdb21cbd7102fdcf184d2ef1/assets/README/004.png --------------------------------------------------------------------------------