添加AI算法框架,大量修改模型

This commit is contained in:
liuweilhy 2018-11-29 03:35:48 +08:00
parent 3ab9610c07
commit 022ae41475
78 changed files with 820 additions and 558 deletions

23
.gitignore vendored
View File

@ -1,4 +1,4 @@
## Ignore Visual Studio temporary files, build results, and
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
@ -260,14 +260,7 @@ paket-files/
__pycache__/
*.pyc
# exe and dll
*.exe
*.dll
# backup
*.bak
#############################################
# QT
# C++ objects and libs
@ -313,3 +306,15 @@ target_wrapper.*
# QtCreator CMake
CMakeLists.txt.user*
###########################################
# exe and dll
*.exe
*.dll
# backup
*.bak
# visual studio code
.vscode/

View File

@ -3,7 +3,6 @@
# Project created by QtCreator 2015-11-03T22:30:34
#
#-------------------------------------------------
#QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01
QT += core gui \
multimedia
@ -23,6 +22,7 @@ SOURCES += \
src/gamescene.cpp \
src/gameview.cpp \
src/ninechess.cpp \
src/ninechessai_ab.cpp \
src/ninechesswindow.cpp \
src/pieceitem.cpp \
src/aithread.cpp
@ -34,9 +34,10 @@ HEADERS += \
src/gameview.h \
src/graphicsconst.h \
src/ninechess.h \
src/ninechessai_ab.h \
src/ninechesswindow.h \
src/pieceitem.h \
src/sizehintlistview.h \
src/manuallistview.h \
src/aithread.h
FORMS += \
@ -46,10 +47,10 @@ RESOURCES += \
ninechesswindow.qrc
DISTFILES += \
NineChess.rc \
../Readme.md \
../范例棋谱.txt \
../History.txt \
../Licence.txt \
NineChess.rc
../Licence.txt
RC_FILE += NineChess.rc

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.7.2, 2018-11-20T23:27:26. -->
<!-- Written by QtCreator 4.6.1, 2018-11-29T03:34:51. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{9a8c5f9d-1814-40d9-ab01-983c45f229c5}</value>
<value type="QByteArray">{fba36f69-c7a3-4c3f-91d4-7c71ad79549c}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
@ -54,22 +54,19 @@
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
</valuemap>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.9.7 GCC 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.9.7 GCC 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.597.gcc_64_kit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.11.0 MSVC2017 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.11.0 MSVC2017 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5110.win64_msvc2017_64_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@ -87,10 +84,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
@ -106,10 +100,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
@ -129,7 +120,7 @@
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@ -147,10 +138,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
@ -166,10 +154,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
@ -189,7 +174,7 @@
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Profile</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@ -207,10 +192,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
@ -226,10 +208,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
@ -257,7 +236,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署设置</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
@ -307,10 +286,11 @@
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">ninechess</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/media/sniper/Work/My program/QT/NineChess/NineChess/ninechess.pro</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:E:/My program/QT/NineChess/NineChess/ninechess.pro</value>
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">ninechess.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>

View File

@ -371,17 +371,29 @@
</QtUic>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\aithread.cpp" />
<ClCompile Include="src\boarditem.cpp" />
<ClCompile Include="src\gamecontroller.cpp" />
<ClCompile Include="src\gamescene.cpp" />
<ClCompile Include="src\gameview.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\ninechess.cpp" />
<ClCompile Include="src\ninechessai_ab.cpp" />
<ClCompile Include="src\ninechesswindow.cpp" />
<ClCompile Include="src\pieceitem.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
<QtMoc Include="src\aithread.h">
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\debug;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<Define Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\debug;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<Define Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\release;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<Define Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\release;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
</QtMoc>
<ClInclude Include="src\boarditem.h">
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\debug;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\debug;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
@ -419,11 +431,15 @@
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;release;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
</QtMoc>
<QtMoc Include="src\pieceitem.h" />
<QtMoc Include="src\sizehintlistview.h">
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;debug;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;debug;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;release;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;release;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
<QtMoc Include="src\manuallistview.h">
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\debug;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\debug;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\release;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(QTDIR)\include;.\release;\include;$(QTDIR)\mkspecs\win32-msvc;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtNetwork</IncludePath>
<Define Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
<Define Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
<Define Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
<Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_WIDGETS_LIB;QT_CORE_LIB;QT_GUI_LIB;QT_MULTIMEDIA_LIB;QT_NETWORK_LIB</Define>
</QtMoc>
</ItemGroup>
<ItemGroup>
@ -481,6 +497,7 @@
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</AdditionalInputs>
</CustomBuild>
<ClInclude Include="src\ninechessai_ab.h" />
<ClInclude Include="ui_ninechesswindow.h" />
</ItemGroup>
<ItemGroup>
@ -490,6 +507,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\Readme.md" />
<None Include="ninechess.pro" />
<None Include="Resources\icon\ActualSizeHS.png" />
<None Include="Resources\icon\Black.png" />
<None Include="Resources\icon\BreakpointHS.png" />

View File

@ -50,10 +50,11 @@
<Extensions>*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Distribution Files">
<UniqueIdentifier>{B83CAF91-C7BF-462F-B76C-EA11631F866C}</UniqueIdentifier>
<Extensions>*</Extensions>
<ParseFiles>false</ParseFiles>
<Filter Include="Text Files">
<UniqueIdentifier>{d3810898-e5d4-49ce-92da-beddffba0697}</UniqueIdentifier>
</Filter>
<Filter Include="Project Files">
<UniqueIdentifier>{16c52ca8-0391-4ad2-919c-4a865ad87e98}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@ -81,6 +82,12 @@
<ClCompile Include="src\pieceitem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\aithread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ninechessai_ab.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\gamecontroller.h">
@ -107,6 +114,12 @@
<QtMoc Include="src\pieceitem.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\aithread.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\manuallistview.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
@ -236,27 +249,40 @@
<None Include="Resources\image\white_piece.png">
<Filter>Resource Files</Filter>
</None>
<None Include="..\Readme.md" />
<None Include="..\Readme.md">
<Filter>Text Files</Filter>
</None>
<None Include="ninechess.pro">
<Filter>Project Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="NineChess.rc" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\sizehintlistview.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<Text Include="..\History.txt" />
<Text Include="..\Licence.txt" />
<Text Include="..\范例棋谱.txt" />
</ItemGroup>
<ItemGroup>
<Image Include="NineChess.ico" />
<Text Include="..\History.txt">
<Filter>Text Files</Filter>
</Text>
<Text Include="..\Licence.txt">
<Filter>Text Files</Filter>
</Text>
<Text Include="..\范例棋谱.txt">
<Filter>Text Files</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\boarditem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\ninechessai_ab.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="NineChess.ico">
<Filter>Project Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="NineChess.rc">
<Filter>Project Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -1,54 +1,54 @@
<RCC>
<qresource prefix="/image">
<file>Resources/image/black_piece.png</file>
<file>Resources/image/board.png</file>
<file>Resources/image/white_piece.png</file>
<file>Resources/image/background.png</file>
<file>resources/image/black_piece.png</file>
<file>resources/image/board.png</file>
<file>resources/image/white_piece.png</file>
<file>resources/image/background.png</file>
</qresource>
<qresource prefix="/icon">
<file>Resources/icon/Black.png</file>
<file>Resources/icon/White.png</file>
<file>Resources/icon/ActualSizeHS.png</file>
<file>Resources/icon/BreakpointHS.png</file>
<file>Resources/icon/DocumentHS.png</file>
<file>Resources/icon/EditInformationHS.png</file>
<file>Resources/icon/EditTableHS.png</file>
<file>Resources/icon/Error.png</file>
<file>Resources/icon/First.png</file>
<file>Resources/icon/FlipHorizontalHS.png</file>
<file>Resources/icon/FlipVerticalHS.png</file>
<file>Resources/icon/FullScreenHS.png</file>
<file>Resources/icon/Help.png</file>
<file>Resources/icon/HomeHS.png</file>
<file>Resources/icon/Last.png</file>
<file>Resources/icon/LeftHS.png</file>
<file>Resources/icon/LegendHS.png</file>
<file>Resources/icon/NewDocumentHS.png</file>
<file>Resources/icon/Next.png</file>
<file>Resources/icon/OpenHS.png</file>
<file>Resources/icon/Pause.png</file>
<file>Resources/icon/Play.png</file>
<file>Resources/icon/Previous.png</file>
<file>Resources/icon/PrimaryKeyHS.png</file>
<file>Resources/icon/Refresh.png</file>
<file>Resources/icon/Request.png</file>
<file>Resources/icon/OptionsHS.png</file>
<file>Resources/icon/Web.png</file>
<file>Resources/icon/RestartHS.png</file>
<file>Resources/icon/Invert.png</file>
<file>Resources/icon/RightHS.png</file>
<file>Resources/icon/SaveHS.png</file>
<file>resources/icon/Black.png</file>
<file>resources/icon/White.png</file>
<file>resources/icon/ActualSizeHS.png</file>
<file>resources/icon/BreakpointHS.png</file>
<file>resources/icon/DocumentHS.png</file>
<file>resources/icon/EditInformationHS.png</file>
<file>resources/icon/EditTableHS.png</file>
<file>resources/icon/Error.png</file>
<file>resources/icon/First.png</file>
<file>resources/icon/FlipHorizontalHS.png</file>
<file>resources/icon/FlipVerticalHS.png</file>
<file>resources/icon/FullScreenHS.png</file>
<file>resources/icon/Help.png</file>
<file>resources/icon/HomeHS.png</file>
<file>resources/icon/Last.png</file>
<file>resources/icon/LeftHS.png</file>
<file>resources/icon/LegendHS.png</file>
<file>resources/icon/NewDocumentHS.png</file>
<file>resources/icon/Next.png</file>
<file>resources/icon/OpenHS.png</file>
<file>resources/icon/Pause.png</file>
<file>resources/icon/Play.png</file>
<file>resources/icon/Previous.png</file>
<file>resources/icon/PrimaryKeyHS.png</file>
<file>resources/icon/Refresh.png</file>
<file>resources/icon/Request.png</file>
<file>resources/icon/OptionsHS.png</file>
<file>resources/icon/Web.png</file>
<file>resources/icon/RestartHS.png</file>
<file>resources/icon/Invert.png</file>
<file>resources/icon/RightHS.png</file>
<file>resources/icon/SaveHS.png</file>
</qresource>
<qresource prefix="/sound">
<file>Resources/sound/choose.wav</file>
<file>Resources/sound/drog.wav</file>
<file>Resources/sound/forbidden.wav</file>
<file>Resources/sound/loss.wav</file>
<file>Resources/sound/move.wav</file>
<file>Resources/sound/newgame.wav</file>
<file>Resources/sound/remove.wav</file>
<file>Resources/sound/win.wav</file>
<file>Resources/sound/warning.wav</file>
<file>Resources/sound/capture.wav</file>
<file>resources/sound/choose.wav</file>
<file>resources/sound/drog.wav</file>
<file>resources/sound/forbidden.wav</file>
<file>resources/sound/loss.wav</file>
<file>resources/sound/move.wav</file>
<file>resources/sound/newgame.wav</file>
<file>resources/sound/remove.wav</file>
<file>resources/sound/win.wav</file>
<file>resources/sound/warning.wav</file>
<file>resources/sound/capture.wav</file>
</qresource>
</RCC>

