From ce46f638a5aaa10e1557640075b1c37019ae909b Mon Sep 17 00:00:00 2001 From: daleclack Date: Sat, 5 Nov 2022 12:33:56 +0800 Subject: [PATCH] Add gtk142 --- .../gtk142_minesweeper3/.vscode/settings.json | 89 ++++++ Gtkmm4/gtk142_minesweeper3/CMakeLists.txt | 88 ++++++ .../res/cambalache/.gitignore | 1 + .../res/cambalache/minesweeper.cmb | 58 ++++ .../res/icons/scalable/status/1mines.svg | 80 +++++ .../res/icons/scalable/status/2mines.svg | 80 +++++ .../res/icons/scalable/status/3mines.svg | 80 +++++ .../res/icons/scalable/status/4mines.svg | 80 +++++ .../res/icons/scalable/status/5mines.svg | 80 +++++ .../res/icons/scalable/status/6mines.svg | 80 +++++ .../res/icons/scalable/status/7mines.svg | 80 +++++ .../res/icons/scalable/status/8mines.svg | 80 +++++ .../res/icons/scalable/status/exploded.svg | 125 ++++++++ .../res/icons/scalable/status/flag.svg | 90 ++++++ .../res/icons/scalable/status/incorrect.svg | 90 ++++++ .../res/icons/scalable/status/maybe.svg | 101 ++++++ .../res/icons/scalable/status/mine.svg | 125 ++++++++ Gtkmm4/gtk142_minesweeper3/res/mine_menu.xml | 27 ++ Gtkmm4/gtk142_minesweeper3/res/minesweeper.ui | 41 +++ Gtkmm4/gtk142_minesweeper3/res/scoreswin.ui | 41 +++ Gtkmm4/gtk142_minesweeper3/res/win_input.ui | 82 +++++ Gtkmm4/gtk142_minesweeper3/src/InputBox.cc | 99 ++++++ Gtkmm4/gtk142_minesweeper3/src/InputBox.hh | 38 +++ Gtkmm4/gtk142_minesweeper3/src/MineSweeper.cc | 295 ++++++++++++++++++ Gtkmm4/gtk142_minesweeper3/src/MineSweeper.hh | 67 ++++ Gtkmm4/gtk142_minesweeper3/src/ScoresWin.cc | 77 +++++ Gtkmm4/gtk142_minesweeper3/src/ScoresWin.hh | 35 +++ Gtkmm4/gtk142_minesweeper3/src/jsonfile.hh | 7 + Gtkmm4/gtk142_minesweeper3/src/main.cc | 8 + 29 files changed, 2224 insertions(+) create mode 100644 Gtkmm4/gtk142_minesweeper3/.vscode/settings.json create mode 100644 Gtkmm4/gtk142_minesweeper3/CMakeLists.txt create mode 100644 Gtkmm4/gtk142_minesweeper3/res/cambalache/.gitignore create mode 100644 Gtkmm4/gtk142_minesweeper3/res/cambalache/minesweeper.cmb create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/1mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/2mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/3mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/4mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/5mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/6mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/7mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/8mines.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/exploded.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/flag.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/incorrect.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/maybe.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/mine.svg create mode 100644 Gtkmm4/gtk142_minesweeper3/res/mine_menu.xml create mode 100644 Gtkmm4/gtk142_minesweeper3/res/minesweeper.ui create mode 100644 Gtkmm4/gtk142_minesweeper3/res/scoreswin.ui create mode 100644 Gtkmm4/gtk142_minesweeper3/res/win_input.ui create mode 100644 Gtkmm4/gtk142_minesweeper3/src/InputBox.cc create mode 100644 Gtkmm4/gtk142_minesweeper3/src/InputBox.hh create mode 100644 Gtkmm4/gtk142_minesweeper3/src/MineSweeper.cc create mode 100644 Gtkmm4/gtk142_minesweeper3/src/MineSweeper.hh create mode 100644 Gtkmm4/gtk142_minesweeper3/src/ScoresWin.cc create mode 100644 Gtkmm4/gtk142_minesweeper3/src/ScoresWin.hh create mode 100644 Gtkmm4/gtk142_minesweeper3/src/jsonfile.hh create mode 100644 Gtkmm4/gtk142_minesweeper3/src/main.cc diff --git a/Gtkmm4/gtk142_minesweeper3/.vscode/settings.json b/Gtkmm4/gtk142_minesweeper3/.vscode/settings.json new file mode 100644 index 0000000..65a114e --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/.vscode/settings.json @@ -0,0 +1,89 @@ +{ + "files.associations": { + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp", + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "__verbose_abort": "cpp", + "ios": "cpp", + "locale": "cpp", + "queue": "cpp", + "stack": "cpp" + }, + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools" +} \ No newline at end of file diff --git a/Gtkmm4/gtk142_minesweeper3/CMakeLists.txt b/Gtkmm4/gtk142_minesweeper3/CMakeLists.txt new file mode 100644 index 0000000..bb583f4 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/CMakeLists.txt @@ -0,0 +1,88 @@ +set(CMAKE_CXX_STANDARD 17) +cmake_minimum_required(VERSION 3.0.0) +project(gtk142_minesweeper3 VERSION 1.0.0) + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../GCR_CMake/macros) +include(GlibCompileResourcesSupport) + +include(CTest) +enable_testing() + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) + +include(CPack) +include_directories(.) +include_directories(..) + +#Find PkgConfig to use gtkmm3 +find_package (PkgConfig REQUIRED) +pkg_check_modules (GTKMM4 REQUIRED gtkmm-4.0) +include_directories (${GTKMM4_INCLUDE_DIRS}) +link_directories (${GTKMM4_LIBRARY_DIRS}) + +#Find Gettext +# find_package (Gettext REQUIRED) +# set(PO_DIR ${CMAKE_BINARY_DIR}/po/zh_CN/LC_MESSAGES) + +#Source files +set(SOURCE_FILE src/main.cc src/MineSweeper.cc src/InputBox.cc src/ScoresWin.cc) + +#Compile Resource + +set(RESOURCE_LIST + icons/scalable/status/1mines.svg + icons/scalable/status/2mines.svg + icons/scalable/status/3mines.svg + icons/scalable/status/4mines.svg + icons/scalable/status/5mines.svg + icons/scalable/status/6mines.svg + icons/scalable/status/7mines.svg + icons/scalable/status/8mines.svg + icons/scalable/status/exploded.svg + icons/scalable/status/flag.svg + icons/scalable/status/incorrect.svg + icons/scalable/status/maybe.svg + icons/scalable/status/mine.svg + STRIPBLANKS minesweeper.ui + STRIPBLANKS win_input.ui + STRIPBLANKS scoreswin.ui + STRIPBLANKS mine_menu.xml) + +compile_gresources(RESOURCE_FILE + XML_OUT + TYPE EMBED_C + RESOURCES ${RESOURCE_LIST} + PREFIX "/org/gtk/daleclack" + SOURCE_DIR ${PROJECT_SOURCE_DIR}/res) + +# Add a custom target to the makefile. Now make builds our resource file. +# It depends on the output RESOURCE_FILE. + +add_custom_target(resource ALL DEPENDS ${RESOURCE_FILE}) + +#For win32 platform,use rc resource and .ico icon +if(WIN32) + SET(CMAKE_RC_COMPILER windres) + set(app_WINRC ../icon.rc) + set_property(SOURCE ../icon.rc APPEND PROPERTY + OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/../icon.ico + ) + add_executable(${PROJECT_NAME} WIN32 ${app_WINRC} ${SOURCE_FILE} ${RESOURCE_FILE}) + add_custom_command( TARGET ${PROJECT_NAME} + COMMAND echo * > ${CMAKE_BINARY_DIR}/.gitignore + COMMAND echo **/* > ${CMAKE_BINARY_DIR}/.hgignore) +else() + add_executable(${PROJECT_NAME} ${SOURCE_FILE} ${RESOURCE_FILE}) + add_custom_command( TARGET ${PROJECT_NAME} + COMMAND echo \"*\" > ${CMAKE_BINARY_DIR}/.gitignore + COMMAND echo \"**/*\" > ${CMAKE_BINARY_DIR}/.hgignore) +endif(WIN32) + +#Add command to generate .gitignore and .mo files +# add_custom_command( TARGET ${PROJECT_NAME} +# COMMAND mkdir -p ${PO_DIR} +# COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ${CMAKE_SOURCE_DIR}/po/zh_CN.po -o ${PO_DIR}/${PROJECT_NAME}.mo) + +SET (CMAKE_EXTRA_CXX_FLAGS ${GTKMM4_CFLAGS_OTHER}) +target_link_libraries (${PROJECT_NAME} ${GTKMM4_LIBRARIES} -lpthread) diff --git a/Gtkmm4/gtk142_minesweeper3/res/cambalache/.gitignore b/Gtkmm4/gtk142_minesweeper3/res/cambalache/.gitignore new file mode 100644 index 0000000..25284c2 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/cambalache/.gitignore @@ -0,0 +1 @@ +*.ui \ No newline at end of file diff --git a/Gtkmm4/gtk142_minesweeper3/res/cambalache/minesweeper.cmb b/Gtkmm4/gtk142_minesweeper3/res/cambalache/minesweeper.cmb new file mode 100644 index 0000000..6e75fcc --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/cambalache/minesweeper.cmb @@ -0,0 +1,58 @@ + + + + + (1,None,"minesweeper.ui","minesweeper.ui",None,None,None,None,None,None,None), + (2,None,None,"win_input.ui",None,None,None,None,None,None,None), + (3,None,None,"scoreswin.ui",None,None,None,None,None,None,None) + + + (1,1,"GtkWindow","minesweeper",None,None,None,None,None,None), + (1,2,"GtkStackSwitcher",None,1,None,"titlebar",None,-1,None), + (1,3,"GtkStack","main_stack",1,None,None,None,1,None), + (1,4,"GtkGrid","start_page",3,None,None,None,None,None), + (1,5,"GtkBox","main_page",3,None,None,None,1,None), + (1,6,"GtkGrid","custom_page",3,None,None,None,2,None), + (2,1,"GtkDialog",None,None,None,None,None,None,None), + (3,1,"GtkWindow","scores_win",None,None,None,None,None,None), + (3,2,"GtkBox",None,1,None,None,None,-1,None), + (3,3,"GtkBox","btn_box",2,None,None,None,2,None), + (3,4,"GtkTreeView","scores_view",2,None,None,None,1,None), + (3,5,"GtkButton","btnclose",3,None,None,None,2,None), + (3,6,"GtkLabel",None,3,None,None,None,1,None) + + + (1,1,"GtkContainer","resize-mode","queue",None,None,None,None,None), + (1,1,"GtkWindow","default-height","400",None,None,None,None,None), + (1,1,"GtkWindow","default-width","700",None,None,None,None,None), + (1,3,"GtkStack","transition-type","slide-right",None,None,None,None,None), + (1,3,"GtkWidget","halign","baseline",None,None,None,None,None), + (1,4,"GtkGrid","column-homogeneous","True",None,None,None,None,None), + (1,4,"GtkGrid","column-spacing","2",None,None,None,None,None), + (1,4,"GtkGrid","row-homogeneous","True",None,None,None,None,None), + (1,4,"GtkWidget","halign","center",None,None,None,None,None), + (1,4,"GtkWidget","valign","center",None,None,None,None,None), + (1,5,"GtkOrientable","orientation","vertical",None,None,None,None,None), + (2,1,"GtkWidget","expand","True",None,None,None,None,None), + (2,1,"GtkWidget","height-request","200",None,None,None,None,None), + (2,1,"GtkWidget","margin-start","3",None,None,None,None,None), + (2,1,"GtkWidget","width-request","400",None,None,None,None,None), + (2,1,"GtkWindow","gravity","center",None,None,None,None,None), + (3,2,"GtkOrientable","orientation","vertical",None,None,None,None,None), + (3,3,"GtkWidget","height-request","3",None,None,None,None,None), + (3,4,"GtkWidget","height-request","300",None,None,None,None,None), + (3,4,"GtkWidget","valign","start",None,None,None,None,None), + (3,4,"GtkWidget","width-request","400",None,None,None,None,None), + (3,5,"GtkButton","label","Close",None,None,None,None,None), + (3,6,"GtkLabel","label"," ",None,None,None,None,None), + (3,6,"GtkWidget","hexpand","True",None,None,None,None,None) + + + (3,2,3,"GtkBoxLayoutChild","fill","False",None,None,None,None), + (3,2,3,"GtkBoxLayoutChild","position","2",None,None,None,None), + (3,2,4,"GtkBoxLayoutChild","position","1",None,None,None,None), + (3,3,5,"GtkBoxLayoutChild","position","2",None,None,None,None), + (3,3,6,"GtkBoxLayoutChild","fill","False",None,None,None,None), + (3,3,6,"GtkBoxLayoutChild","position","1",None,None,None,None) + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/1mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/1mines.svg new file mode 100644 index 0000000..6bba912 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/1mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 1 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/2mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/2mines.svg new file mode 100644 index 0000000..f9ac25f --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/2mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 2 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/3mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/3mines.svg new file mode 100644 index 0000000..57d249b --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/3mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 3 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/4mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/4mines.svg new file mode 100644 index 0000000..12906ee --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/4mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 4 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/5mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/5mines.svg new file mode 100644 index 0000000..7cb4c23 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/5mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 5 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/6mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/6mines.svg new file mode 100644 index 0000000..960c218 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/6mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 6 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/7mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/7mines.svg new file mode 100644 index 0000000..7e117a5 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/7mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 7 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/8mines.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/8mines.svg new file mode 100644 index 0000000..a3894cc --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/8mines.svg @@ -0,0 +1,80 @@ + + + + + + + + + + image/svg+xml + + + + + + + + 8 + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/exploded.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/exploded.svg new file mode 100644 index 0000000..3211acf --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/exploded.svg @@ -0,0 +1,125 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/flag.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/flag.svg new file mode 100644 index 0000000..ceb16a3 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/flag.svg @@ -0,0 +1,90 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/incorrect.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/incorrect.svg new file mode 100644 index 0000000..ceb16a3 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/incorrect.svg @@ -0,0 +1,90 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/maybe.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/maybe.svg new file mode 100644 index 0000000..1edbd8b --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/maybe.svg @@ -0,0 +1,101 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/mine.svg b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/mine.svg new file mode 100644 index 0000000..c3faf76 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/icons/scalable/status/mine.svg @@ -0,0 +1,125 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/mine_menu.xml b/Gtkmm4/gtk142_minesweeper3/res/mine_menu.xml new file mode 100644 index 0000000..96984dc --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/mine_menu.xml @@ -0,0 +1,27 @@ + + + +
+ + New Game + win.new_game + + + Custom Game + win.custom_game + + + Show Scores + win.scores + + + Show all mines + win.show_mines + + + Quit + win.quit + +
+
+
\ No newline at end of file diff --git a/Gtkmm4/gtk142_minesweeper3/res/minesweeper.ui b/Gtkmm4/gtk142_minesweeper3/res/minesweeper.ui new file mode 100644 index 0000000..42f72bd --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/minesweeper.ui @@ -0,0 +1,41 @@ + + + + + 400 + 700 + + + 0 + + + + + 1 + baseline + slide-right + + + 1 + 1 + 2 + center + 1 + center + + + + + 1 + vertical + + + + + 1 + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/scoreswin.ui b/Gtkmm4/gtk142_minesweeper3/res/scoreswin.ui new file mode 100644 index 0000000..d1a262c --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/scoreswin.ui @@ -0,0 +1,41 @@ + + + + + + + 1 + vertical + + + 1 + 400 + 300 + start + + + + + center + 1 + 3 + + + center + 1 + 1 + + + + + + 1 + Close + + + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/res/win_input.ui b/Gtkmm4/gtk142_minesweeper3/res/win_input.ui new file mode 100644 index 0000000..d1ac8ed --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/res/win_input.ui @@ -0,0 +1,82 @@ + + + + + 300 + 150 + + + 1 + 10 + 10 + 10 + 10 + vertical + 2 + + + center + center + 1 + 1 + vertical + + + center + center + 1 + 1 + + + center + center + Input Name: + + + + + 1 + center + center + + + + + + + Show Scores Window + 1 + + + + + + + + btn_ok + btn_cancel + + + + center + 1 + + + 1 + OK + 1 + 1 + + + + + 1 + Cancel + 1 + 1 + + + + + + diff --git a/Gtkmm4/gtk142_minesweeper3/src/InputBox.cc b/Gtkmm4/gtk142_minesweeper3/src/InputBox.cc new file mode 100644 index 0000000..c46deeb --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/InputBox.cc @@ -0,0 +1,99 @@ +#include "InputBox.hh" + +InputBox::InputBox(BaseObjectType *cobject, const Glib::RefPtr &ref_Glade) + : Gtk::Dialog(cobject), + ref_builder(ref_Glade) +{ + // Get Widgets + entry_name = ref_builder->get_widget("entry_name"); + check_scores = ref_builder->get_widget("check_scores"); + entry_name->signal_activate().connect(sigc::mem_fun(*this, &InputBox::entry_activated)); +} + +void InputBox::on_response(int response_id) +{ + // Open a file to save json data + std::fstream outfile; + outfile.open("scores.json", std::ios_base::out); + if (outfile.is_open()) + { + // Insert data to json + std::string name = std::string((entry_name->get_text()).c_str()); + names.push_back(name); + times.push_back(game_time); + data["name"] = names; + data["time"] = times; + + // Output data + outfile << data; + } + outfile.close(); + if (response_id == Gtk::ResponseType::OK) + { + read_scores(check_scores->get_active()); + } + hide(); +} + +void InputBox::read_scores(bool show_scores_win) +{ + // If show scores checkbutton is checked, show scores window + if (show_scores_win) + { + scores_win1->update_and_show(); + } +} + +void InputBox::set_game_time(int time) +{ + // Try to open json file + std::fstream jsonfile; + jsonfile.open("scores.json", std::ios_base::in); + + // If json file opened, read the data + if (jsonfile.is_open()) + { + data = json::parse(jsonfile); + std::vector names1 = data["name"]; + std::vector times1 = data["time"]; + names = names1; + times = times1; + } + else + { + // Otherwist, create json data + data = json::parse(R"( + { + "name":[" "], + "time":[0] + } + )"); + } + jsonfile.close(); + + // Initalize time + game_time = time; +} + +void InputBox::entry_activated() +{ + // Default response + response(Gtk::ResponseType::OK); +} + +void InputBox::set_scores_window(ScoresWin *win1) +{ + // Bind Scores Window + scores_win1 = win1; +} + +InputBox *InputBox::create() +{ + // Create a inputbox object + auto builder = Gtk::Builder::create_from_resource("/org/gtk/daleclack/win_input.ui"); + + InputBox *dialog; + dialog = Gtk::Builder::get_widget_derived(builder, "dialog"); + + return dialog; +} diff --git a/Gtkmm4/gtk142_minesweeper3/src/InputBox.hh b/Gtkmm4/gtk142_minesweeper3/src/InputBox.hh new file mode 100644 index 0000000..228ddc7 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/InputBox.hh @@ -0,0 +1,38 @@ +#pragma once + +#include +#include "jsonfile.hh" +#include "ScoresWin.hh" + +class InputBox : public Gtk::Dialog{ + public: + static InputBox *create(); + InputBox(BaseObjectType *cobject, const Glib::RefPtr &ref_Glade); + void read_scores(bool show_scores_win = true); + void set_game_time(int time); + void set_scores_window(ScoresWin *win1); + + protected: + void on_response(int response_id) override; + + private: + int game_time; + + // Data to write to json file + json data; + std::vector names; + std::vector times; + + // Builder Object + Glib::RefPtr ref_builder; + + // Child widget + Gtk::Entry *entry_name; + Gtk::CheckButton *check_scores; + + // Scores Window + ScoresWin *scores_win1; + + // Signal Handlers + void entry_activated(); +}; \ No newline at end of file diff --git a/Gtkmm4/gtk142_minesweeper3/src/MineSweeper.cc b/Gtkmm4/gtk142_minesweeper3/src/MineSweeper.cc new file mode 100644 index 0000000..ca05c68 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/MineSweeper.cc @@ -0,0 +1,295 @@ +#include "MineSweeper.hh" +#include +#include + +MineSweeper::MineSweeper() + : main_box(Gtk::Orientation::VERTICAL, 5), + btn_box(Gtk::Orientation::HORIZONTAL, 5), + cell(nullptr) +{ + // Initalize Window + set_title("MineSweeper"); + set_titlebar(header); + header.set_show_title_buttons(); + header.set_decoration_layout("close,minimize,maximize:menu"); + header.pack_end(menu_btn); + set_icon_name("org.gtk.daleclack"); + + // Initalize Menu + menu_builder = Gtk::Builder::create_from_resource("/org/gtk/daleclack/mine_menu.xml"); + auto object = menu_builder->get_object("mine_menu"); + popover1.set_menu_model(object); + // popover1.show(); + menu_btn.set_popover(popover1); + + // Add Actions + add_action("new_game", sigc::mem_fun(*this, &MineSweeper::new_game)); + add_action("scores", sigc::mem_fun(*this, &MineSweeper::show_scores)); + add_action("show_mines", sigc::mem_fun(*this, &MineSweeper::show_mines)); + add_action("quit", sigc::mem_fun(*this, &MineSweeper::hide)); + + // Default setting + reset_game(); + + // Buttons + btnstart.set_label("Start/Reset"); + btnshow.set_label("Show All"); + btnexit.set_label("Exit"); + btn_box.append(btnstart); + btn_box.append(btnshow); + btn_box.append(btnexit); + btnstart.signal_clicked().connect(sigc::mem_fun(*this, &MineSweeper::new_game)); + btnshow.signal_clicked().connect(sigc::mem_fun(*this, &MineSweeper::show_mines)); + btnexit.signal_clicked().connect(sigc::mem_fun(*this, &MineSweeper::hide)); + + // Pack widgets + status_label.set_halign(Gtk::Align::CENTER); + btn_box.set_halign(Gtk::Align::CENTER); + mine_grid.set_halign(Gtk::Align::CENTER); + main_box.append(status_label); + main_box.append(mine_grid); + main_box.append(btn_box); + + // Create a dialog + input_dialog = InputBox::create(); + + // Create Scores Window + scores_win = ScoresWin::create(); + + // Bind windows + input_dialog->set_transient_for(*this); + scores_win->set_transient_for(*this); + input_dialog->set_scores_window(scores_win); + + // Show everything + set_child(main_box); + //show_all_children(); +} + +MineSweeper::~MineSweeper(){ + // Delete all resources + delete input_dialog; + delete scores_win; + if(cell != nullptr){ + delete[] cell; + } +} + +void MineSweeper::new_game(){ + // New game = reset game + reset_game(); +} + +void MineSweeper::reset_game(int width, int height, int mines) +{ + // Clear the cells + if(cell != nullptr){ + delete[] cell; + } + + cell = new MineCell[width * height]; + // Reset timer + mytimer.disconnect(); + timer_count = 0; + mytimer = Glib::signal_timeout().connect(sigc::mem_fun(*this, &MineSweeper::timer_func), 1000); + + mine_count = 0; + mines_clear = 0; + mine_grid.set_sensitive(); + // Reset all data + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + // Initalize cell + cell[i * 7 + j].set_has_frame(); + cell[i * 7 + j].set_image_from_icon_name("", Gtk::IconSize::LARGE); + // cell[i * 7 + j].set_always_show_image(); + cell[i * 7 + j].set_size_request(40, 40); + cell[i * 7 + j].mines_around = 0; + cell[i * 7 + j].has_mine = false; + cell[i * 7 + j].cleared = false; + } + } + + // Reset mines + while (mine_count < mines) + { + int index = g_random_int_range(0, width * height); + if (!(cell[index].has_mine)) + { + cell[index].has_mine = true; + // cell[index].set_label("x"); + mine_count++; + } + } + // std::cout << mine_count << std::endl; + game_ended = false; + winned = true; + status_label.set_label(" "); + calc_mines(); + + // Append buttons to grid + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + // cell[i * 7 + j].set_label("?"); + cell[i * width + j].signal_clicked().connect(sigc::bind( + sigc::mem_fun(*this, &MineSweeper::cell_clicked), &cell[i * width + j])); + mine_grid.attach(cell[i * width + j], j, i); + cell[i * width + j].set_has_frame(); + cell[i * width + j].x = j; + cell[i * width + j].y = i; + cell[i * width + j].cleared = false; + } + } + + mine_grid.show(); +} + +void MineSweeper::calc_mines() +{ + // Calculate the mines around a cell + for (int i = 0; i < 7; i++) + { + for (int j = 0; j < 7; j++) + { + int index1, index2; + // The Search cell should not over the grids + for (index1 = MAX(0, i - 1); index1 < MIN(i + 1, 6) + 1; index1++) + { + for (index2 = MAX(0, j - 1); index2 < MIN(j + 1, 6) + 1; index2++) + { + if ((cell[index1 * 7 + index2].has_mine)) + { + cell[i * 7 + j].mines_around++; + } + } + } + } + } +} + +void MineSweeper::show_mines() +{ + // Show all cell with a mine + for (int i = 0; i < 49; i++) + { + if (cell[i].has_mine) + { + cell[i].set_image_from_icon_name("mine", Gtk::IconSize::LARGE); + } + } +} + +void MineSweeper::show_scores(){ + // Show Scores Window + input_dialog->read_scores(); +} + +void MineSweeper::game_lost(int explode_index){ + // When a cell with mine is clicked, show other mines + for (int i = 0; i < 49; i++) + { + if (cell[i].has_mine && i != explode_index) + { + cell[i].set_image_from_icon_name("mine", Gtk::IconSize::LARGE); + } + } +} + +bool MineSweeper::timer_func() +{ + // Set timer + char tmp[50]; + timer_count++; + sprintf(tmp, "Time:%d", timer_count); + status_label.set_label(tmp); + return true; +} + +void MineSweeper::cell_clicked(MineCell *cell1) +{ + cell1->set_has_frame(false); + if (!game_ended && !cell1->cleared) + { + // + // If get mine, the game will end now + if (cell1->has_mine) + { + // Set game to stop + winned = false; + cell1->cleared = true; + cell1->set_image_from_icon_name("exploded", Gtk::IconSize::LARGE); + + // End the game + game_lost(cell1->y * 7 + cell1->x); + status_label.set_label("You lost!"); + game_ended = true; + mytimer.disconnect(); + mine_grid.set_sensitive(false); + } + else + { + // If no mines, check the cell around + check_mines(cell1->x, cell1->y); + } + } +} + +void MineSweeper::check_mines(int pos_x, int pos_y) +{ + if (pos_x >= 0 && pos_x <= 6 && + pos_y >= 0 && pos_y <= 6) + { + if (!cell[pos_y * 7 + pos_x].has_mine && + !cell[pos_y * 7 + pos_x].cleared) + { + mines_clear++; + // Show the cell has no mines around + if (cell[pos_y * 7 + pos_x].mines_around == 0) + { + cell[pos_y * 7 + pos_x].set_image_from_icon_name("", Gtk::IconSize::LARGE); + } + else + { + // Show the numbers of mines around a cell + char *label = g_strdup_printf("%dmines", cell[pos_y * 7 + pos_x].mines_around); + cell[pos_y * 7 + pos_x].set_image_from_icon_name(label, Gtk::IconSize::LARGE); + g_free(label); + } + + // make the cell without mines cleared + cell[pos_y * 7 + pos_x].set_has_frame(false); + cell[pos_y * 7 + pos_x].cleared = true; + + // Check the cells around a cell that has no mines + if (cell[pos_y * 7 + pos_x].mines_around == 0) + { + check_mines((pos_x - 1), (pos_y - 1)); + check_mines((pos_x + 1), (pos_y + 1)); + check_mines((pos_x - 1), (pos_y + 1)); + check_mines((pos_x + 1), (pos_y - 1)); + check_mines(pos_x, (pos_y - 1)); + check_mines(pos_x, (pos_y + 1)); + check_mines((pos_x + 1), pos_y); + check_mines((pos_x - 1), pos_y); + } + } + } + + // If all the mines has cleared, you has winned + if (mines_clear == 40) + { + // Stop the game + status_label.set_label("You winned!"); + winned = true; + game_ended = true; + mytimer.disconnect(); + + // Save the time of game + input_dialog->set_game_time(timer_count); + input_dialog->show(); + } +} diff --git a/Gtkmm4/gtk142_minesweeper3/src/MineSweeper.hh b/Gtkmm4/gtk142_minesweeper3/src/MineSweeper.hh new file mode 100644 index 0000000..3072629 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/MineSweeper.hh @@ -0,0 +1,67 @@ +#pragma once + +#include +#include "InputBox.hh" +#include "ScoresWin.hh" + +class MineCell : public Gtk::Button +{ +public: + bool has_mine = false; // Whether the grid has mine + bool cleared = false; // Whether the mine is cleared + int mines_around; // The number near the grid + int x, y; // The Position of the grid + MineCell() + { + // Set button style + mines_around = 0; + } +}; + +class MineSweeper : public Gtk::ApplicationWindow +{ +public: + MineSweeper(); + ~MineSweeper(); + +private: + // HeaderBar + Gtk::HeaderBar header; + Gtk::MenuButton menu_btn; + Gtk::PopoverMenu popover1; + + // Child widgets + Gtk::Grid mine_grid; + Gtk::Label status_label; + Gtk::Box main_box, btn_box; + Gtk::Button btnstart, btnshow, btnexit; + + // The cell to place mines + MineCell *cell; + bool winned, game_ended; // The status of game(win/end) + int mines_clear, mine_count; // Whether the mine is cleared + + // Menu + Glib::RefPtr menu_builder; + + // Timer + int timer_count; + sigc::connection mytimer; + + // Input dialog + InputBox *input_dialog; + + // Scores Window + ScoresWin *scores_win; + + // Signal Handlers + void new_game(); // "New Game" handler + void reset_game(int width = 7, int height = 7, int mines = 9); // Reset all mines + void calc_mines(); // Get the mines around + void show_mines(); // Show all mines + void show_scores(); // Show all scores + void game_lost(int explode_index); // You lost the game + void cell_clicked(MineCell *cell1); // Open a cell + bool timer_func(); // Timer + void check_mines(int pos_x, int pos_y); // Check if there is a mine +}; diff --git a/Gtkmm4/gtk142_minesweeper3/src/ScoresWin.cc b/Gtkmm4/gtk142_minesweeper3/src/ScoresWin.cc new file mode 100644 index 0000000..ea2450c --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/ScoresWin.cc @@ -0,0 +1,77 @@ +#include "ScoresWin.hh" + +ScoresWin::ScoresWin(BaseObjectType *cobject, const Glib::RefPtr &ref_Glade) + : Gtk::Window(cobject), + ref_builder(ref_Glade) +{ + // Get Widgets + btnclose = ref_builder->get_widget("btnclose"); + tree_view = ref_builder->get_widget("scores_view"); + btnclose->signal_clicked().connect(sigc::mem_fun(*this, &ScoresWin::hide)); + + // Create the list store + store = Gtk::ListStore::create(column1); + store->set_sort_column(column1.win_time, Gtk::SortType::DESCENDING); + // store->set_default_sort_func(sigc::mem_fun(*this, &ScoresWin::sort_func)); + tree_view->set_model(store); + tree_view->append_column("name", column1.player_name); + tree_view->append_column("time", column1.win_time); +} + +void ScoresWin::update_and_show() +{ + std::fstream infile; + infile.open("scores.json", std::ios_base::in); + + if (infile.is_open()) + { + // Read data from json file + json data = json::parse(infile); + std::vector name_vec = data["name"]; + std::vector time_vec = data["time"]; + + // Clear the store + store->clear(); + + // Append data to the store + for (int i = 0; i < name_vec.size(); i++) + { + auto row = *(store->append()); + row[column1.player_name] = name_vec[i]; + row[column1.win_time] = time_vec[i]; + } + } + + show(); +} + +int ScoresWin::sort_func(const Gtk::TreeModel::iterator &iter1, const Gtk::TreeModel::iterator &iter2) +{ + // Sort by the game time + auto row1 = *iter1; + auto row2 = *iter2; + if (row1[column1.win_time] < row2[column1.win_time]) + { + return -1; + } + if (row1[column1.win_time] == row2[column1.win_time]) + { + return 0; + } + else + { + return 1; + } +} + +ScoresWin *ScoresWin::create() +{ + // Create a window + auto builder = Gtk::Builder::create_from_resource("/org/gtk/daleclack/scoreswin.ui"); + ScoresWin *main_win; + + // builder->get_widget_derived("scores_win", main_win); + main_win = Gtk::Builder::get_widget_derived(builder, "scores_win"); + + return main_win; +} diff --git a/Gtkmm4/gtk142_minesweeper3/src/ScoresWin.hh b/Gtkmm4/gtk142_minesweeper3/src/ScoresWin.hh new file mode 100644 index 0000000..f87ec2f --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/ScoresWin.hh @@ -0,0 +1,35 @@ +#pragma once + +#include +#include "jsonfile.hh" + +class ScoresWin : public Gtk::Window{ + public: + static ScoresWin *create(); + ScoresWin(BaseObjectType *cobject, const Glib::RefPtr &ref_Glade); + void update_and_show(); + + private: + Glib::RefPtr ref_builder; + + // Child widgets + Gtk::Button *btnclose; + Gtk::TreeView *tree_view; + + // TreeView data + class ModelColumns : public Gtk::TreeModelColumnRecord{ + public: + ModelColumns(){ + add(player_name); + add(win_time); + } + Gtk::TreeModelColumn player_name; + Gtk::TreeModelColumn win_time; + }; + ModelColumns column1; + + Glib::RefPtr store; + + // Sort function + int sort_func(const Gtk::TreeModel::iterator &iter1, const Gtk::TreeModel::iterator &iter2); +}; diff --git a/Gtkmm4/gtk142_minesweeper3/src/jsonfile.hh b/Gtkmm4/gtk142_minesweeper3/src/jsonfile.hh new file mode 100644 index 0000000..6fbdabb --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/jsonfile.hh @@ -0,0 +1,7 @@ +#pragma once + +#include "../json_nlohmann/json.hpp" +#include +#include + +using json = nlohmann::json; diff --git a/Gtkmm4/gtk142_minesweeper3/src/main.cc b/Gtkmm4/gtk142_minesweeper3/src/main.cc new file mode 100644 index 0000000..6110cf2 --- /dev/null +++ b/Gtkmm4/gtk142_minesweeper3/src/main.cc @@ -0,0 +1,8 @@ +#include "MineSweeper.hh" + +int main(int argc, char **argv){ + // Create a application and run + auto app = Gtk::Application::create("org.gtk.daleclack"); + + return app->make_window_and_run(argc,argv); +}