View File

@ -39,7 +39,7 @@
</size>
</property>
<property name="styleSheet">
<string notr="true">background-image: url(:/image/Resources/image/background.png);</string>
<string notr="true">background-image: url(:/image/resources/image/background.png);</string>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
@ -57,7 +57,7 @@
<x>0</x>
<y>0</y>
<width>491</width>
<height>23</height>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menu_F">
@ -247,7 +247,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="ninechesswindow.qrc">:/icon/Resources/icon/Black.png</pixmap>
<pixmap resource="ninechesswindow.qrc">:/icon/resources/icon/Black.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@ -328,7 +328,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="ninechesswindow.qrc">:/icon/Resources/icon/White.png</pixmap>
<pixmap resource="ninechesswindow.qrc">:/icon/resources/icon/White.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@ -398,7 +398,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="ninechesswindow.qrc">:/icon/Resources/icon/Help.png</pixmap>
<pixmap resource="ninechesswindow.qrc">:/icon/resources/icon/Help.png</pixmap>
</property>
</widget>
</item>
@ -424,7 +424,7 @@
</layout>
</item>
<item>
<widget class="SizeHintListView" name="listView">
<widget class="ManualListView" name="listView">
<property name="font">
<font>
<pointsize>7</pointsize>
@ -443,7 +443,7 @@
<action name="actionNew_N">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/DocumentHS.png</normaloff>:/icon/Resources/icon/DocumentHS.png</iconset>
<normaloff>:/icon/resources/icon/DocumentHS.png</normaloff>:/icon/resources/icon/DocumentHS.png</iconset>
</property>
<property name="text">
<string>新建(&amp;N)</string>
@ -458,7 +458,7 @@
<action name="actionOpen_O">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/OpenHS.png</normaloff>:/icon/Resources/icon/OpenHS.png</iconset>
<normaloff>:/icon/resources/icon/OpenHS.png</normaloff>:/icon/resources/icon/OpenHS.png</iconset>
</property>
<property name="text">
<string>打开(&amp;O)...</string>
@ -470,7 +470,7 @@
<action name="actionSave_S">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/SaveHS.png</normaloff>:/icon/Resources/icon/SaveHS.png</iconset>
<normaloff>:/icon/resources/icon/SaveHS.png</normaloff>:/icon/resources/icon/SaveHS.png</iconset>
</property>
<property name="text">
<string>保存(&amp;S)</string>
@ -482,7 +482,7 @@
<action name="actionSaveAs_A">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/SaveHS.png</normaloff>:/icon/Resources/icon/SaveHS.png</iconset>
<normaloff>:/icon/resources/icon/SaveHS.png</normaloff>:/icon/resources/icon/SaveHS.png</iconset>
</property>
<property name="text">
<string>另存为(&amp;A)...</string>
@ -499,7 +499,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/EditTableHS.png</normaloff>:/icon/Resources/icon/EditTableHS.png</iconset>
<normaloff>:/icon/resources/icon/EditTableHS.png</normaloff>:/icon/resources/icon/EditTableHS.png</iconset>
</property>
<property name="text">
<string>编辑棋局(&amp;E)</string>
@ -508,7 +508,7 @@
<action name="actionFlip_F">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/FlipVerticalHS.png</normaloff>:/icon/Resources/icon/FlipVerticalHS.png</iconset>
<normaloff>:/icon/resources/icon/FlipVerticalHS.png</normaloff>:/icon/resources/icon/FlipVerticalHS.png</iconset>
</property>
<property name="text">
<string>上下翻转(&amp;F)</string>
@ -517,7 +517,7 @@
<action name="actionMirror_M">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/FlipHorizontalHS.png</normaloff>:/icon/Resources/icon/FlipHorizontalHS.png</iconset>
<normaloff>:/icon/resources/icon/FlipHorizontalHS.png</normaloff>:/icon/resources/icon/FlipHorizontalHS.png</iconset>
</property>
<property name="text">
<string>左右翻转(&amp;M)</string>
@ -526,7 +526,7 @@
<action name="actionTurnRight_R">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/RightHS.png</normaloff>:/icon/Resources/icon/RightHS.png</iconset>
<normaloff>:/icon/resources/icon/RightHS.png</normaloff>:/icon/resources/icon/RightHS.png</iconset>
</property>
<property name="text">
<string>顺时针旋转90°(&amp;R)</string>
@ -538,7 +538,7 @@
<action name="actionTurnLeftt_L">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/LeftHS.png</normaloff>:/icon/Resources/icon/LeftHS.png</iconset>
<normaloff>:/icon/resources/icon/LeftHS.png</normaloff>:/icon/resources/icon/LeftHS.png</iconset>
</property>
<property name="text">
<string>逆时针旋转90°(&amp;L)</string>
@ -556,7 +556,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Invert.png</normaloff>:/icon/Resources/icon/Invert.png</iconset>
<normaloff>:/icon/resources/icon/Invert.png</normaloff>:/icon/resources/icon/Invert.png</iconset>
</property>
<property name="text">
<string>黑白反转(&amp;B)</string>
@ -565,7 +565,7 @@
<action name="actionBegin_S">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/First.png</normaloff>:/icon/Resources/icon/First.png</iconset>
<normaloff>:/icon/resources/icon/First.png</normaloff>:/icon/resources/icon/First.png</iconset>
</property>
<property name="text">
<string>初始局面(&amp;S)</string>
@ -580,7 +580,7 @@
<action name="actionPrevious_B">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Previous.png</normaloff>:/icon/Resources/icon/Previous.png</iconset>
<normaloff>:/icon/resources/icon/Previous.png</normaloff>:/icon/resources/icon/Previous.png</iconset>
</property>
<property name="text">
<string>前一招(&amp;B)</string>
@ -592,7 +592,7 @@
<action name="actionNext_F">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Next.png</normaloff>:/icon/Resources/icon/Next.png</iconset>
<normaloff>:/icon/resources/icon/Next.png</normaloff>:/icon/resources/icon/Next.png</iconset>
</property>
<property name="text">
<string>后一招(&amp;F)</string>
@ -607,7 +607,7 @@
<action name="actionEnd_E">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Last.png</normaloff>:/icon/Resources/icon/Last.png</iconset>
<normaloff>:/icon/resources/icon/Last.png</normaloff>:/icon/resources/icon/Last.png</iconset>
</property>
<property name="text">
<string>最后局面(&amp;E)</string>
@ -622,7 +622,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Play.png</normaloff>:/icon/Resources/icon/Play.png</iconset>
<normaloff>:/icon/resources/icon/Play.png</normaloff>:/icon/resources/icon/Play.png</iconset>
</property>
<property name="text">
<string>自动演示(&amp;A)</string>
@ -634,7 +634,7 @@
<action name="actionGiveUp_G">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/BreakpointHS.png</normaloff>:/icon/Resources/icon/BreakpointHS.png</iconset>
<normaloff>:/icon/resources/icon/BreakpointHS.png</normaloff>:/icon/resources/icon/BreakpointHS.png</iconset>
</property>
<property name="text">
<string>认输(&amp;G)</string>
@ -660,7 +660,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/FullScreenHS.png</normaloff>:/icon/Resources/icon/FullScreenHS.png</iconset>
<normaloff>:/icon/resources/icon/FullScreenHS.png</normaloff>:/icon/resources/icon/FullScreenHS.png</iconset>
</property>
<property name="text">
<string>本机对战(&amp;L)</string>
@ -678,7 +678,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Web.png</normaloff>:/icon/Resources/icon/Web.png</iconset>
<normaloff>:/icon/resources/icon/Web.png</normaloff>:/icon/resources/icon/Web.png</iconset>
</property>
<property name="text">
<string>网络对战(&amp;I)</string>
@ -690,7 +690,7 @@
<action name="actionEngine_E">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/OptionsHS.png</normaloff>:/icon/Resources/icon/OptionsHS.png</iconset>
<normaloff>:/icon/resources/icon/OptionsHS.png</normaloff>:/icon/resources/icon/OptionsHS.png</iconset>
</property>
<property name="text">
<string>引擎设置(&amp;E)...</string>
@ -708,7 +708,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Black.png</normaloff>:/icon/Resources/icon/Black.png</iconset>
<normaloff>:/icon/resources/icon/Black.png</normaloff>:/icon/resources/icon/Black.png</iconset>
</property>
<property name="text">
<string>电脑执先手(&amp;T)</string>
@ -723,7 +723,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/White.png</normaloff>:/icon/Resources/icon/White.png</iconset>
<normaloff>:/icon/resources/icon/White.png</normaloff>:/icon/resources/icon/White.png</iconset>
</property>
<property name="text">
<string>电脑执后手(&amp;R)</string>
@ -738,7 +738,7 @@
</property>
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/PrimaryKeyHS.png</normaloff>:/icon/Resources/icon/PrimaryKeyHS.png</iconset>
<normaloff>:/icon/resources/icon/PrimaryKeyHS.png</normaloff>:/icon/resources/icon/PrimaryKeyHS.png</iconset>
</property>
<property name="text">
<string>设置(&amp;O)...</string>
@ -808,7 +808,7 @@
<action name="actionViewHelp_V">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/Help.png</normaloff>:/icon/Resources/icon/Help.png</iconset>
<normaloff>:/icon/resources/icon/Help.png</normaloff>:/icon/resources/icon/Help.png</iconset>
</property>
<property name="text">
<string>查看帮助(&amp;V)</string>
@ -820,7 +820,7 @@
<action name="actionWeb_W">
<property name="icon">
<iconset resource="ninechesswindow.qrc">
<normaloff>:/icon/Resources/icon/HomeHS.png</normaloff>:/icon/Resources/icon/HomeHS.png</iconset>
<normaloff>:/icon/resources/icon/HomeHS.png</normaloff>:/icon/resources/icon/HomeHS.png</iconset>
</property>
<property name="text">
<string>作者主页(&amp;W)</string>
@ -846,9 +846,9 @@
<header>gameview.h</header>
</customwidget>
<customwidget>
<class>SizeHintListView</class>
<class>ManualListView</class>
<extends>QListView</extends>
<header>sizehintlistview.h</header>
<header>manuallistview.h</header>
</customwidget>
</customwidgets>
<resources>

View File

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 228 B

View File

Before

Width:  |  Height:  |  Size: 528 B

After

Width:  |  Height:  |  Size: 528 B

View File

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 757 B

View File

Before

Width:  |  Height:  |  Size: 380 B

After

Width:  |  Height:  |  Size: 380 B

View File

Before

Width:  |  Height:  |  Size: 736 B

After

Width:  |  Height:  |  Size: 736 B

View File

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 390 B

View File

Before

Width:  |  Height:  |  Size: 621 B

After

Width:  |  Height:  |  Size: 621 B

View File

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 665 B

View File

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 865 B

View File

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 527 B

View File

Before

Width:  |  Height:  |  Size: 560 B

After

Width:  |  Height:  |  Size: 560 B

View File

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 597 B

View File

Before

Width:  |  Height:  |  Size: 574 B

After

Width:  |  Height:  |  Size: 574 B

View File

Before

Width:  |  Height:  |  Size: 761 B

After

Width:  |  Height:  |  Size: 761 B

View File

Before

Width:  |  Height:  |  Size: 619 B

After

Width:  |  Height:  |  Size: 619 B

View File

Before

Width:  |  Height:  |  Size: 869 B

After

Width:  |  Height:  |  Size: 869 B

View File

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 515 B

View File

Before

Width:  |  Height:  |  Size: 685 B

After

Width:  |  Height:  |  Size: 685 B

View File

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 650 B

View File

Before

Width:  |  Height:  |  Size: 574 B

After

Width:  |  Height:  |  Size: 574 B

View File

Before

Width:  |  Height:  |  Size: 427 B

After

Width:  |  Height:  |  Size: 427 B

View File

Before

Width:  |  Height:  |  Size: 743 B

After

Width:  |  Height:  |  Size: 743 B

View File

Before

Width:  |  Height:  |  Size: 572 B

After

Width:  |  Height:  |  Size: 572 B

View File

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 297 B

View File

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 355 B

View File

Before

Width:  |  Height:  |  Size: 420 B

After

Width:  |  Height:  |  Size: 420 B

View File

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 472 B

View File

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 633 B

View File

Before

Width:  |  Height:  |  Size: 773 B

After

Width:  |  Height:  |  Size: 773 B

View File

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 473 B

View File

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 672 B

View File

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 595 B

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 636 B

After

Width:  |  Height:  |  Size: 636 B

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 926 B

View File

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 292 B

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1003 B

After

Width:  |  Height:  |  Size: 1003 B

View File

@ -1,4 +1,4 @@
#include <QDebug>
#include <QDebug>
#include "aithread.h"
AiThread::AiThread(QObject *parent) : QThread(parent),
@ -13,13 +13,21 @@ AiThread::~AiThread()
wait();
}
void AiThread::setAi(const NineChess &chess)
{
mutex.lock();
this->chess = chess;
ai_ab.setChess(chess);
mutex.unlock();
}
void AiThread::run()
{
// 测试用数据
int iTemp = 0;
while (true) {
if(isInterruptionRequested())
if (isInterruptionRequested())
return;
mutex.lock();
if (waiting_)
@ -29,17 +37,10 @@ void AiThread::run()
// 测试用
qDebug() << "thread running " << iTemp << "ms";
msleep(250);
iTemp+=250;
iTemp += 250;
}
}
void AiThread::setChess(NineChess &chess)
{
mutex.lock();
this->chess = chess;
mutex.unlock();
}
void AiThread::pause()
{
mutex.lock();

View File

@ -1,27 +1,29 @@
#ifndef AITHREAD_H
#ifndef AITHREAD_H
#define AITHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include "ninechess.h"
#include "ninechessai_ab.h"
class AiThread : public QThread
{
Q_OBJECT
public:
explicit AiThread(QObject *parent = nullptr);
~AiThread();
signals:
// 招法信号
void command(QString cmdline);
void command(const QString &cmdline, bool update = true);
protected:
void run() override;
public slots:
void setChess(NineChess &);
void setAi(const NineChess &);
void pause();
void resume();
void stop();
@ -36,6 +38,8 @@ private:
// 棋类
NineChess chess;
// Alpha-Beta剪枝算法类
NineChessAi_ab ai_ab;
};
#endif // AITHREAD_H

View File

@ -63,10 +63,13 @@ void BoardItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
// 填充阴影
painter->fillRect(boundingRect(), QBrush(QColor(64, 64, 64)));
// 填充图片
painter->drawPixmap(-size/2, -size/2, size, size, QPixmap(":/image/Resources/image/board.png"));
painter->drawPixmap(-size/2, -size/2, size, size, QPixmap(":/image/resources/image/board.png"));
// 黑色实线画笔
QPen pen(QBrush(Qt::black), LINE_WEIGHT, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin);
painter->setPen(pen);

View File

@ -17,37 +17,42 @@
#include "boarditem.h"
GameController::GameController(GameScene &scene, QObject *parent) : QObject(parent),
// 是否浏览过历史纪录
scene(scene),
currentPiece(nullptr),
currentRow(-1),
isEditing(false),
isInverted(false),
isEngine1(false),
isEngine2(false),
hasAnimation(true),
durationTime(250),
hasSound(true),
timeID(0),
ruleNo(-1),
timeLimit(0),
stepsLimit(0)
scene(scene),
currentPiece(nullptr),
currentRow(-1),
isEditing(false),
isInverted(false),
isEngine1(false),
isEngine2(false),
hasAnimation(true),
durationTime(250),
hasSound(true),
timeID(0),
ruleNo(-1),
timeLimit(0),
stepsLimit(0)
{
// 已在view的样式表中添加背景scene中不用添加背景
// 区别在于view中的背景不随视图变换而变换scene中的背景随视图变换而变换
//scene.setBackgroundBrush(QPixmap(":/image/Resources/image/background.png"));
//scene.setBackgroundBrush(QPixmap(":/image/resources/image/background.png"));
gameReset();
// 关联AI和控制器的招法命令行
connect(&ai1, SIGNAL(command(const QString &, bool)),
this, SLOT(command(const QString &, bool)));
connect(&ai2, SIGNAL(command(const QString &, bool)),
this, SLOT(command(const QString &, bool)));
// 安装事件过滤器监视scene的各个事件由于我重载了QGraphicsScene相关事件在重载函数中已设定不必安装监视器。
//scene.installEventFilter(this);
}
GameController::~GameController()
{
// 清除棋子
qDeleteAll(pieceList);
pieceList.clear();
currentPiece = nullptr;
// 停止计时器
if (timeID != 0)
killTimer(timeID);
}
const QMap<int, QStringList> GameController::getActions()
@ -86,7 +91,7 @@ void GameController::gameReset()
timeID = 0;
// 重置游戏
chess.reset();
chessTemp.reset();
chessTemp = chess;
// 清除棋子
qDeleteAll(pieceList);
@ -123,7 +128,6 @@ void GameController::gameReset()
scene.addItem(newP);
}
// 读取规则限时要求
timeLimit = chess.getRule()->maxTime;
// 如果规则不要求计时则time1和time2表示已用时间
@ -150,7 +154,7 @@ void GameController::gameReset()
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放音效
playSound(":/sound/Resources/sound/newgame.wav");
playSound(":/sound/resources/sound/newgame.wav");
}
void GameController::setEditing(bool arg)
@ -202,7 +206,7 @@ void GameController::setEngine1(bool arg)
isEngine1 = arg;
if (arg) {
qDebug() << "Player1 is computer.";
ai1.setChess(chess);
ai1.setAi(chess);
ai1.start();
}
else {
@ -214,14 +218,7 @@ void GameController::setEngine1(bool arg)
void GameController::setEngine2(bool arg)
{
isEngine2 = arg;
if (arg) {
qDebug() << "Player2 is computer.";
// ai2.start();
}
else {
qDebug() << "Player2 is not computer.";
ai2.stop();
}
}
void GameController::setAnimation(bool arg)
@ -279,9 +276,11 @@ void GameController::timerEvent(QTimerEvent *event)
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放音效
playSound(":/sound/Resources/sound/win.wav");
playSound(":/sound/resources/sound/win.wav");
}
/*
// 测试用代码
/*
int ti = time.elapsed();
static QTime t;
if (ti < 0)
@ -305,7 +304,7 @@ void GameController::timerEvent(QTimerEvent *event)
*/
}
bool GameController::command(QString &cmd, bool update /*= true*/)
bool GameController::command(const QString &cmd, bool update /*= true*/)
{
if (chess.command(cmd.toStdString().c_str())) {
if (chess.getPhase() == NineChess::GAME_NOTSTARTED) {
@ -379,6 +378,14 @@ bool GameController::actionPiece(QPointF pos)
{
chess = chessTemp;
manualListModel.removeRows(currentRow + 1, manualListModel.rowCount() - currentRow - 1);
// 如果再决出胜负后悔棋,则重新启动计时
if (chess.whoWin() == NineChess::NOBODY) {
// 重新启动计时
timeID = startTimer(100);
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
}
}
else
{
@ -414,8 +421,6 @@ bool GameController::actionPiece(QPointF pos)
else if (chess.getAction() == NineChess::ACTION_PLACE) {
// 如果移子不成功,尝试重新选子
result = movePiece(pos);
if (!result)
result = choosePiece(pos);
}// 去子
else if (chess.getAction() == NineChess::ACTION_REMOVE) {
result = removePiece(pos);
@ -442,7 +447,7 @@ bool GameController::actionPiece(QPointF pos)
}
if (chess.whoWin() != NineChess::NOBODY &&
(manualListModel.data(manualListModel.index(currentRow-1))).toString().contains("Time over."))
playSound(":/sound/Resources/sound/win.wav");
playSound(":/sound/resources/sound/win.wav");
}
updateScence();
@ -467,12 +472,12 @@ bool GameController::choosePiece(QPointF pos)
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放选子音效
playSound(":/sound/Resources/sound/choose.wav");
playSound(":/sound/resources/sound/choose.wav");
return true;
}
else {
// 播放禁止音效
playSound(":/sound/Resources/sound/forbidden.wav");
playSound(":/sound/resources/sound/forbidden.wav");
return false;
}
}
@ -486,14 +491,14 @@ bool GameController::placePiece(QPointF pos)
}
if (!chess.place(c, p)) {
// 播放禁止音效
playSound(":/sound/Resources/sound/forbidden.wav");
playSound(":/sound/resources/sound/forbidden.wav");
return false;
}
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放音效
playSound(":/sound/Resources/sound/drog.wav");
playSound(":/sound/resources/sound/drog.wav");
return true;
}
@ -514,12 +519,14 @@ bool GameController::movePiece(QPointF pos)
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放音效
playSound(":/sound/Resources/sound/move.wav");
playSound(":/sound/resources/sound/move.wav");
return true;
}
// 播放禁止音效
playSound(":/sound/Resources/sound/forbidden.wav");
return false;
// 如果移子不成功,尝试重新选子
else
{
return choosePiece(pos);
}
}
// 去子
@ -531,7 +538,7 @@ bool GameController::removePiece(QPointF pos)
}
if (!chess.remove(c, p)) {
// 播放禁止音效
playSound(":/sound/Resources/sound/forbidden.wav");
playSound(":/sound/resources/sound/forbidden.wav");
return false;
}
@ -539,7 +546,7 @@ bool GameController::removePiece(QPointF pos)
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放音效
playSound(":/sound/Resources/sound/remove.wav");
playSound(":/sound/resources/sound/remove.wav");
return true;
}
@ -564,7 +571,7 @@ bool GameController::giveUp()
manualListModel.setData(manualListModel.index(currentRow), (*i).c_str());
}
if (chess.whoWin() != NineChess::NOBODY)
playSound(":/sound/Resources/sound/loss.wav");
playSound(":/sound/resources/sound/loss.wav");
}
return result;
}

View File

@ -72,7 +72,7 @@ public slots:
// 认输
bool giveUp();
// 棋谱的命令行执行
bool command(QString &cmd, bool update = true);
bool command(const QString &cmd, bool update = true);
// 历史局面及局面改变
bool phaseChange(int row);
// 更新棋局显示,每步后必须执行

View File

@ -27,24 +27,27 @@ GameScene::~GameScene()
delete board;
}
// 屏蔽掉Shift和Control按键事实证明没用按键事件未必由视图类处理
/*
void GameScene::keyPressEvent(QKeyEvent *keyEvent)
{
// 屏蔽掉Shift和Control按键事实证明没用按键事件未必由视图类处理
if(keyEvent->key() == Qt::Key_Shift || keyEvent->key() == Qt::Key_Control)
return;
QGraphicsScene::keyPressEvent(keyEvent);
}
*/
void GameScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
//什么也不做,屏蔽双击事件
Q_UNUSED(mouseEvent)
//屏蔽双击事件
mouseEvent->accept();
}
void GameScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
//什么也不做,屏蔽鼠标按下事件
Q_UNUSED(mouseEvent)
//屏蔽鼠标按下事件
mouseEvent->accept();
/*
// 只处理左键事件
if(mouseEvent->button() != Qt::LeftButton)
@ -64,8 +67,10 @@ void GameScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
void GameScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
// 只处理左键事件
if(mouseEvent->button() != Qt::LeftButton)
if (mouseEvent->button() != Qt::LeftButton) {
mouseEvent->accept();
return;
}
// 如果是棋盘
QGraphicsItem *item = itemAt(mouseEvent->scenePos(), QTransform());
@ -83,6 +88,8 @@ void GameScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
emit mouseReleased(item->scenePos());
}
mouseEvent->accept();
// 调用默认事件处理函数
//QGraphicsScene::mouseReleaseEvent(mouseEvent);
}

View File

@ -23,7 +23,7 @@ public:
const QPointF pos_p2, pos_p2_g;
protected:
void keyPressEvent(QKeyEvent *keyEvent);
//void keyPressEvent(QKeyEvent *keyEvent);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);

View File

@ -7,18 +7,20 @@
*
*/
#ifndef SIZEHINTLISTVIEW
#define SIZEHINTLISTVIEW
#ifndef MANUALLISTVIEW
#define MANUALLISTVIEW
#include <QListView>
#include <QDebug>
class SizeHintListView : public QListView
class ManualListView : public QListView
{
Q_OBJECT
public:
SizeHintListView(QWidget * parent = nullptr) { Q_UNUSED(parent) }
ManualListView(QWidget * parent = nullptr) : QListView (parent) {
Q_UNUSED(parent)
}
QSize sizeHint() const {
QSize size = QListView::sizeHint();
// 缺省宽度设为128这样就不太宽了
@ -50,11 +52,16 @@ protected slots:
// 采用判断最后一个元素是否改变来选中之
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
const QVector<int> &roles = QVector<int>()) {
QAbstractItemView::dataChanged(topLeft, bottomRight, roles);
QModelIndex index = model()->index(model()->rowCount() - 1, 0);
if (index == bottomRight) {
setCurrentIndex(index);
scrollToBottom();
// 调用父类默认函数
QListView::dataChanged(topLeft, bottomRight, roles);
// 如果包含model
if (model()) {
// 判断
QModelIndex index = model()->index(model()->rowCount() - 1, 0);
if (index == bottomRight) {
setCurrentIndex(index);
scrollToBottom();
}
}
}
@ -66,5 +73,4 @@ protected slots:
}
};
#endif // SIZEHINTLISTVIEW
#endif // MANUALLISTVIEW

View File

@ -130,44 +130,44 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla
this->rule.maxSteps = s;
this->rule.maxTime = t;
// 设置步数
this->step = step;
data_.step = step;
// 设置状态
// 局面阶段标识
if (flags & GAME_NOTSTARTED)
phase = GAME_NOTSTARTED;
data_.phase = GAME_NOTSTARTED;
else if (flags & GAME_OPENING)
phase = GAME_OPENING;
data_.phase = GAME_OPENING;
else if (flags & GAME_MID)
phase = GAME_MID;
data_.phase = GAME_MID;
else if (flags & GAME_OVER)
phase = GAME_OVER;
data_.phase = GAME_OVER;
else
return false;
// 轮流状态标识
if (flags & PLAYER1)
turn = PLAYER1;
data_.turn = PLAYER1;
else if (flags & PLAYER2)
turn = PLAYER2;
data_.turn = PLAYER2;
else
return false;
// 动作状态标识
if (flags & ACTION_CHOOSE)
action = ACTION_CHOOSE;
data_.action = ACTION_CHOOSE;
else if (flags & ACTION_PLACE)
action = ACTION_PLACE;
data_.action = ACTION_PLACE;
else if (flags & ACTION_REMOVE)
action = ACTION_REMOVE;
data_.action = ACTION_REMOVE;
else
return false;
// 胜负标识
winner = NOBODY;
data_.winner = NOBODY;
// 当前棋局3×8
if (boardsource == nullptr)
memset(this->board, 0, sizeof(this->board));
memset(data_.board, 0, sizeof(data_.board));
else
memcpy(this->board, boardsource, sizeof(this->board));
memcpy(data_.board, boardsource, sizeof(data_.board));
// 生成招法表
for (int i = 1; i <= RING; i++)
{
@ -257,38 +257,38 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla
}
// 计算盘面子数
player1_Remain = player2_Remain = 0;
data_.player1_Remain = data_.player2_Remain = 0;
for (int i = 1; i < RING + 2; i++)
{
for (int j = 0; j < SEAT; j++)
{
if (board[i*SEAT + j] & '\x10')
player1_Remain++;
else if (board[i*SEAT + j] & '\x20') {
player2_Remain++;
if (data_.board[i*SEAT + j] & '\x10')
data_.player1_Remain++;
else if (data_.board[i*SEAT + j] & '\x20') {
data_.player2_Remain++;
}
}
}
// 设置玩家盘面剩余子数和未放置子数
if (player1_Remain > rule->numOfChess || player2_Remain > rule->numOfChess)
if (data_.player1_Remain > rule->numOfChess || data_.player2_Remain > rule->numOfChess)
return false;
if (p1_InHand < 0 || p2_InHand < 0)
return false;
player1_InHand = rule->numOfChess - player1_Remain;
player2_InHand = rule->numOfChess - player2_Remain;
player1_InHand = p1_InHand < player1_InHand ? p1_InHand : player1_InHand;
player2_InHand = p2_InHand < player2_InHand ? p2_InHand : player2_InHand;
data_.player1_InHand = rule->numOfChess - data_.player1_Remain;
data_.player2_InHand = rule->numOfChess - data_.player2_Remain;
data_.player1_InHand = p1_InHand < data_.player1_InHand ? p1_InHand : data_.player1_InHand;
data_.player2_InHand = p2_InHand < data_.player2_InHand ? p2_InHand : data_.player2_InHand;
// 设置去子状态时的剩余尚待去除子数
if (flags & ACTION_REMOVE) {
if (num_NeedRemove >= 0 && num_NeedRemove < 3)
this->num_NeedRemove = num_NeedRemove;
data_.num_NeedRemove = num_NeedRemove;
}
else
this->num_NeedRemove = 0;
data_.num_NeedRemove = 0;
// 清空成三记录
millList.clear();
data_.millList.clear();
// 不选中棋子
currentPos = 0;
@ -322,53 +322,53 @@ void NineChess::getData(struct Rule &rule, int &step, int &chess, const char *&b
int &p1_InHand, int &p2_InHand, int &num_NeedRemove)
{
rule = this->rule;
step = this->step;
chess = phase | turn | action | winner;
board = this->board;
p1_InHand = player1_InHand;
p2_InHand = player2_InHand;
num_NeedRemove = this->num_NeedRemove;
step = data_.step;
chess = data_.phase | data_.turn | data_.action | data_.winner;
board = data_.board;
p1_InHand = data_.player1_InHand;
p2_InHand = data_.player2_InHand;
num_NeedRemove = data_.num_NeedRemove;
}
const char * NineChess::getBoard()
{
return board;
return data_.board;
}
bool NineChess::reset()
{
if (phase == GAME_NOTSTARTED && player1_MS == player2_MS == 0)
if (data_.phase == GAME_NOTSTARTED && player1_MS == player2_MS == 0)
return true;
// 步数归零
step = 0;
data_.step = 0;
// 局面阶段标识
phase = GAME_NOTSTARTED;
data_.phase = GAME_NOTSTARTED;
// 轮流状态标识
turn = PLAYER1;
data_.turn = PLAYER1;
// 动作状态标识
action = ACTION_PLACE;
data_.action = ACTION_PLACE;
// 胜负标识
winner = NOBODY;
data_.winner = NOBODY;
// 当前棋局3×8
memset(board, 0, sizeof(board));
memset(data_.board, 0, sizeof(data_.board));
// 盘面子数归零
player1_Remain = player2_Remain = 0;
data_.player1_Remain = data_.player2_Remain = 0;
// 设置玩家盘面剩余子数和未放置子数
player1_InHand = player2_InHand = rule.numOfChess;
data_.player1_InHand = data_.player2_InHand = rule.numOfChess;
// 设置去子状态时的剩余尚待去除子数
num_NeedRemove = 0;
data_.num_NeedRemove = 0;
// 清空成三记录
millList.clear();
data_.millList.clear();
// 不选中棋子
currentPos = 0;
@ -401,16 +401,16 @@ bool NineChess::reset()
bool NineChess::start()
{
// 如果游戏已经开始则返回false
if (phase == GAME_OPENING || phase == GAME_MID)
if (data_.phase == GAME_OPENING || data_.phase == GAME_MID)
return false;
// 如果游戏结束,则重置游戏,进入未开始状态
if (phase == GAME_OVER)
if (data_.phase == GAME_OVER)
reset();
// 如果游戏处于未开始状态
if (phase == GAME_NOTSTARTED) {
phase = GAME_OPENING;
if (data_.phase == GAME_NOTSTARTED) {
data_.phase = GAME_OPENING;
// 启动计时器
ftime(&startTimeb);
}
@ -429,18 +429,18 @@ int NineChess::cp2pos(int c, int p)
bool NineChess::place(int c, int p, long time_p /* = -1*/)
{
// 如果局面为“结局”返回false
if (phase == GAME_OVER)
if (data_.phase == GAME_OVER)
return false;
// 如果局面为“未开局”,则开具
if (phase == GAME_NOTSTARTED)
if (data_.phase == GAME_NOTSTARTED)
start();
// 如非“落子”状态返回false
if (action != ACTION_PLACE)
if (data_.action != ACTION_PLACE)
return false;
// 如果落子位置在棋盘外、已有子点或禁点返回false
int pos = cp2pos(c, p);
if (!inBoard[pos] || board[pos])
if (!inBoard[pos] || data_.board[pos])
return false;
// 时间的临时变量
long player_ms = -1;
@ -448,28 +448,29 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
// 对于开局落子
char piece = '\x00';
int n = 0;
if (phase == GAME_OPENING) {
if (data_.phase == GAME_OPENING) {
// 先手下
if (turn == PLAYER1)
if (data_.turn == PLAYER1)
{
piece = '\x11' + rule.numOfChess - player1_InHand;
board[pos] = piece;
player1_InHand--;
player1_Remain++;
piece = '\x11' + rule.numOfChess - data_.player1_InHand;
data_.board[pos] = piece;
data_.player1_InHand--;
data_.player1_Remain++;
}
// 后手下
else
{
piece = '\x21' + rule.numOfChess - player2_InHand;
board[pos] = piece;
player2_InHand--;
player2_Remain++;
piece = '\x21' + rule.numOfChess - data_.player2_InHand;
data_.board[pos] = piece;
data_.player2_InHand--;
data_.player2_Remain++;
}
player_ms = update(time_p);
data_.move_ = pos;
sprintf(cmdline, "(%1u,%1u) %02u:%02u.%03u", c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000);
cmdlist.push_back(string(cmdline));
currentPos = pos;
step++;
data_.step++;
// 如果决出胜负
if (win()) {
setTip();
@ -480,19 +481,19 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
// 开局阶段未成三
if (n == 0) {
// 如果双方都无未放置的棋子
if (player1_InHand == 0 && player2_InHand == 0) {
if (data_.player1_InHand == 0 && data_.player2_InHand == 0) {
// 进入中局阶段
phase = GAME_MID;
data_.phase = GAME_MID;
// 进入选子状态
action = ACTION_CHOOSE;
data_.action = ACTION_CHOOSE;
// 清除禁点
cleanForbidden();
// 设置轮到谁走
if (rule.isDefensiveMoveFirst) {
turn = PLAYER2;
data_.turn = PLAYER2;
}
else {
turn = PLAYER1;
data_.turn = PLAYER1;
}
// 再决胜负
if (win()) {
@ -509,19 +510,19 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
// 如果成三
else {
// 设置去子数目
num_NeedRemove = rule.removeMore ? n : 1;
data_.num_NeedRemove = rule.removeMore ? n : 1;
// 进入去子状态
action = ACTION_REMOVE;
data_.action = ACTION_REMOVE;
}
setTip();
return true;
}
// 对于中局落子
else if (phase == GAME_MID) {
else if (data_.phase == GAME_MID) {
// 如果落子不合法
if ((turn == PLAYER1 && (player1_Remain > rule.numAtLest || !rule.canFly)) ||
(turn == PLAYER2 && (player2_Remain > rule.numAtLest || !rule.canFly))) {
if ((data_.turn == PLAYER1 && (data_.player1_Remain > rule.numAtLest || !rule.canFly)) ||
(data_.turn == PLAYER2 && (data_.player2_Remain > rule.numAtLest || !rule.canFly))) {
int i;
for (i = 0; i < 4; i++) {
if (pos == moveTable[currentPos][i])
@ -533,19 +534,20 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
}
// 移子
player_ms = update(time_p);
data_.move_ = (currentPos << 8) | pos;
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u.%03u", currentPos / SEAT, currentPos % SEAT + 1,
c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000);
cmdlist.push_back(string(cmdline));
board[pos] = board[currentPos];
board[currentPos] = '\x00';
data_.board[pos] = data_.board[currentPos];
data_.board[currentPos] = '\x00';
currentPos = pos;
step++;
data_.step++;
n = addMills(currentPos);
// 中局阶段未成三
if (n == 0) {
// 进入选子状态
action = ACTION_CHOOSE;
data_.action = ACTION_CHOOSE;
// 设置轮到谁走
changeTurn();
// 如果决出胜负
@ -557,9 +559,9 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
// 中局阶段成三
else {
// 设置去子数目
num_NeedRemove = rule.removeMore ? n : 1;
data_.num_NeedRemove = rule.removeMore ? n : 1;
// 进入去子状态
action = ACTION_REMOVE;
data_.action = ACTION_REMOVE;
setTip();
}
setTip();
@ -572,20 +574,20 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
bool NineChess::remove(int c, int p, long time_p /* = -1*/)
{
// 如果局面为"未开局"或“结局”返回false
if (phase == GAME_NOTSTARTED || phase == GAME_OVER)
if (data_.phase == GAME_NOTSTARTED || data_.phase == GAME_OVER)
return false;
// 如非“去子”状态返回false
if (action != ACTION_REMOVE)
if (data_.action != ACTION_REMOVE)
return false;
// 如果去子完成返回false
if (num_NeedRemove <= 0)
if (data_.num_NeedRemove <= 0)
return false;
// 时间的临时变量
long player_ms = -1;
int pos = cp2pos(c, p);
// 对手
enum Player opponent = PLAYER2;
if (turn == PLAYER2)
if (data_.turn == PLAYER2)
opponent = PLAYER1;
// 判断去子不是对手棋
if (getWhosPiece(c, p) != opponent)
@ -597,20 +599,21 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/)
}
// 去子(设置禁点)
if (rule.hasForbidden && phase == GAME_OPENING)
board[pos] = '\x0f';
if (rule.hasForbidden && data_.phase == GAME_OPENING)
data_.board[pos] = '\x0f';
else // 去子
board[pos] = '\x00';
if (turn == PLAYER1)
player2_Remain--;
else if (turn == PLAYER2)
player1_Remain--;
data_.board[pos] = '\x00';
if (data_.turn == PLAYER1)
data_.player2_Remain--;
else if (data_.turn == PLAYER2)
data_.player1_Remain--;
player_ms = update(time_p);
data_.move_ = 0xFF00 | pos;
sprintf(cmdline, "-(%1u,%1u) %02u:%02u.%03u", c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000);
cmdlist.push_back(string(cmdline));
currentPos = 0;
num_NeedRemove--;
step++;
data_.num_NeedRemove--;
data_.step++;
// 去子完成
// 如果决出胜负
@ -619,28 +622,28 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/)
return true;
}
// 还有其余的子要去吗
if (num_NeedRemove > 0) {
if (data_.num_NeedRemove > 0) {
// 继续去子
return true;
}
// 所有去子都完成了
else {
// 开局阶段
if (phase == GAME_OPENING) {
if (data_.phase == GAME_OPENING) {
// 如果双方都无未放置的棋子
if (player1_InHand == 0 && player2_InHand == 0) {
if (data_.player1_InHand == 0 && data_.player2_InHand == 0) {
// 进入中局阶段
phase = GAME_MID;
data_.phase = GAME_MID;
// 进入选子状态
action = ACTION_CHOOSE;
data_.action = ACTION_CHOOSE;
// 清除禁点
cleanForbidden();
// 设置轮到谁走
if (rule.isDefensiveMoveFirst) {
turn = PLAYER2;
data_.turn = PLAYER2;
}
else {
turn = PLAYER1;
data_.turn = PLAYER1;
}
// 再决胜负
if (win()) {
@ -651,7 +654,7 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/)
// 如果双方还有子
else {
// 进入落子状态
action = ACTION_PLACE;
data_.action = ACTION_PLACE;
// 设置轮到谁走
changeTurn();
// 如果决出胜负
@ -664,7 +667,7 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/)
// 中局阶段
else {
// 进入选子状态
action = ACTION_CHOOSE;
data_.action = ACTION_CHOOSE;
// 设置轮到谁走
changeTurn();
// 如果决出胜负
@ -681,20 +684,20 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/)
bool NineChess::choose(int c, int p)
{
// 如果局面不是"中局”返回false
if (phase != GAME_MID)
if (data_.phase != GAME_MID)
return false;
// 如非“选子”或“落子”状态返回false
if (action != ACTION_CHOOSE && action != ACTION_PLACE)
if (data_.action != ACTION_CHOOSE && data_.action != ACTION_PLACE)
return false;
int pos = cp2pos(c, p);
// 根据先后手,判断可选子
char t ='\0';
if (turn == PLAYER1)
if (data_.turn == PLAYER1)
t = '\x10';
else if (turn == PLAYER2)
else if (data_.turn == PLAYER2)
t = '\x20';
// 判断选子是否可选
if (board[pos] & t) {
if (data_.board[pos] & t) {
// 判断pos处的棋子是否被“闷”
if (isSurrounded(pos)) {
return false;
@ -702,7 +705,7 @@ bool NineChess::choose(int c, int p)
// 选子
currentPos = pos;
// 选子完成,进入落子状态
action = ACTION_PLACE;
data_.action = ACTION_PLACE;
return true;
}
return false;
@ -710,12 +713,12 @@ bool NineChess::choose(int c, int p)
bool NineChess::giveup(Player loser)
{
if (phase == GAME_MID || phase == GAME_OPENING)
if (data_.phase == GAME_MID || data_.phase == GAME_OPENING)
{
if (loser == PLAYER1)
{
phase = GAME_OVER;
winner = PLAYER2;
data_.phase = GAME_OVER;
data_.winner = PLAYER2;
tip = "玩家1投子认负恭喜玩家2获胜";
sprintf(cmdline, "Player1 give up!");
cmdlist.push_back(string(cmdline));
@ -723,8 +726,8 @@ bool NineChess::giveup(Player loser)
}
else if (loser == PLAYER2)
{
phase = GAME_OVER;
winner = PLAYER1;
data_.phase = GAME_OVER;
data_.winner = PLAYER1;
tip = "玩家2投子认负恭喜玩家1获胜";
sprintf(cmdline, "Player2 give up!");
cmdlist.push_back(string(cmdline));
@ -801,11 +804,11 @@ bool NineChess::command(const char *cmd)
inline long NineChess::update(long time_p /*= -1*/)
{
long ret = -1;
long *player_ms = (turn == PLAYER1 ? &player1_MS : &player2_MS);
long playerNext_ms = (turn == PLAYER1 ? player2_MS : player1_MS);
long *player_ms = (data_.turn == PLAYER1 ? &(player1_MS) : &(player2_MS));
long playerNext_ms = (data_.turn == PLAYER1 ? player2_MS : player1_MS);
// 根据局面调整计时器
switch (phase)
switch (data_.phase)
{
case NineChess::GAME_OPENING:
case NineChess::GAME_MID:
@ -847,9 +850,9 @@ inline long NineChess::update(long time_p /*= -1*/)
// 是否分出胜负
bool NineChess::win()
{
if (phase == GAME_OVER)
if (data_.phase == GAME_OVER)
return true;
if (phase == GAME_NOTSTARTED)
if (data_.phase == GAME_NOTSTARTED)
return false;
// 如果有时间限定
@ -858,8 +861,8 @@ bool NineChess::win()
// 如果玩家1超时
if (player1_MS > rule.maxTime * 60000) {
player1_MS = rule.maxTime * 60000;
winner = PLAYER2;
phase = GAME_OVER;
data_.winner = PLAYER2;
data_.phase = GAME_OVER;
tip = "玩家1超时恭喜玩家2获胜";
sprintf(cmdline, "Time over. Player2 win!");
cmdlist.push_back(string(cmdline));
@ -868,8 +871,8 @@ bool NineChess::win()
// 如果玩家2超时
else if (player2_MS > rule.maxTime * 60000) {
player2_MS = rule.maxTime * 60000;
winner = PLAYER1;
phase = GAME_OVER;
data_.winner = PLAYER1;
data_.phase = GAME_OVER;
tip = "玩家2超时恭喜玩家1获胜";
sprintf(cmdline, "Time over. Player1 win!");
cmdlist.push_back(string(cmdline));
@ -879,9 +882,9 @@ bool NineChess::win()
// 如果有步数限定
if (rule.maxSteps > 0) {
if (step > rule.maxSteps) {
winner = DRAW;
phase = GAME_OVER;
if (data_.step > rule.maxSteps) {
data_.winner = DRAW;
data_.phase = GAME_OVER;
sprintf(cmdline, "Steps over. In draw!");
cmdlist.push_back(string(cmdline));
return true;
@ -889,48 +892,48 @@ bool NineChess::win()
}
// 如果玩家1子数小于赛点则玩家2获胜
if (player1_Remain + player1_InHand < rule.numAtLest) {
winner = PLAYER2;
phase = GAME_OVER;
if (data_.player1_Remain + data_.player1_InHand < rule.numAtLest) {
data_.winner = PLAYER2;
data_.phase = GAME_OVER;
sprintf(cmdline, "Player2 win!");
cmdlist.push_back(string(cmdline));
return true;
}
// 如果玩家2子数小于赛点则玩家1获胜
else if (player2_Remain + player2_InHand < rule.numAtLest) {
winner = PLAYER1;
phase = GAME_OVER;
else if (data_.player2_Remain + data_.player2_InHand < rule.numAtLest) {
data_.winner = PLAYER1;
data_.phase = GAME_OVER;
sprintf(cmdline, "Player1 win!");
cmdlist.push_back(string(cmdline));
return true;
}
// 如果摆满了,根据规则判断胜负
else if (player1_Remain + player2_Remain >= SEAT * RING) {
else if (data_.player1_Remain + data_.player2_Remain >= SEAT * RING) {
if (rule.isFullLose) {
winner = PLAYER2;
phase = GAME_OVER;
data_.winner = PLAYER2;
data_.phase = GAME_OVER;
sprintf(cmdline, "Player2 win!");
cmdlist.push_back(string(cmdline));
return true;
}
else
{
winner = DRAW;
phase = GAME_OVER;
data_.winner = DRAW;
data_.phase = GAME_OVER;
sprintf(cmdline, "Full. In draw!");
cmdlist.push_back(string(cmdline));
return true;
}
}
// 如果中局被“闷”
else if (phase == GAME_MID && action == ACTION_CHOOSE && isAllSurrounded(turn)) {
else if (data_.phase == GAME_MID && data_.action == ACTION_CHOOSE && isAllSurrounded(data_.turn)) {
// 规则要求被“闷”判负,则对手获胜
if (rule.isNoWayLose) {
if (turn == PLAYER1)
if (data_.turn == PLAYER1)
{
tip = "玩家1无子可走恭喜玩家2获胜";
winner = PLAYER2;
phase = GAME_OVER;
data_.winner = PLAYER2;
data_.phase = GAME_OVER;
sprintf(cmdline, "Player1 no way to go. Player2 win!");
cmdlist.push_back(string(cmdline));
return true;
@ -938,8 +941,8 @@ bool NineChess::win()
else
{
tip = "玩家2无子可走恭喜玩家1获胜";
winner = PLAYER1;
phase = GAME_OVER;
data_.winner = PLAYER1;
data_.phase = GAME_OVER;
sprintf(cmdline, "Player2 no way to go. Player1 win!");
cmdlist.push_back(string(cmdline));
return true;
@ -960,12 +963,12 @@ int NineChess::isInMills(int pos)
{
int n = 0;
int pos1, pos2;
char m = board[pos] & '\x30';
char m = data_.board[pos] & '\x30';
for (int i = 0; i < 3; i++)
{
pos1 = millTable[pos][i][0];
pos2 = millTable[pos][i][1];
if (m & board[pos1] & board[pos2])
if (m & data_.board[pos1] & data_.board[pos2])
n++;
}
return n;
@ -980,14 +983,14 @@ int NineChess::addMills(int pos)
long long mill = 0;
int n = 0;
int p[3], min, temp;
char m = board[pos] & '\x30';
char m = data_.board[pos] & '\x30';
for (int i = 0; i < 3; i++)
{
p[0] = pos;
p[1] = millTable[pos][i][0];
p[2] = millTable[pos][i][1];
// 如果成三
if (m & board[p[1]] & board[p[2]]) {
if (m & data_.board[p[1]] & data_.board[p[2]]) {
// 排序
for (int j = 0; j < 2; j++) {
min = j;
@ -1002,11 +1005,11 @@ int NineChess::addMills(int pos)
}
}
// 成三
mill = (((long long)board[p[0]]) << 40)
mill = (((long long)(data_.board[p[0]])) << 40)
+ (((long long)p[0]) << 32)
+ (((long long)board[p[1]]) << 24)
+ (((long long)(data_.board[p[1]])) << 24)
+ (((long long)p[1]) << 16)
+ (((long long)board[p[2]]) << 8)
+ (((long long)(data_.board[p[2]])) << 8)
+ (long long)p[2];
// 如果允许相同三连反复去子
@ -1019,15 +1022,15 @@ int NineChess::addMills(int pos)
// 迭代器
list<long long>::iterator itor;
// 遍历
for (itor = millList.begin(); itor != millList.end(); itor++)
for (itor = data_.millList.begin(); itor != data_.millList.end(); itor++)
{
if (mill == *itor)
break;
}
// 如果没找到历史项
if (itor == millList.end()) {
if (itor == data_.millList.end()) {
n++;
millList.push_back(mill);
data_.millList.push_back(mill);
}
}
}
@ -1047,7 +1050,7 @@ bool NineChess::isAllInMills(enum Player player)
for (int i = 1; i <= RING; i++)
for (int j = 0; j < SEAT; j++) {
if (board[i*SEAT + j] & ch) {
if (data_.board[i*SEAT + j] & ch) {
if (!isInMills(i*SEAT + j)) {
return false;
}
@ -1060,13 +1063,13 @@ bool NineChess::isAllInMills(enum Player player)
bool NineChess::isSurrounded(int pos)
{
// 判断pos处的棋子是否被“闷”
if ((turn == PLAYER1 && (player1_Remain > rule.numAtLest || !rule.canFly)) ||
(turn == PLAYER2 && (player2_Remain > rule.numAtLest || !rule.canFly)))
if ((data_.turn == PLAYER1 && (data_.player1_Remain > rule.numAtLest || !rule.canFly)) ||
(data_.turn == PLAYER2 && (data_.player2_Remain > rule.numAtLest || !rule.canFly)))
{
int i, movePos;
for (i = 0; i < 4; i++) {
movePos = moveTable[pos][i];
if (movePos && !board[movePos])
if (movePos && !data_.board[movePos])
break;
}
// 被围住
@ -1086,11 +1089,11 @@ bool NineChess::isAllSurrounded(enum Player ply)
else if (ply == PLAYER2)
t &= '\x20';
// 如果摆满
if (player1_Remain + player2_Remain >= SEAT * RING)
if (data_.player1_Remain + data_.player2_Remain >= SEAT * RING)
return true;
// 判断是否可以飞子
if ((turn == PLAYER1 && (player1_Remain <= rule.numAtLest && rule.canFly)) ||
(turn == PLAYER2 && (player2_Remain <= rule.numAtLest && rule.canFly)))
if ((data_.turn == PLAYER1 && (data_.player1_Remain <= rule.numAtLest && rule.canFly)) ||
(data_.turn == PLAYER2 && (data_.player2_Remain <= rule.numAtLest && rule.canFly)))
{
return false;
}
@ -1100,10 +1103,10 @@ bool NineChess::isAllSurrounded(enum Player ply)
for (int j = 0; j < SEAT; j++)
{
int movePos;
if (t & board[i*SEAT + j]) {
if (t & data_.board[i*SEAT + j]) {
for (int k = 0; k < 4; k++) {
movePos = moveTable[i*SEAT + j][k];
if (movePos && !board[movePos])
if (movePos && !data_.board[movePos])
return false;
}
}
@ -1116,70 +1119,70 @@ void NineChess::cleanForbidden()
{
for (int i = 1; i <= RING; i++)
for (int j = 0; j < SEAT; j++) {
if (board[i*SEAT + j] == '\x0f')
board[i*SEAT + j] = '\x00';
if (data_.board[i*SEAT + j] == '\x0f')
data_.board[i*SEAT + j] = '\x00';
}
}
enum NineChess::Player NineChess::changeTurn()
{
// 设置轮到谁走
return turn = (turn == PLAYER1) ? PLAYER2 : PLAYER1;
return data_.turn = (data_.turn == PLAYER1) ? PLAYER2 : PLAYER1;
}
void NineChess::setTip()
{
switch (phase)
switch (data_.phase)
{
case NineChess::GAME_NOTSTARTED:
tip = "轮到玩家1落子剩余" + std::to_string(player1_InHand) + "";
tip = "轮到玩家1落子剩余" + std::to_string(data_.player1_InHand) + "";
break;
case NineChess::GAME_OPENING:
if (action == ACTION_PLACE) {
if (turn == PLAYER1) {
tip = "轮到玩家1落子剩余" + std::to_string(player1_InHand) + "";
if (data_.action == ACTION_PLACE) {
if (data_.turn == PLAYER1) {
tip = "轮到玩家1落子剩余" + std::to_string(data_.player1_InHand) + "";
}
else if (turn == PLAYER2) {
tip = "轮到玩家2落子剩余" + std::to_string(player2_InHand) + "";
else if (data_.turn == PLAYER2) {
tip = "轮到玩家2落子剩余" + std::to_string(data_.player2_InHand) + "";
}
}
else if (action == ACTION_REMOVE) {
if (turn == PLAYER1) {
tip = "轮到玩家1去子需去" + std::to_string(num_NeedRemove) + "";
else if (data_.action == ACTION_REMOVE) {
if (data_.turn == PLAYER1) {
tip = "轮到玩家1去子需去" + std::to_string(data_.num_NeedRemove) + "";
}
else if (turn == PLAYER2) {
tip = "轮到玩家2去子需去" + std::to_string(num_NeedRemove) + "";
else if (data_.turn == PLAYER2) {
tip = "轮到玩家2去子需去" + std::to_string(data_.num_NeedRemove) + "";
}
}
break;
case NineChess::GAME_MID:
if (action == ACTION_PLACE || action == ACTION_CHOOSE) {
if (turn == PLAYER1) {
if (data_.action == ACTION_PLACE || data_.action == ACTION_CHOOSE) {
if (data_.turn == PLAYER1) {
tip = "轮到玩家1选子移动";
}
else if (turn == PLAYER2) {
else if (data_.turn == PLAYER2) {
tip = "轮到玩家2选子移动";
}
}
else if (action == ACTION_REMOVE) {
if (turn == PLAYER1) {
tip = "轮到玩家1去子需去" + std::to_string(num_NeedRemove) + "";
else if (data_.action == ACTION_REMOVE) {
if (data_.turn == PLAYER1) {
tip = "轮到玩家1去子需去" + std::to_string(data_.num_NeedRemove) + "";
}
else if (turn == PLAYER2) {
tip = "轮到玩家2去子需去" + std::to_string(num_NeedRemove) + "";
else if (data_.turn == PLAYER2) {
tip = "轮到玩家2去子需去" + std::to_string(data_.num_NeedRemove) + "";
}
}
break;
case NineChess::GAME_OVER:
if (winner == DRAW)
if (data_.winner == DRAW)
tip = "超出限定步数,双方平局";
else if (winner == PLAYER1) {
else if (data_.winner == PLAYER1) {
if (tip.find("无子可走") != tip.npos)
tip += "恭喜玩家1获胜";
else
tip = "恭喜玩家1获胜";
}
else if (winner == PLAYER2) {
else if (data_.winner == PLAYER2) {
if (tip.find("无子可走") != tip.npos)
tip += "恭喜玩家2获胜";
else
@ -1194,9 +1197,9 @@ void NineChess::setTip()
enum NineChess::Player NineChess::getWhosPiece(int c, int p)
{
int pos = cp2pos(c, p);
if (board[pos] & '\x10')
if (data_.board[pos] & '\x10')
return PLAYER1;
else if (board[pos] & '\x20')
else if (data_.board[pos] & '\x20')
return PLAYER2;
return NOBODY;
}
@ -1204,7 +1207,7 @@ enum NineChess::Player NineChess::getWhosPiece(int c, int p)
int NineChess::getPieceNum(int c, int p)
{
int pos = cp2pos(c, p);
int n = 0x0f & board[pos];
int n = 0x0f & data_.board[pos];
return n;
}

View File

@ -16,11 +16,12 @@ using std::string;
using std::list;
// 棋类(在数据模型内,玩家只分先后手,不分黑白)
// 注意NineChess类不是线程安全的
// 所以不能跨线程修改NineChess类的静态成员变量切记
class NineChess
{
public:
// 公有的结构体和枚举,只是类型定义,不是变量!
// 规则结构体
// 嵌套的规则结构体
struct Rule
{
// 规则名称
@ -86,9 +87,89 @@ public:
// 预定义的规则
static const struct Rule RULES[RULENUM];
// 嵌套的数据结构体
// 单独提出来是为了ai计算的时候压栈的数据量少
struct Data
{
// 当前步数
int step;
// 局面阶段标识
enum Phases phase;
// 轮流状态标识
enum Player turn;
// 动作状态标识
enum Actions action;
// 赢家
enum Player winner;
// 玩家1剩余未放置子数
int player1_InHand;
// 玩家2剩余未放置子数
int player2_InHand;
// 玩家1盘面剩余子数
int player1_Remain;
// 玩家1盘面剩余子数
int player2_Remain;
// 尚待去除的子数
int num_NeedRemove;
/* 棋局抽象为一个5×8的char数组上下两行留空
* 0x00
* 0x0F
* 0x110x1C112
* 0x210x2c112
* (board[i] & 0x10)
* (board[i] & 0x20)
*/
char board[(NineChess::RING + 2)*NineChess::SEAT];
/* 本打算用如下的结构体来表示“三连”
struct Mill {
char piece1; // “三连”中最小的棋子
char pos1; // 最小棋子的位置
char piece2; // 次小的棋子
char pos2; // 次小棋子的位置
char piece3; // 最大的棋子
char pos3; // 最大棋子的位置
};
64
0x 00 00 00 00 00 00 00 00
unused unused piece1 pos1 piece2 pos2 piece3 pos3
*/
// “三连列表”
list <long long> millList;
/* 当前招法AI会用到如下表示
0x 00 00
pos1 pos2
0x00????
0x__??__为移动前的位置??
0xFF????
*/
short move_;
};
private:
// 空棋盘点位,用于判断一个棋子位置是否在棋盘上
static const char inBoard[(RING + 2)*SEAT];
// 招法表每个位置有最多4种走法顺时针、逆时针、向内、向外
// 这个表跟规则有关,一旦规则改变需要重新修改
static char moveTable[(RING + 2)*SEAT][4];
// 成三表,表示棋盘上各个位置有成三关系的对应位置表
// 这个表跟规则有关,一旦规则改变需要重新修改
static char millTable[(RING + 2)*SEAT][3][2];
public:
NineChess();
virtual ~NineChess();
/* 拷贝构造函数
NineChess类没有指针类型的成员变量list内的值也是深拷贝
*/
//explicit NineChess(const NineChess &);
// 设置棋局状态和棋盘数据,用于初始化
bool setData(const struct Rule *rule,
int s = 0, // 限制步数
@ -110,15 +191,15 @@ public:
// 获取当前点
int getCurrentPos() { return currentPos; }
// 获取当前步数
int getStep() { return step; }
int getStep() { return data_.step; }
// 获取局面阶段标识
enum Phases getPhase() { return phase; }
enum Phases getPhase() { return data_.phase; }
// 获取轮流状态标识
enum Player whosTurn() { return turn; }
enum Player whosTurn() { return data_.turn; }
// 获取动作状态标识
enum Actions getAction() { return action; }
enum Actions getAction() { return data_.action; }
// 判断胜负
enum Player whoWin() { return winner; }
enum Player whoWin() { return data_.winner; }
// 玩家1和玩家2的用时
void getPlayer_TimeMS(int &p1_ms, int &p2_ms);
// 获取棋局的字符提示
@ -137,15 +218,15 @@ public:
void setStartTimeb(timeb stimeb) { startTimeb = stimeb; }
// 玩家1剩余未放置子数
int getPlayer1_InHand() { return player1_InHand; }
int getPlayer1_InHand() { return data_.player1_InHand; }
// 玩家2剩余未放置子数
int getPlayer2_InHand() { return player2_InHand; }
int getPlayer2_InHand() { return data_.player2_InHand; }
// 玩家1盘面剩余子数
int getPlayer1_Remain() { return player1_Remain; }
int getPlayer1_Remain() { return data_.player1_Remain; }
// 玩家1盘面剩余子数
int getPlayer2_Remain() { return player2_Remain; }
int getPlayer2_Remain() { return data_.player2_Remain; }
// 尚待去除的子数
int getNum_NeedRemove() { return num_NeedRemove; }
int getNum_NeedRemove() { return data_.num_NeedRemove; }
// 游戏重置
bool reset();
@ -189,27 +270,10 @@ protected:
private:
// 当前使用的规则
struct Rule rule;
// 当前步数
int step;
// 局面阶段标识
enum Phases phase;
// 轮流状态标识
enum Player turn;
// 动作状态标识
enum Actions action;
// 赢家
enum Player winner;
// 玩家1剩余未放置子数
int player1_InHand;
// 玩家2剩余未放置子数
int player2_InHand;
// 玩家1盘面剩余子数
int player1_Remain;
// 玩家1盘面剩余子数
int player2_Remain;
// 尚待去除的子数
int num_NeedRemove;
// 棋盘数据
struct Data data_;
// 选中的棋子在board中的位置
int currentPos;
// 游戏起始时间
timeb startTimeb;
@ -220,40 +284,7 @@ private:
// 玩家2用时毫秒
long player2_MS;
/* 棋局抽象为一个5×8的char数组上下两行留空
* 0x00
* 0x0F
* 0x10(N-1)+0x101N子
* 0x20(N-1)+0x201N子
* (board[i] & 0x10)
* (board[i] & 0x20)
*/
char board[(RING + 2)*SEAT];
// 选中的棋子在board中的位置
int currentPos;
// 空棋盘点位,用于判断一个棋子位置是否在棋盘上
static const char inBoard[(RING + 2)*SEAT];
// 招法表每个位置有最多4种走法顺时针、逆时针、向内、向外
static char moveTable[(RING + 2)*SEAT][4];
// 成三表,表示棋盘上各个位置有成三关系的对应位置表
static char millTable[(RING + 2)*SEAT][3][2];
/* 本打算用如下的结构体来表示“三连”
struct Mill {
char piece1; // “三连”中最小的棋子
char pos1; // 最小棋子的位置
char piece2; // 次小的棋子
char pos2; // 次小棋子的位置
char piece3; // 最大的棋子
char pos3; // 最大棋子的位置
};
64
0x 00 00 00 00 00 00 00 00
unused unused piece1 pos1 piece2 pos2 piece3 pos3
*/
// “三连列表”
list <long long> millList;
// 招法命令行用于棋谱的显示和解析
// 当前招法的命令行指令,即一招棋谱
char cmdline[32];
// 棋谱

View File

@ -0,0 +1,107 @@
#include "NineChessAi_ab.h"
NineChessAi_ab::NineChessAi_ab():
rootNode(nullptr),
requiredQuit(false),
depth(5) // 默认5层深度
{
}
NineChessAi_ab::~NineChessAi_ab()
{
deleteTree(rootNode);
}
void NineChessAi_ab::buildChildren(Node *node)
{
;
}
void NineChessAi_ab::sortChildren(Node *node)
{
// 这个函数对效率的影响很大,
// 排序好的话,剪枝较早,节省时间
// 但不能在此函数耗费太多时间
;
}
void NineChessAi_ab::deleteTree(Node *node)
{
if (rootNode) {
for (auto i : rootNode->children) {
deleteTree(i);
}
rootNode->children.clear();
delete rootNode;
}
}
void NineChessAi_ab::setChess(const NineChess &chess)
{
this->chess = chess;
chessTemp = chess;
requiredQuit = false;
}
int NineChessAi_ab::evaluate(Node *node)
{
// 初始评估值为0对先手有利则增大对后手有利则减小
int value = 0;
// 赋值返回
node->value = value;
return value;
}
int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
{
// 评价值
int value;
if (!depth || !(node->children.size())) {
node->value = evaluate(node);
return node->value;
}
// 生成子节点树
buildChildren(node);
// 排序子节点树
sortChildren(node);
// 根据演算模型执行MiniMax检索
// 对先手搜索Max
if (chessTemp.whosTurn() == NineChess::PLAYER1) {
for (auto child : node->children) {
value = alphaBetaPruning(depth - 1, alpha, beta, child);
// 取最大值
if (value > alpha)
alpha = value;
// 剪枝返回
if (alpha >= beta) {
return value;
}
}
// 取最大值
node->value = alpha;
}
// 对后手搜索Min
else {
for (auto child : node->children) {
value = alphaBetaPruning(depth - 1, alpha, beta, child);
// 取最小值
if (value < beta)
beta = value;
// 剪枝返回
if (alpha >= beta) {
return value;
}
}
// 取最小值
node->value = beta;
}
// 返回
return node->value;
}

View File

@ -0,0 +1,60 @@
#ifndef NINECHESSAI_AB
#define NINECHESSAI_AB
#include "ninechess.h"
#include <list>
// 注意NineChess类不是线程安全的
// 所以不能在ai类中修改NineChess类的静态成员变量切记
class NineChessAi_ab
{
public:
// 定义一个节点结构体
struct Node{
int value; // 节点的值
short move_; // 招法的命令行指令,图上标示为节点前的连线
struct Node * parent; // 父节点
list<struct Node *> children; // 子节点列表
};
public:
NineChessAi_ab();
~NineChessAi_ab();
void setChess(const NineChess &chess);
void setDepth(int depth) { this->depth = depth; }
void quit() { requiredQuit = true; }
protected:
// 建立子节点
void buildChildren(Node *node);
// 子节点排序
void sortChildren(Node *node);
// 清空节点树
void deleteTree(Node *node);
// 评价函数
int evaluate(Node *node);
// Alpha-Beta剪枝算法
int alphaBetaPruning(int depth, int alpha, int beta, Node *node);
private:
// 原始模型
NineChess chess;
// 演算用的模型
NineChess chessTemp;
// 根节点
Node * rootNode;
// 标识,用于跳出剪枝算法,立即返回
bool requiredQuit;
// 剪枝算法的层深
int depth;
// 定义极大值等于32位有符号整形数字的最大值
static const int infinity = 0x7fffffff;
};
#endif

View File

@ -85,6 +85,19 @@ NineChessWindow::NineChessWindow(QWidget *parent)
NineChessWindow::~NineChessWindow()
{
if (game) {
game->disconnect();
game->deleteLater();
}
qDeleteAll(ruleActionList);
}
void NineChessWindow::closeEvent(QCloseEvent *event)
{
if (file.isOpen())
file.close();
//qDebug() << "closed";
QMainWindow::closeEvent(event);
}
bool NineChessWindow::eventFilter(QObject *watched, QEvent *event)
@ -108,20 +121,6 @@ bool NineChessWindow::eventFilter(QObject *watched, QEvent *event)
return QMainWindow::eventFilter(watched, event);
}
void NineChessWindow::closeEvent(QCloseEvent *event)
{
if (file.isOpen())
file.close();
if (game) {
game->disconnect();
delete game;
game = nullptr;
}
qDeleteAll(ruleActionList);
//qDebug() << "closed";
QMainWindow::closeEvent(event);
}
void NineChessWindow::initialize()
{
// 初始化函数,仅执行一次
@ -161,10 +160,7 @@ void NineChessWindow::initialize()
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
game, SLOT(setAnimation(bool)));
/* 关联控制器的信号和主窗口控件的槽
GameController中直接控制NineChessWindow
MVC模型中控制器与视图相分离的方式 */
// 关联控制器的信号和主窗口控件的槽
// 更新LCD1显示玩家1用时
connect(game, SIGNAL(time1Changed(QString)),
ui.lcdNumber_1, SLOT(display(QString)));
@ -208,7 +204,7 @@ void NineChessWindow::initialize()
connect(ui.actionEnd_E, &QAction::triggered,
this, &NineChessWindow::on_actionRowChange);
// 手动在listView里选择招法后更新的槽
connect(ui.listView, &SizeHintListView::currentChangedSignal,
connect(ui.listView, &ManualListView::currentChangedSignal,
this, &NineChessWindow::on_actionRowChange);
// 更新四个键的状态
on_actionRowChange();
@ -238,7 +234,6 @@ void NineChessWindow::ruleInfo()
void NineChessWindow::actionRules_triggered()
{
// setChecked函数会发出toggled信号在这里响应toggled信号会陷入死循环
// 取消其它规则的选择
for(QAction *action: ruleActionList)
action->setChecked(false);
@ -246,6 +241,10 @@ void NineChessWindow::actionRules_triggered()
QAction *action = dynamic_cast<QAction *>(sender());
action->setChecked(true);
ruleNo = action->data().toInt();
// 取消AI设定
ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false);
// 重置游戏规则
game->setRule(ruleNo);
// 更新规则显示
@ -441,13 +440,20 @@ void NineChessWindow::on_actionRowChange()
// 更新局面
bool changed = game->phaseChange(currentRow);
// 处理自动播放时的动画
// 处理自动播放时的动画
if (changed && game->isAnimation()) {
int waitTime = game->getDurationTime() + 50;
// 使用QEventLoop进行非阻塞延时CPU占用低
QEventLoop loop;
QTimer::singleShot(waitTime, &loop, SLOT(quit()));
loop.exec();
// 不使用processEvents函数进行非阻塞延时频繁调用占用CPU较多
//QElapsedTimer et;
//et.start();
//while (et.elapsed() < waitTime) {
// qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
//}
int waitTime = game->getDurationTime() + 50;
// 使用QEventLoop进行非阻塞延时CPU占用低
QEventLoop loop;
QTimer::singleShot(waitTime, &loop, SLOT(quit()));
loop.exec();
}
}
@ -456,8 +462,8 @@ void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
{
if (!arg1)
return;
int rows = ui.listView->model()->rowCount();
int rows = ui.listView->model()->rowCount();
int currentRow = ui.listView->currentIndex().row();
if (rows <= 1)
@ -504,22 +510,6 @@ void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
// 更新局面
game->phaseChange(currentRow);
// 处理自动播放时的动画
if (game->isAnimation()) {
int waitTime = game->getDurationTime() + 50;
// 不使用processEvents函数进行非阻塞延时频繁调用占用CPU较多
//QElapsedTimer et;
//et.start();
//while (et.elapsed() < waitTime) {
// qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
//}
// 使用QEventLoop进行非阻塞延时CPU占用低
QEventLoop loop;
QTimer::singleShot(waitTime, &loop, SLOT(quit()));
loop.exec();
}
}
// 自动运行结束后启用所有控件

View File

@ -1,6 +1,7 @@
#include "pieceitem.h"
#include "graphicsconst.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOption>
PieceItem::PieceItem(QGraphicsItem *parent) : QGraphicsItem(parent),
@ -63,11 +64,11 @@ void PieceItem::paint(QPainter *painter,
// 如果模型为黑色,则画黑色棋子
if (model == blackPiece)
painter->drawPixmap(-size/2, -size/2, size, size,
QPixmap(":/image/Resources/image/black_piece.png"));
QPixmap(":/image/resources/image/black_piece.png"));
// 如果模型为白色,则画白色棋子
else if (model == whitePiece)
painter->drawPixmap(-size/2, -size/2, size, size,
QPixmap(":/image/Resources/image/white_piece.png"));
QPixmap(":/image/resources/image/white_piece.png"));
// 如果模型要求显示序号
if (showNum)

View File

@ -6,7 +6,8 @@
class PieceItem : public QObject, public QGraphicsItem
{
Q_OBJECT
// 位置属性
Q_INTERFACES(QGraphicsItem)
// 位置属性
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
public:
@ -43,9 +44,9 @@ public:
void setShowNum(bool show = true) { this->showNum = show; }
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
// 棋子本质

View File

@ -64,33 +64,44 @@
```
MVC
├─Model
│ └─NineChess用标准C++写的棋类模型,处理下棋过程
│ ├─NineChess: 用标准C++写的棋类模型,处理下棋过程
│ └─NineChessAi_ab: 用标准C++写的alpha-beta剪枝算法AI模型模仿人类下棋
├─View
│ ├─NineChessWindow从QMainWindow派生的主窗口类由Qt自动生成
│ ├─SizeHintListView从QListView派生的列表框用于显示棋谱
│ ├─GameView从QGraphicsView派生的视图框用于显示棋局
│ ├─GameScene从QGraphicsScene派生的场景类
│ ├─BoardItem从QGraphicsItem派生的棋盘图形类
│ └─PiecedItem从QGraphicsItem派生的棋子图形类
│ ├─NineChessWindow: 从QMainWindow派生的主窗口类由Qt自动生成
│ ├─ManualListView: 从QListView派生的列表框用于显示棋谱
│ ├─GameView: 从QGraphicsView派生的视图框用于显示棋局
│ ├─GameScene: 从QGraphicsScene派生的场景类
│ ├─BoardItem: 从QGraphicsItem派生的棋盘图形类
│ └─PiecedItem: 从QGraphicsItem派生的棋子图形类
└─Controller
└─GameController从QObject派生的控制类
├─GameController: 从QObject派生的控制类
└─AiThread: 从QThread派生的AI线程类
```
这个程序用到了很多Qt的特性其模式后期可以扩展到各种棋类游戏。
### 许可协议及更新历史
详见文末Gitee内的License和History文件。请取用的朋友尊重知识产权。
### AI算法说明
相见Wiki目录下的《Alpha-Beta剪枝算法在直棋中的运用》
### 许可协议
**本项目所有类代码全部原创。**
详见文末Gitee项目内的License文件。请取用的朋友尊重知识产权。
### 更新历史
详见文末Gitee项目内的History文件。
## 作者声明
本项目所有类代码全部原创。由于本人非IT科班出身未经专业培训也没有现成的QT棋类游戏源码做参考源码中肯定有很多不合理不规范之处。望好心的前辈不吝赐教。对于其它初学者可以参考相互学习共同进步。
由于本人非IT科班出身未经专业培训也没有现成的QT棋类游戏源码做参考源码中肯定有很多不合理不规范之处。望好心的前辈不吝赐教。对于同道初学者,可以参考,相互学习,共同进步。
多年前上大学那会儿,笔者就打算做这么个程序出来,然而条件比较艰苦:
一来没有老师教课上只学了Ç语言和VBC ++是笔者自学的一个人啃晦涩过时的MFC;
二来我穷到连个电脑都没有......三嘛,就是贪玩......
一来没有老师教课上只学了Ç语言和VBC++是笔者自学的一个人啃晦涩过时的MFC;
二来我穷到连个电脑都没有......
三嘛,就是贪玩......
工作之后有条件了我又自学了C和Qt但都很肤浅没深入学只用来做几个小工具而已。
这个项目我在2013年用标准C++写了个模型类然后扔了不管2015年自学Qt写了个简单的界面又扔了不管直到2018年5月才重新开始做。
如果你发现本程序有什么问题或好的建议请与本人联系。我的邮箱是liuweilhy@163.com
> by liuweilhy 2015年11月6日
> by liuweilhy 2018年11月26日
## 项目源码及发行版下载
+ 源码下载Gitee[https://gitee.com/liuweilhy/NineChess](https://gitee.com/liuweilhy/NineChess)
+ 发行版下载Gitee[https://gitee.com/liuweilhy/NineChess/releases](https://gitee.com/liuweilhy/NineChess/releases)
+ 如果你没有Gitee账号可以在本人CSDN资源下载:(链接待补充)
+ 如果你以上都没有,那么用百度云盘吧:(链接待补充)
+ 发行版下载Gitee,请选择最新版[https://gitee.com/liuweilhy/NineChess/releases](https://gitee.com/liuweilhy/NineChess/releases)
+ 如果你没有Gitee账号可以在本人CSDN资源下载(非最新版):(链接待补充)
+ 如果你以上都没有,那么用百度云盘(非最新版):(链接待补充)

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB