mirror of
https://github.com/jie65535/Landlords.git
synced 2024-07-27 19:05:27 +08:00
提交源代码
上次创建Git仓库后忘记上传代码了。。 编译环境 VS2017 需要配合酷Q C++ SDK使用
This commit is contained in:
parent
2cf768605a
commit
4656410829
BIN
Landlords/CQP.lib
Normal file
BIN
Landlords/CQP.lib
Normal file
Binary file not shown.
2
Landlords/Debug/Landlords.log
Normal file
2
Landlords/Debug/Landlords.log
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Room.cpp
|
||||||
|
Landlords.vcxproj -> F:\C++\代码\斗地主\Landlords\Debug\me.cqp.jie.landlords.dll
|
BIN
Landlords/Debug/Landlords.obj
Normal file
BIN
Landlords/Debug/Landlords.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/Landlords.tlog/CL.command.1.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/CL.command.1.tlog
Normal file
Binary file not shown.
BIN
Landlords/Debug/Landlords.tlog/CL.read.1.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/CL.read.1.tlog
Normal file
Binary file not shown.
BIN
Landlords/Debug/Landlords.tlog/CL.write.1.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/CL.write.1.tlog
Normal file
Binary file not shown.
2
Landlords/Debug/Landlords.tlog/Landlords.lastbuildstate
Normal file
2
Landlords/Debug/Landlords.tlog/Landlords.lastbuildstate
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.16299.0
|
||||||
|
Debug|Win32|F:\C++\代码\斗地主\Landlords\|
|
BIN
Landlords/Debug/Landlords.tlog/Landlords.write.1u.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/Landlords.write.1u.tlog
Normal file
Binary file not shown.
BIN
Landlords/Debug/Landlords.tlog/link.command.1.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/link.command.1.tlog
Normal file
Binary file not shown.
BIN
Landlords/Debug/Landlords.tlog/link.read.1.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/link.read.1.tlog
Normal file
Binary file not shown.
BIN
Landlords/Debug/Landlords.tlog/link.write.1.tlog
Normal file
BIN
Landlords/Debug/Landlords.tlog/link.write.1.tlog
Normal file
Binary file not shown.
BIN
Landlords/Debug/Player.obj
Normal file
BIN
Landlords/Debug/Player.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/PlayingCards.obj
Normal file
BIN
Landlords/Debug/PlayingCards.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/Process.obj
Normal file
BIN
Landlords/Debug/Process.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/Room.obj
Normal file
BIN
Landlords/Debug/Room.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/Server.obj
Normal file
BIN
Landlords/Debug/Server.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/dllmain.obj
Normal file
BIN
Landlords/Debug/dllmain.obj
Normal file
Binary file not shown.
34
Landlords/Debug/me.cqp.jie.landlords.Build.CppClean.log
Normal file
34
Landlords/Debug/me.cqp.jie.landlords.Build.CppClean.log
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.pch.codeanalysis
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\vc141.pdb
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\vc141.idb
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.pch.codeanalysisast
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\stdafx.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\stdafx.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.pch
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\dllmain.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\player.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\process.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\room.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\server.nativecodeanalysis.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\server.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\room.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\process.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\player.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\dllmain.obj
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.lib
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.exp
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.dll
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.ilk
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.pdb
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\nativecodeanalysis.read.1.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\vc.nativecodeanalysis.all.xml
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\me.cqp.jie.landlords.dll.lastcodeanalysissucceeded
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\cl.command.1.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\cl.read.1.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\cl.write.1.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\landlords.write.1u.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\link.command.1.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\link.read.1.tlog
|
||||||
|
f:\c++\代码\斗地主\landlords\debug\landlords.tlog\link.write.1.tlog
|
BIN
Landlords/Debug/me.cqp.jie.landlords.dll
Normal file
BIN
Landlords/Debug/me.cqp.jie.landlords.dll
Normal file
Binary file not shown.
BIN
Landlords/Debug/me.cqp.jie.landlords.exp
Normal file
BIN
Landlords/Debug/me.cqp.jie.landlords.exp
Normal file
Binary file not shown.
BIN
Landlords/Debug/me.cqp.jie.landlords.ilk
Normal file
BIN
Landlords/Debug/me.cqp.jie.landlords.ilk
Normal file
Binary file not shown.
BIN
Landlords/Debug/me.cqp.jie.landlords.lib
Normal file
BIN
Landlords/Debug/me.cqp.jie.landlords.lib
Normal file
Binary file not shown.
BIN
Landlords/Debug/me.cqp.jie.landlords.pch
Normal file
BIN
Landlords/Debug/me.cqp.jie.landlords.pch
Normal file
Binary file not shown.
BIN
Landlords/Debug/me.cqp.jie.landlords.pdb
Normal file
BIN
Landlords/Debug/me.cqp.jie.landlords.pdb
Normal file
Binary file not shown.
BIN
Landlords/Debug/stdafx.obj
Normal file
BIN
Landlords/Debug/stdafx.obj
Normal file
Binary file not shown.
BIN
Landlords/Debug/vc141.idb
Normal file
BIN
Landlords/Debug/vc141.idb
Normal file
Binary file not shown.
BIN
Landlords/Debug/vc141.pdb
Normal file
BIN
Landlords/Debug/vc141.pdb
Normal file
Binary file not shown.
BIN
Landlords/Landlords.cpp
Normal file
BIN
Landlords/Landlords.cpp
Normal file
Binary file not shown.
3
Landlords/Landlords.h
Normal file
3
Landlords/Landlords.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#define CQAPPID "me.cqp.jie.landlords" //请修改AppID,规则见 http://d.cqp.me/Pro/开发/基础信息
|
||||||
|
#define CQAPPINFO CQAPIVERTEXT "," CQAPPID
|
31
Landlords/Landlords.sln
Normal file
31
Landlords/Landlords.sln
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27130.2036
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Landlords", "Landlords.vcxproj", "{B402092F-048F-49AD-83D4-2AA6147FFD4D}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{B402092F-048F-49AD-83D4-2AA6147FFD4D}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {C440E136-2D5E-4954-92E5-3F28627FC23B}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
190
Landlords/Landlords.vcxproj
Normal file
190
Landlords/Landlords.vcxproj
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{B402092F-048F-49AD-83D4-2AA6147FFD4D}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>Landlords</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<TargetName>me.cqp.jie.landlords</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<TargetName>me.cqp.jie.landlords</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;LANDLORDS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;LANDLORDS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;LANDLORDS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;LANDLORDS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="cqp.h" />
|
||||||
|
<ClInclude Include="define.h" />
|
||||||
|
<ClInclude Include="Landlords.h" />
|
||||||
|
<ClInclude Include="Player.h" />
|
||||||
|
<ClInclude Include="PlayingCards.h" />
|
||||||
|
<ClInclude Include="Process.h" />
|
||||||
|
<ClInclude Include="Room.h" />
|
||||||
|
<ClInclude Include="Server.h" />
|
||||||
|
<ClInclude Include="stdafx.h" />
|
||||||
|
<ClInclude Include="targetver.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="Landlords.cpp" />
|
||||||
|
<ClCompile Include="Player.cpp" />
|
||||||
|
<ClCompile Include="PlayingCards.cpp" />
|
||||||
|
<ClCompile Include="Process.cpp" />
|
||||||
|
<ClCompile Include="Room.cpp" />
|
||||||
|
<ClCompile Include="Server.cpp" />
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="me.cqp.jie.landlords.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Library Include="CQP.lib" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Text Include="recording.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
84
Landlords/Landlords.vcxproj.filters
Normal file
84
Landlords/Landlords.vcxproj.filters
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="源文件">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="资源文件">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="stdafx.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="targetver.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="cqp.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Landlords.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Player.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Room.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Server.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="define.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Process.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PlayingCards.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Landlords.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="dllmain.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Player.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Room.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Server.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Process.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PlayingCards.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="me.cqp.jie.landlords.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Library Include="CQP.lib" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Text Include="recording.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
6
Landlords/Landlords.vcxproj.user
Normal file
6
Landlords/Landlords.vcxproj.user
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ShowAllFiles>false</ShowAllFiles>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
13
Landlords/Player.cpp
Normal file
13
Landlords/Player.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
||||||
|
Player::Player(playerID_t id):
|
||||||
|
m_id(id), m_name(), m_integral(0), m_currRoom(0), isReady(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Player::~Player()
|
||||||
|
{
|
||||||
|
}
|
36
Landlords/Player.h
Normal file
36
Landlords/Player.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "define.h"
|
||||||
|
// #include <string>
|
||||||
|
|
||||||
|
class Player
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Player() = delete;
|
||||||
|
Player(playerID_t id);
|
||||||
|
~Player();
|
||||||
|
|
||||||
|
playerID_t getID() { return m_id; }
|
||||||
|
int getIntegral() { return m_integral; }
|
||||||
|
roomID_t getCurrRoom() { return m_currRoom; }
|
||||||
|
void setCurrRoom(roomID_t rid) { m_currRoom = rid; }
|
||||||
|
std::string getName() { return m_name; }
|
||||||
|
void setName(std::string newName) { m_name = newName; }
|
||||||
|
void setIntegral(int integral) { m_integral = integral; }
|
||||||
|
|
||||||
|
// 得分 正数为加分 负数为扣分
|
||||||
|
void score(int integral) { m_integral += integral; }
|
||||||
|
|
||||||
|
bool operator==(Player &rhs) { return m_id == rhs.getID(); }
|
||||||
|
bool operator==(playerID_t pid) { return m_id == pid; }
|
||||||
|
bool operator<(Player &rhs) { return m_id < rhs.getID(); }
|
||||||
|
bool operator<(playerID_t pid) { return m_id < pid; }
|
||||||
|
public:
|
||||||
|
bool isReady; // 准备
|
||||||
|
private:
|
||||||
|
playerID_t m_id; // 唯一ID
|
||||||
|
std::string m_name; // 昵称
|
||||||
|
int m_integral; // 积分
|
||||||
|
roomID_t m_currRoom; // 当前所在房间(0为无)
|
||||||
|
};
|
||||||
|
|
153
Landlords/PlayingCards.cpp
Normal file
153
Landlords/PlayingCards.cpp
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "PlayingCards.h"
|
||||||
|
|
||||||
|
void PlayingCards::updata()
|
||||||
|
{
|
||||||
|
if (cards.empty())
|
||||||
|
{
|
||||||
|
type = c0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::sort(cards.begin(), cards.end());
|
||||||
|
size = cards.size();
|
||||||
|
if (size == 2 && cards[0] == _S && cards[1] == _B)
|
||||||
|
{
|
||||||
|
type = c11;
|
||||||
|
}
|
||||||
|
else if (size < 5) // 如果小于5张
|
||||||
|
{
|
||||||
|
// 首尾相同 单 双 三 炸
|
||||||
|
if (cards.front() == cards.back())
|
||||||
|
{
|
||||||
|
if (size == 1)
|
||||||
|
type = c1;
|
||||||
|
else if (size == 2)
|
||||||
|
type = c2;
|
||||||
|
else if (size == 3)
|
||||||
|
type = c3;
|
||||||
|
else if (size == 4)
|
||||||
|
type = c4;
|
||||||
|
max = cards[0];
|
||||||
|
}
|
||||||
|
else if (size == 4) // 四张不同的 三带一?
|
||||||
|
{
|
||||||
|
if (cards[0] == cards[2])
|
||||||
|
type = c31, max = cards[0];
|
||||||
|
else if (cards[1] == cards[3])
|
||||||
|
type = c31, max = cards[1];
|
||||||
|
else
|
||||||
|
type = c0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (size >= 5) // 如果大于等于5张
|
||||||
|
{
|
||||||
|
// std::vector<card_t> cards; 要识别的牌
|
||||||
|
// arr[0] 重复一次的牌
|
||||||
|
// arr[1] 重复两次的牌
|
||||||
|
// arr[2] 重复三次的牌
|
||||||
|
// arr[3] 重复四次的牌
|
||||||
|
std::vector<card_t> arr[4];
|
||||||
|
for (int index = 0; index < size;)
|
||||||
|
{
|
||||||
|
card_t temp = cards[index++];
|
||||||
|
int count = 1;
|
||||||
|
for (; index < size && temp == cards[index]; ++index)
|
||||||
|
count++;
|
||||||
|
if (temp == _S || temp == _B && count > 1) // 大王小王还有多的?
|
||||||
|
type = c0;
|
||||||
|
if (count > 4) // 五张以上一样的??
|
||||||
|
type = c0;
|
||||||
|
else
|
||||||
|
arr[count - 1].push_back(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 三带一对
|
||||||
|
if (size == 5 && arr[2].size() == 1 && arr[1].size() == 1)
|
||||||
|
type = c32, max = arr[2].front();
|
||||||
|
// 四带两张 333345、666677
|
||||||
|
else if (size == 6 && arr[3].size() == 1)
|
||||||
|
type = c411, max = arr[3].front();
|
||||||
|
// 四带两对
|
||||||
|
else if (size == 8 && arr[3].size() == 1 && arr[1].size() == 2)
|
||||||
|
type = c422, max = arr[3].front();
|
||||||
|
// 单顺
|
||||||
|
else if (size == arr[0].size()
|
||||||
|
&& arr[0].back() - arr[0].front() == size - 1 // 最后一张减第一张 == 总数-1
|
||||||
|
&& arr[0].back() < _2) // 最大的牌小于2
|
||||||
|
{
|
||||||
|
type = c123, max = arr[0].back();
|
||||||
|
}
|
||||||
|
// 连对
|
||||||
|
else if (size / 2 >= 3 && (size % 2 == 0) // 判断是否大于3对并且牌数是偶数
|
||||||
|
&& arr[1].size() == size / 2 // 是不是都是对子
|
||||||
|
&& arr[1].back() - arr[1].front() == size / 2 - 1 // 对子是不是连着的
|
||||||
|
&& arr[1].back() < _2) // 最大的牌小于2
|
||||||
|
{
|
||||||
|
type = c1122, max = arr[1].back();
|
||||||
|
}
|
||||||
|
// 飞机
|
||||||
|
else if (arr[2].size() == size / 3
|
||||||
|
&& (size % 3 == 0)
|
||||||
|
&& arr[2].back() - arr[2].front() == (size / 3 - 1)
|
||||||
|
&& arr[2].back() < _2)
|
||||||
|
{
|
||||||
|
type = c111222, max = arr[2].back();
|
||||||
|
}
|
||||||
|
// 飞机带翅膀 单
|
||||||
|
else if (arr[2].size() >= 2
|
||||||
|
&& arr[2].size() == size / 4
|
||||||
|
&& (size % 4 == 0)
|
||||||
|
&& arr[2].back() - arr[2].front() == size / 4 - 1
|
||||||
|
&& arr[2].back() < _2)
|
||||||
|
{
|
||||||
|
type = c11122234, max = arr[2].back();
|
||||||
|
}
|
||||||
|
// 飞机带翅膀 双
|
||||||
|
else if (arr[2].size() >= 2
|
||||||
|
&& arr[2].size() == size / 5
|
||||||
|
&& (size % 5 == 0) // 被5整除?
|
||||||
|
&& arr[2].back() - arr[2].front() == size / 5 - 1 // 是否连
|
||||||
|
&& arr[1].size() == size / 5 // 有相同数量的对子
|
||||||
|
&& arr[2].back() < _2)
|
||||||
|
{
|
||||||
|
type = c1112223344, max = arr[2].back();
|
||||||
|
}
|
||||||
|
// 什么都不是,不能出!
|
||||||
|
else
|
||||||
|
type = c0;
|
||||||
|
|
||||||
|
// 对牌进行排序,相同数量多的在前
|
||||||
|
if (type != c0)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
for (int r = 3; r >= 0; --r)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < arr[r].size(); ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < r+1; ++j)
|
||||||
|
cards[index++] = arr[r][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // 如果大于等于5张 -- end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayingCards::operator<(const PlayingCards & rhs) const
|
||||||
|
{
|
||||||
|
// 王炸
|
||||||
|
if (type == c11)
|
||||||
|
return false;
|
||||||
|
else if (rhs.type == c11)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 炸弹
|
||||||
|
if (type == c4 && rhs.type != c4)
|
||||||
|
return false;
|
||||||
|
else if (type != c4 && rhs.type == c4)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 假定牌型数量一样,比较权值
|
||||||
|
return max < rhs.max;
|
||||||
|
}
|
41
Landlords/PlayingCards.h
Normal file
41
Landlords/PlayingCards.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "define.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum CardType {
|
||||||
|
c1, //单牌
|
||||||
|
c2, //对子
|
||||||
|
c3, //3不带
|
||||||
|
c4, //炸弹
|
||||||
|
c11, //王炸
|
||||||
|
c31, //3带1
|
||||||
|
c32, //3带2
|
||||||
|
c411, //4带2个单,或者一对
|
||||||
|
c422, //4带2对
|
||||||
|
c123, //连子
|
||||||
|
c1122, //连队
|
||||||
|
c111222, //飞机
|
||||||
|
c11122234, //飞机带单排
|
||||||
|
c1112223344,//飞机带对子
|
||||||
|
c0 //不能出牌
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PlayingCards
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlayingCards() = delete;
|
||||||
|
PlayingCards(const std::vector<card_t>& incards):cards(incards) { updata(); };
|
||||||
|
void updata();
|
||||||
|
std::vector<card_t> cards;
|
||||||
|
const std::vector<card_t> & getVec() const { return cards; }
|
||||||
|
CardType getType() const { return type; }
|
||||||
|
int getSize() const { return size; }
|
||||||
|
// 比较大小,不检测非法!
|
||||||
|
bool operator<(const PlayingCards& rhs) const;
|
||||||
|
private:
|
||||||
|
CardType type; // 牌型
|
||||||
|
card_t max; // 权值
|
||||||
|
int size; // 牌的数量
|
||||||
|
};
|
773
Landlords/Process.cpp
Normal file
773
Landlords/Process.cpp
Normal file
@ -0,0 +1,773 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Process.h"
|
||||||
|
using namespace std;
|
||||||
|
extern int ac;
|
||||||
|
string playerInfoToString(Player* pplayer)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
if (pplayer == nullptr)
|
||||||
|
{
|
||||||
|
out << "找不到该玩家信息" << endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "昵称:" << pplayer->getName() << '\t'
|
||||||
|
<< "id:" << pplayer->getID() << '\t'
|
||||||
|
<< "积分:" << pplayer->getIntegral() << '\t';
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
if (rid != 0)
|
||||||
|
{
|
||||||
|
out << "房间ID:" << rid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "大厅中";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string playerInfoToString(playerID_t pid)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
auto pplayer = server().getPlayer(pid);
|
||||||
|
out << playerInfoToString(pplayer);
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string playerListToString()
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
for (auto i : server().getPlayerList())
|
||||||
|
{
|
||||||
|
out << playerInfoToString(&i) << endl;
|
||||||
|
}
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string roomInfoToString(roomID_t rid)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
Room *proom = server().getRoom(rid);
|
||||||
|
if (proom == nullptr)
|
||||||
|
{
|
||||||
|
out << "找不到该房间";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
out << "房间id:" << proom->getID() << endl;
|
||||||
|
auto plist = proom->getPlayerIDList();
|
||||||
|
out << "房间人数:" << plist.size() << endl;
|
||||||
|
out << "详细信息:" << endl;
|
||||||
|
for (auto i : plist)
|
||||||
|
{
|
||||||
|
auto pplayer = server().getPlayer(i);
|
||||||
|
if (pplayer == nullptr)
|
||||||
|
{
|
||||||
|
out << "找不到该玩家信息" << endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "昵称:" << pplayer->getName()
|
||||||
|
<< "\t积分:" << pplayer->getIntegral()
|
||||||
|
<< (pplayer->isReady ? "\t已准备" : "\t未准备")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string roomListToString(bool isHideFull)
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
auto & vec = server().getRoomList();
|
||||||
|
if (vec.empty())
|
||||||
|
{
|
||||||
|
out << "[空]";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bool flag = false;
|
||||||
|
for (auto &i : vec)
|
||||||
|
{
|
||||||
|
if (isHideFull && i.full())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (flag == false)
|
||||||
|
{
|
||||||
|
out << "ID\t人数\t状态" << endl;
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
out << i.getID() << '\t' << i.getSize() << '/' << roomPlayerLimit << '\t';
|
||||||
|
if (i.getStatus() == roomStatus_t::Waiting)
|
||||||
|
out << "等待中";
|
||||||
|
else if (i.getStatus() == roomStatus_t::playing)
|
||||||
|
out << "游戏中";
|
||||||
|
out << endl;
|
||||||
|
}
|
||||||
|
if (flag == false)
|
||||||
|
out << "[空]";
|
||||||
|
}
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline playerID_t QQToPID(uint64_t fromQQ)
|
||||||
|
{
|
||||||
|
return playerID_t(fromQQ);
|
||||||
|
}
|
||||||
|
inline uint64_t PIDToQQ(playerID_t pid)
|
||||||
|
{
|
||||||
|
return uint64_t(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 广播消息给指定玩家ID的房间(该消息将发送给指定玩家之外所有人)
|
||||||
|
void broadcast(playerID_t pid, const string& msg)
|
||||||
|
{
|
||||||
|
//logFile << "尝试广播给该房间指定ID外所有玩家,指定ID:" << pid << std::endl;
|
||||||
|
Player * pplayer = server().getPlayer(pid);
|
||||||
|
if (pplayer == nullptr)
|
||||||
|
{
|
||||||
|
logFile << "没这个玩家" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Room *proom = server().getRoom(pplayer->getCurrRoom());
|
||||||
|
if (proom == nullptr)
|
||||||
|
{
|
||||||
|
logFile << "没这个房间" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto i : proom->getPlayerIDList())
|
||||||
|
{
|
||||||
|
if (pid != i)
|
||||||
|
{
|
||||||
|
// logFile << "正在发送给pid:" << i;
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(i), msg.c_str());
|
||||||
|
// logFile << " --- 完毕" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 广播消息给指定房间ID的房间(该消息将发送给该房间所有人)
|
||||||
|
void broadcast(roomID_t rid, const string& msg)
|
||||||
|
{
|
||||||
|
//logFile << "尝试广播给该房间所有玩家,房间ID:" << rid << std::endl;
|
||||||
|
|
||||||
|
Room *proom = server().getRoom(rid);
|
||||||
|
if (proom == nullptr)
|
||||||
|
{
|
||||||
|
logFile << "没这个房间" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto i : proom->getPlayerIDList())
|
||||||
|
{
|
||||||
|
// logFile << "正在发送给pid:" << i;
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(i), msg.c_str());
|
||||||
|
// logFile << " --- 完毕" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void instruction(uint64_t fromQQ, string msg)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
playerID_t pid = QQToPID(fromQQ);
|
||||||
|
Player *pplayer = server().getPlayer(pid);
|
||||||
|
|
||||||
|
|
||||||
|
if (msg == "准备")
|
||||||
|
{
|
||||||
|
if (server().playerReady(pid))
|
||||||
|
{
|
||||||
|
if (pplayer->isReady)
|
||||||
|
{
|
||||||
|
out << "已准备";
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
broadcast(pid, "有玩家准备");
|
||||||
|
|
||||||
|
// 如果开始游戏了就发牌给玩家,并且直接返回
|
||||||
|
if (server().startGame(rid))
|
||||||
|
{
|
||||||
|
broadcast(rid, "游戏已经开始!");
|
||||||
|
broadcast(rid, roomCardsToString(rid));
|
||||||
|
Room *proom = server().getRoom(rid);
|
||||||
|
// 给所有玩家看牌
|
||||||
|
for (auto pid : proom->getPlayerIDList())
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(pid), CardsToString(proom->getPlayerCards(pid)).c_str());
|
||||||
|
NotifyNextPlayer(rid, "是否叫地主 [叫地主] [不叫]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]叫地主");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "已取消";
|
||||||
|
broadcast(pid, "有玩家取消准备");
|
||||||
|
}
|
||||||
|
broadcast(pplayer->getCurrRoom(), string("当前房间信息:\n") + roomInfoToString(pplayer->getCurrRoom()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "操作失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "创建房间")
|
||||||
|
{
|
||||||
|
roomID_t rid = server().createRoom(pid);
|
||||||
|
if (rid != 0)
|
||||||
|
out << "创建成功";
|
||||||
|
else
|
||||||
|
out << "创建失败";
|
||||||
|
}
|
||||||
|
else if (msg.substr(0, 4) == "加入") {
|
||||||
|
std::istringstream tempin(msg.substr(4));
|
||||||
|
roomID_t rid = 0;
|
||||||
|
tempin >> rid;
|
||||||
|
if (tempin.bad())
|
||||||
|
{
|
||||||
|
out << "参数非法,请输入 加入+ID" << endl;
|
||||||
|
out << "例:加入 1";
|
||||||
|
}
|
||||||
|
else if (server().joinRoom(pid, rid))
|
||||||
|
{
|
||||||
|
out << "加入房间成功";
|
||||||
|
broadcast(pid, "有新玩家加入!");
|
||||||
|
broadcast(rid, string("当前房间信息:\n") + roomInfoToString(rid));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "加入房间失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "退出房间")
|
||||||
|
{
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
if (server().leaveRoom(pid))
|
||||||
|
{
|
||||||
|
out << "退出房间成功";
|
||||||
|
if (server().getRoom(rid))
|
||||||
|
{
|
||||||
|
broadcast(rid, string("有玩家退出!\n当前房间信息:\n") + roomInfoToString(rid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "退出失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "查看房间")
|
||||||
|
{
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
if (rid == 0)
|
||||||
|
out << "你当前正在大厅,无法查看当前房间";
|
||||||
|
else
|
||||||
|
out << roomInfoToString(rid);
|
||||||
|
}
|
||||||
|
else if (msg.substr(0, 8) == "房间列表")
|
||||||
|
{
|
||||||
|
if (msg[8] == '1')
|
||||||
|
{
|
||||||
|
out << roomListToString(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << roomListToString(false);
|
||||||
|
out << "\n发 *房间列表1 可以隐藏满人房间";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "玩家列表")
|
||||||
|
{
|
||||||
|
out << playerListToString();
|
||||||
|
}
|
||||||
|
else if (pplayer->getCurrRoom() != 0)
|
||||||
|
{
|
||||||
|
msg = "玩家[" + pplayer->getName() + "]说:" + msg;
|
||||||
|
broadcast(pplayer->getCurrRoom(), msg.c_str());
|
||||||
|
}
|
||||||
|
CQ_sendPrivateMsg(ac, fromQQ, out.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string roomCardsToString(roomID_t rid)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
Room *proom = server().getRoom(rid);
|
||||||
|
if (proom == nullptr)
|
||||||
|
out << "未加入房间";
|
||||||
|
else if (proom->getStatus() != roomStatus_t::playing)
|
||||||
|
out << "当前房间未开始游戏";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto pid : proom->getPlayerIDList())
|
||||||
|
{
|
||||||
|
Player *pplayer = server().getPlayer(pid);
|
||||||
|
if (proom->getLandID() != 0)
|
||||||
|
{
|
||||||
|
if (proom->getLandID() == pid)
|
||||||
|
out << "地主";
|
||||||
|
else
|
||||||
|
out << "农民";
|
||||||
|
}
|
||||||
|
out << '[' << pplayer->getName() << "]\t剩余手牌数量:" << proom->getPlayerCardsSize(pid) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CardToString(card_t card)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
switch (card)
|
||||||
|
{
|
||||||
|
case _3:str = " 3";break;
|
||||||
|
case _4:str = " 4";break;
|
||||||
|
case _5:str = " 5";break;
|
||||||
|
case _6:str = " 6";break;
|
||||||
|
case _7:str = " 7";break;
|
||||||
|
case _8:str = " 8";break;
|
||||||
|
case _9:str = " 9";break;
|
||||||
|
case _10:str = "10";break;
|
||||||
|
case _J:str = " J";break;
|
||||||
|
case _Q:str = " Q";break;
|
||||||
|
case _K:str = " K";break;
|
||||||
|
case _A:str = " A";break;
|
||||||
|
case _2:str = " 2";break;
|
||||||
|
case _S:str = "小";break;
|
||||||
|
case _B:str = "大"; break;
|
||||||
|
}
|
||||||
|
str = "[" + str + "]";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CardsToString(const vector<card_t> &cards)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
for (auto i : cards)
|
||||||
|
{
|
||||||
|
out << CardToString(i);
|
||||||
|
}
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CardTtypeToString(CardType ct)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
switch (ct)
|
||||||
|
{
|
||||||
|
case c1: str = "单牌"; break;
|
||||||
|
case c2: str = "对子"; break;
|
||||||
|
case c3: str = "三张"; break;
|
||||||
|
case c4: str = "炸弹"; break;
|
||||||
|
case c11: str = "王炸"; break;
|
||||||
|
case c31: str = "三带一"; break;
|
||||||
|
case c32: str = "三带二"; break;
|
||||||
|
case c411: str = "四带二"; break;
|
||||||
|
case c422: str = "四带两对"; break;
|
||||||
|
case c123: str = "顺子"; break;
|
||||||
|
case c1122: str = "连对"; break;
|
||||||
|
case c111222: str = "飞机"; break;
|
||||||
|
case c11122234: str = "飞机带翅膀"; break;
|
||||||
|
case c1112223344: str = "飞机带翅膀"; break;
|
||||||
|
case c0: str = "不能出牌"; break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector< card_t > StringToCards(const string src) {
|
||||||
|
vector< card_t > cards;
|
||||||
|
card_t temp;
|
||||||
|
for (size_t i = 0; i < src.size(); ++i) {
|
||||||
|
if (src[i] == '1' && src[i + 1] == '0') {
|
||||||
|
i++;
|
||||||
|
temp = _10;
|
||||||
|
}
|
||||||
|
else if (src.substr(i, i + 4) == "大王") {
|
||||||
|
i += 3;
|
||||||
|
temp = _B;
|
||||||
|
}
|
||||||
|
else if (src.substr(i, i + 2) == "大"){
|
||||||
|
i += 1;
|
||||||
|
temp = _B;
|
||||||
|
}
|
||||||
|
else if (src.substr(i, i + 4) == "小王") {
|
||||||
|
i += 3;
|
||||||
|
temp = _S;
|
||||||
|
}
|
||||||
|
else if (src.substr(i, i + 2) == "小") {
|
||||||
|
i += 1;
|
||||||
|
temp = _S;
|
||||||
|
}
|
||||||
|
else if (src.substr(i, i + 4) == "王炸") {
|
||||||
|
cards.push_back(_B);
|
||||||
|
cards.push_back(_S);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (src[i]) {
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
temp = _A;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
temp = _2;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
temp = _3;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
temp = _4;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
temp = _5;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
temp = _6;
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
temp = _7;
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
temp = _8;
|
||||||
|
break;
|
||||||
|
case '9':
|
||||||
|
temp = _9;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
case 'J':
|
||||||
|
temp = _J;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
temp = _Q;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
temp = _K;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cards.push_back(temp);
|
||||||
|
}
|
||||||
|
return cards;
|
||||||
|
}
|
||||||
|
|
||||||
|
void becomeLandlord(Room * proom)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
Player * pLand = server().getPlayer(proom->getLandID());
|
||||||
|
broadcast(pLand->getID(), "玩家[" + pLand->getName() + "]成为了地主!");
|
||||||
|
out << "你成为了地主!手牌:\n";
|
||||||
|
out << CardsToString(proom->getPlayerCards(pLand->getID()));
|
||||||
|
string temp;
|
||||||
|
for (auto i : proom->getLandCards())
|
||||||
|
temp += CardToString(i);
|
||||||
|
broadcast(proom->getID(), "地主牌:" + temp);
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(pLand->getID()), out.str().c_str());
|
||||||
|
NotifyNextPlayer(proom->getID(), "轮到你出牌", "等待地主出牌");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知该玩家所有人
|
||||||
|
// 参数 msg 是发送给该轮轮到的玩家的消息
|
||||||
|
// 参数 otherMsg 是发送给其它玩家的消息
|
||||||
|
void NotifyNextPlayer(roomID_t rid, std::string msg, std::string otherMsg)
|
||||||
|
{
|
||||||
|
Room * proom = server().getRoom(rid);
|
||||||
|
for (auto pid : proom->getPlayerIDList())
|
||||||
|
{
|
||||||
|
if (proom->getThisTurn() == pid)
|
||||||
|
{
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(pid), msg.c_str());
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(pid), CardsToString(proom->getPlayerCards(pid)).c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(pid), otherMsg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 游戏指令
|
||||||
|
void gameCommand(uint64_t fromQQ, string msg)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
playerID_t pid = QQToPID(fromQQ);
|
||||||
|
Player *pplayer = server().getPlayer(pid);
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
Room * proom = server().getRoom(rid);
|
||||||
|
do {/******************** do while 块 方便跳出 ************************/
|
||||||
|
if (pplayer == nullptr ||
|
||||||
|
proom == nullptr ||
|
||||||
|
proom->getStatus() != roomStatus_t::playing)
|
||||||
|
{
|
||||||
|
out << "当前状态无法使用游戏指令,必须在游戏状态下才可以使用";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg == "看牌")
|
||||||
|
{
|
||||||
|
out << roomCardsToString(rid);
|
||||||
|
out << CardsToString(proom->getPlayerCards(pid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg == "叫" || msg == "不叫" || msg == "叫地主")
|
||||||
|
{
|
||||||
|
if (proom->getLandID() != 0)
|
||||||
|
{
|
||||||
|
out << "已经过了争地主的阶段!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (proom->getThisTurn() != pid)
|
||||||
|
{
|
||||||
|
out << "还没轮到你哦!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (proom->isColledLand())
|
||||||
|
{
|
||||||
|
out << "现在是抢地主的阶段!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg == "叫" || msg == "叫地主")
|
||||||
|
{
|
||||||
|
proom->coll(true);
|
||||||
|
broadcast(pid, "玩家["+pplayer->getName()+"]叫地主");
|
||||||
|
|
||||||
|
if (proom->getLandID() == pid)
|
||||||
|
{
|
||||||
|
becomeLandlord(proom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NotifyNextPlayer(rid, "是否抢地主 [抢地主] [不抢]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]抢地主");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!proom->coll(false)) // 如果返回假表示没人叫地主,自动重开游戏
|
||||||
|
{
|
||||||
|
broadcast(rid, "所有人都没叫地主,本局重开");
|
||||||
|
// 给所有玩家看牌
|
||||||
|
for (auto pid : proom->getPlayerIDList())
|
||||||
|
CQ_sendPrivateMsg(ac, PIDToQQ(pid), CardsToString(proom->getPlayerCards(pid)).c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "你不叫地主";
|
||||||
|
broadcast(pid, "玩家[" + pplayer->getName() + "]不叫地主");
|
||||||
|
}
|
||||||
|
NotifyNextPlayer(rid, "是否叫地主 [叫地主] [不叫]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]叫地主");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "抢" || msg == "不抢"
|
||||||
|
|| msg == "我抢" || msg == "抢地主")
|
||||||
|
{
|
||||||
|
if (proom->getLandID() != 0)
|
||||||
|
{
|
||||||
|
out << "已经过了争地主的阶段!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (proom->getThisTurn() != pid)
|
||||||
|
{
|
||||||
|
out << "还没轮到你哦!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!proom->isColledLand())
|
||||||
|
{
|
||||||
|
out << "现在是叫地主的阶段!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg == "抢" || msg == "我抢" || msg == "抢地主")
|
||||||
|
{
|
||||||
|
broadcast(pid, "玩家[" + pplayer->getName() + "]抢地主");
|
||||||
|
if (proom->grab(true))
|
||||||
|
{
|
||||||
|
becomeLandlord(proom);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NotifyNextPlayer(rid, "是否抢地主 [抢地主] [不抢]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]抢地主");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
broadcast(pid, "玩家[" + pplayer->getName() + "]不抢地主");
|
||||||
|
if (proom->grab(false))
|
||||||
|
{
|
||||||
|
becomeLandlord(proom);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NotifyNextPlayer(rid, "是否抢地主 [抢地主] [不抢]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]抢地主");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg.substr(0, 2) == "出")
|
||||||
|
{
|
||||||
|
if (proom->getLandID() == 0)
|
||||||
|
{
|
||||||
|
out << "现在还是争地主的阶段!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (proom->getThisTurn() != pid)
|
||||||
|
{
|
||||||
|
out << "还没轮到你哦!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vector<card_t> vec = StringToCards(msg.substr(2));
|
||||||
|
PlayingCards pc(vec);
|
||||||
|
logFile << CardsToString(vec) << std::endl;
|
||||||
|
if (pc.getType() == c0)
|
||||||
|
{
|
||||||
|
out << "你出的牌不符合规则!";
|
||||||
|
}
|
||||||
|
if (proom->popCards(pc))
|
||||||
|
{
|
||||||
|
ostringstream outTemp;
|
||||||
|
outTemp << "玩家[";
|
||||||
|
outTemp << pplayer->getName();
|
||||||
|
outTemp << "]打出了[";
|
||||||
|
outTemp << CardTtypeToString(pc.getType());
|
||||||
|
outTemp << "]\n";
|
||||||
|
outTemp << CardsToString(vec);
|
||||||
|
broadcast(rid, outTemp.str());
|
||||||
|
outTemp.str("");
|
||||||
|
if (proom->isEndGame())
|
||||||
|
{
|
||||||
|
outTemp << "游戏结束!" << std::endl;;
|
||||||
|
if (pplayer->getID() == proom->getLandID())
|
||||||
|
outTemp << "地主胜利!" << std::endl;
|
||||||
|
else
|
||||||
|
outTemp << "农民胜利!" << std::endl;
|
||||||
|
for (auto pid : proom->getPlayerIDList())
|
||||||
|
{
|
||||||
|
int score = proom->settle(pid);
|
||||||
|
Player *pPlayerTemp = server().getPlayer(pid);
|
||||||
|
pPlayerTemp->score(score);
|
||||||
|
outTemp << "玩家[" << pPlayerTemp->getName() << "] 得分:" << score << std::endl;
|
||||||
|
}
|
||||||
|
outTemp << "发送 查看房间 来查看当前房间情况\n发送 查看 来查看当前个人信息";
|
||||||
|
broadcast(rid, outTemp.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proom->isPopCards())
|
||||||
|
NotifyNextPlayer(rid, "请出牌 [出 xxx]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]出牌");
|
||||||
|
else
|
||||||
|
NotifyNextPlayer(rid, "请出牌 [出 xxx] [不出]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]出牌");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "你出的牌没有上家大!上家出的牌:\n";
|
||||||
|
out << CardsToString(proom->getLastRoundCards());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg == "不出" || msg == "不要" || msg == "要不起")
|
||||||
|
{
|
||||||
|
if (proom->getLandID() == 0)
|
||||||
|
{
|
||||||
|
out << "现在还是争地主的阶段!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (proom->getThisTurn() != pid)
|
||||||
|
{
|
||||||
|
out << "还没轮到你哦!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (proom->pass())
|
||||||
|
{
|
||||||
|
broadcast(rid, "玩家[" + pplayer->getName() + "]不出");
|
||||||
|
if (proom->isPopCards())
|
||||||
|
NotifyNextPlayer(rid, "请出牌 [出 xxx]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]出牌");
|
||||||
|
else
|
||||||
|
NotifyNextPlayer(rid, "请出牌 [出 xxx] [不出]", "等待[" + server().getPlayer(proom->getThisTurn())->getName() + "]出牌");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "现在是出牌阶段,无法pass,请出牌!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (msg == "强制重开")
|
||||||
|
{
|
||||||
|
logFile << "强制重开游戏";
|
||||||
|
broadcast(rid, "强制重开游戏,发送 看牌 查看手牌");
|
||||||
|
proom->start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = "玩家[" + pplayer->getName() + "]说:" + msg;
|
||||||
|
broadcast(rid, msg.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}while(0);/************** do while 块 方便跳出 ****************/
|
||||||
|
CQ_sendPrivateMsg(ac, fromQQ, out.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receive(uint64_t fromQQ, string msg)
|
||||||
|
{
|
||||||
|
ostringstream out;
|
||||||
|
playerID_t pid = QQToPID(fromQQ);
|
||||||
|
Player *pplayer = server().getPlayer(pid);
|
||||||
|
if (msg.substr(0, 4) == "注册" && pplayer == nullptr)
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
istringstream in(msg.substr(4));
|
||||||
|
in >> name;
|
||||||
|
Player temp(pid);
|
||||||
|
temp.setName(name.substr(0, 12));
|
||||||
|
if (server().loginPlayer(temp))
|
||||||
|
{
|
||||||
|
out << "注册成功!昵称:" << name << std::endl;
|
||||||
|
out << "发送 菜单 来得到指令列表";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "注册失败!";
|
||||||
|
}
|
||||||
|
CQ_sendPrivateMsg(ac, fromQQ, out.str().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pplayer == nullptr)
|
||||||
|
{
|
||||||
|
out << "当前QQ未注册,请回复 注册 昵称 来完成注册!" << std::endl;
|
||||||
|
out << "例子:注册 隔壁老王" << std::endl;
|
||||||
|
out << "请注意,昵称最长6个汉字或者12个字母,注册后面跟名字,名字中不允许有空格";
|
||||||
|
CQ_sendPrivateMsg(ac, fromQQ, out.str().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Room *proom = server().getRoom(pplayer->getCurrRoom());
|
||||||
|
if (msg == "菜单")
|
||||||
|
{
|
||||||
|
out <<
|
||||||
|
"+--------指令列表--------+\n"
|
||||||
|
"| 菜单 -- 输出指令列表 |\n"
|
||||||
|
"| 注册 -- 注册 昵称 |\n"
|
||||||
|
"| 改名 -- 改名 新昵称 |\n"
|
||||||
|
"| 查看 -- 查看当前信息 |\n"
|
||||||
|
"| 更新内容 -- 尾更新内容 |\n"
|
||||||
|
"| [消息] -- 在房间中聊天 |\n"
|
||||||
|
"|---- 大厅指令 ----|\n"
|
||||||
|
"|准备 -- 若已准备,则取消|\n"
|
||||||
|
"|创建房间 -- 创建一个房间|\n"
|
||||||
|
"|加入[id] -- 加入指定房间|\n"
|
||||||
|
"|退出房间 -- 退出当前房间|\n"
|
||||||
|
"|查看房间 -- 查看当前房间|\n"
|
||||||
|
"|房间列表 -- 查看所有房间|\n"
|
||||||
|
"|玩家列表 -- 查看所有玩家|\n"
|
||||||
|
"|*注意大厅指令游戏中禁用*|\n"
|
||||||
|
"|---- 游戏指令 ----|\n"
|
||||||
|
"|看牌 -- 查看当前牌局情况|\n"
|
||||||
|
"|叫地主/不叫 抢地主/不抢|\n"
|
||||||
|
"|出牌/不出 出 xxxx |\n"
|
||||||
|
"|*注意游戏指令大厅中禁用*|\n"
|
||||||
|
"+--------指令列表--------+";
|
||||||
|
}
|
||||||
|
else if (msg == "查看")
|
||||||
|
{
|
||||||
|
out << playerInfoToString(pid);
|
||||||
|
}
|
||||||
|
else if (msg.substr(0, 4) == "改名")
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
istringstream in(msg.substr(4));
|
||||||
|
in >> name;
|
||||||
|
pplayer->setName(name.substr(0, 12));
|
||||||
|
out << "修改完成,当前昵称:" << name;
|
||||||
|
}
|
||||||
|
else if (msg == "更新内容")
|
||||||
|
{
|
||||||
|
out << "正在做从文件中读更新内容的功能,敬请期待";
|
||||||
|
}
|
||||||
|
else if (proom == nullptr || proom->getStatus() != roomStatus_t::playing)
|
||||||
|
instruction(fromQQ, msg);
|
||||||
|
else if (proom->getStatus() == roomStatus_t::playing)
|
||||||
|
gameCommand(fromQQ, msg);
|
||||||
|
else
|
||||||
|
out << "发送 菜单 来得到指令列表";
|
||||||
|
CQ_sendPrivateMsg(ac, fromQQ, out.str().c_str());
|
||||||
|
}
|
42
Landlords/Process.h
Normal file
42
Landlords/Process.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "cqp.h"
|
||||||
|
#include "Server.h"
|
||||||
|
#include "Room.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
std::string playerInfoToString(Player* pplayer);
|
||||||
|
std::string playerInfoToString(playerID_t pid);
|
||||||
|
std::string playerListToString();
|
||||||
|
std::string roomInfoToString(roomID_t rid);
|
||||||
|
|
||||||
|
std::string roomListToString(bool isHideFull);
|
||||||
|
|
||||||
|
inline playerID_t QQToPID(uint64_t fromQQ);
|
||||||
|
|
||||||
|
inline uint64_t PIDToQQ(playerID_t pid);
|
||||||
|
|
||||||
|
// 广播消息给指定玩家ID的房间(该消息将发送给指定玩家之外所有人)
|
||||||
|
void broadcast(playerID_t pid, const std::string& msg);
|
||||||
|
|
||||||
|
// 广播消息给指定房间ID的房间(该消息将发送给该房间所有人)
|
||||||
|
void broadcast(roomID_t rid, const std::string& msg);
|
||||||
|
|
||||||
|
|
||||||
|
void instruction(uint64_t fromQQ, std::string msg);
|
||||||
|
|
||||||
|
std::string roomCardsToString(roomID_t rid);
|
||||||
|
|
||||||
|
std::string CardToString(card_t card);
|
||||||
|
|
||||||
|
std::string CardsToString(const std::vector<card_t> &cards);
|
||||||
|
void becomeLandlord(Room * proom);
|
||||||
|
|
||||||
|
// 通知该玩家所有人
|
||||||
|
// 参数 msg 是发送给该轮轮到的玩家的消息
|
||||||
|
// 参数 otherMsg 是发送给其它玩家的消息
|
||||||
|
void NotifyNextPlayer(roomID_t rid, std::string msg, std::string otherMsg);
|
||||||
|
void gameCommand(uint64_t fromQQ, std::string msg);
|
||||||
|
|
||||||
|
void Receive(uint64_t fromQQ, std::string msg);
|
352
Landlords/Room.cpp
Normal file
352
Landlords/Room.cpp
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Room.h"
|
||||||
|
|
||||||
|
|
||||||
|
Room::Room(roomID_t rid, playerID_t pid) :
|
||||||
|
m_id(rid), m_roomStatus(roomStatus_t::Waiting), m_PIDList(),
|
||||||
|
m_turn(0), m_landlord(0), m_X(100), m_lastRoundCards(std::vector<card_t>())
|
||||||
|
{
|
||||||
|
logFile << "Room::Room(" << rid << ", " << pid << ")\n";
|
||||||
|
playerJoin(pid);
|
||||||
|
int n = 0;
|
||||||
|
for (int i = 0; i < 52; ++i)
|
||||||
|
{
|
||||||
|
if (i % 4 == 0)
|
||||||
|
++n;
|
||||||
|
m_cards[i] = card_t(n);
|
||||||
|
}
|
||||||
|
m_cards[52] = card_t::_S;
|
||||||
|
m_cards[53] = card_t::_B;
|
||||||
|
}
|
||||||
|
|
||||||
|
Room::~Room()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::playerJoin(playerID_t pid)
|
||||||
|
{
|
||||||
|
//logFile << "玩家ID:<" << pid << ">试图加入房间:" << m_id << std::endl;
|
||||||
|
if (m_PIDList.size() == 3)
|
||||||
|
{
|
||||||
|
logFile << m_id << "房间已满" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_PIDList.push_back(pid);
|
||||||
|
logFile << "玩家ID:<" << pid << ">已经加入房间:" << m_id << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::playerLeave(playerID_t pid)
|
||||||
|
{
|
||||||
|
//logFile << "玩家ID:<" << pid << ">试图离开房间:" << m_id << std::endl;
|
||||||
|
if (m_PIDList.empty())
|
||||||
|
{
|
||||||
|
logFile << "房间为空" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it = std::find(m_PIDList.begin(), m_PIDList.end(), pid);
|
||||||
|
if (it == m_PIDList.end())
|
||||||
|
{
|
||||||
|
logFile << "在该房间找不到这个ID" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_PIDList.erase(it);
|
||||||
|
logFile << "玩家ID:<" << pid << ">已经离开房间:" << m_id << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::start()
|
||||||
|
{
|
||||||
|
m_roomStatus = roomStatus_t::playing;
|
||||||
|
logFile << "房间ID<" << m_id << ">已经开始游戏" << std::endl;
|
||||||
|
m_landlord = -1; // 地主初始化为无
|
||||||
|
m_lastPop = -1;
|
||||||
|
m_first = -1;
|
||||||
|
m_turn = landU(e); // 随机找一个人开始
|
||||||
|
logFile << "随机数:" << m_turn << std::endl;
|
||||||
|
m_multiple = 1;
|
||||||
|
for (int i = 0; i < roomPlayerLimit; ++i)
|
||||||
|
m_Grad[i] = true;
|
||||||
|
Refresh(); // 洗牌
|
||||||
|
distribution(); // 发牌
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<card_t, 3> Room::getLandCards()
|
||||||
|
{
|
||||||
|
// 最后三张是地主牌
|
||||||
|
return std::array<card_t, 3>{m_cards[51], m_cards[52], m_cards[53]};
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<card_t>& Room::getPlayerCards(playerID_t pid)
|
||||||
|
{
|
||||||
|
//logFile << "玩家ID<" << pid << ">尝试得到自己的牌" << std::endl;
|
||||||
|
return m_playerCards[findPlayer(pid)];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Room::getPlayerCardsSize(playerID_t pid)
|
||||||
|
{
|
||||||
|
//logFile << "玩家ID<" << pid << ">尝试得到牌的数量" << std::endl;
|
||||||
|
return m_playerCards[findPlayer(pid)].size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Room::settle(playerID_t pid)
|
||||||
|
{
|
||||||
|
int score = m_X * m_multiple;
|
||||||
|
// 结算分数
|
||||||
|
if (pid == getLandID()) // 如果是地主
|
||||||
|
{
|
||||||
|
score *= 2; // 积分翻倍
|
||||||
|
if (m_turn != m_landlord) // 最后出牌的不是地主
|
||||||
|
score = -score; // 扣分
|
||||||
|
}
|
||||||
|
else { // 不是地主
|
||||||
|
if (m_turn == m_landlord) //最后出牌的是地主
|
||||||
|
score = -score; // 扣分
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Room::findPlayer(playerID_t pid)
|
||||||
|
{
|
||||||
|
//logFile << "ID<" << pid << ">尝试查找在当前房间下标" << std::endl;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < 3; ++i)
|
||||||
|
if (m_PIDList[i] == pid)
|
||||||
|
break;
|
||||||
|
if (i == 3)
|
||||||
|
{
|
||||||
|
logFile << "这个玩家不在这个房间" << std::endl;
|
||||||
|
throw "该玩家不在当前房间";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::setLandlords(int n)
|
||||||
|
{
|
||||||
|
m_lastPop = m_turn = m_landlord = n;
|
||||||
|
logFile << n << "成为地主" << std::endl;
|
||||||
|
// 发地主牌
|
||||||
|
m_playerCards[m_landlord].insert(m_playerCards[m_landlord].end(),
|
||||||
|
m_cards.end() - 3, m_cards.end());
|
||||||
|
// 重新排序
|
||||||
|
std::sort(m_playerCards[m_landlord].begin(), m_playerCards[m_landlord].end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::isSubset(const std::vector<card_t>& sub)
|
||||||
|
{
|
||||||
|
auto & vec = m_playerCards[m_turn];
|
||||||
|
if (sub.size() > vec.size())
|
||||||
|
return false;
|
||||||
|
int arr[16] = { 0 };
|
||||||
|
for (auto i : sub)
|
||||||
|
arr[i]++;
|
||||||
|
for (auto i : vec)
|
||||||
|
arr[i]--;
|
||||||
|
for (auto i : arr)
|
||||||
|
if (i > 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::removeSubset(const std::vector<card_t>& sub)
|
||||||
|
{
|
||||||
|
auto & vec = m_playerCards[m_turn];
|
||||||
|
if (sub.size() > vec.size())
|
||||||
|
return false;
|
||||||
|
int arr[16] = { 0 };
|
||||||
|
for (auto i : sub)
|
||||||
|
arr[i]++;
|
||||||
|
for (auto it = vec.begin(); it != vec.end(); )
|
||||||
|
if (arr[*it]-- > 0)
|
||||||
|
it = vec.erase(it);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::coll(bool isColl)
|
||||||
|
{
|
||||||
|
if (m_first != -1)
|
||||||
|
return true;
|
||||||
|
if (isColl)
|
||||||
|
{
|
||||||
|
logFile << m_turn << " 叫地主" << std::endl;
|
||||||
|
m_lastPop = m_first = m_turn;
|
||||||
|
for (turnNext(); !m_Grad[m_turn]; turnNext())
|
||||||
|
logFile << m_turn << "没资格抢,下一个" << std::endl;
|
||||||
|
logFile << m_turn << "有资格" << std::endl;
|
||||||
|
if (m_first == m_turn)
|
||||||
|
{
|
||||||
|
setLandlords(m_turn);
|
||||||
|
logFile << "最后一个叫,得到地主" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m_Grad[m_turn] = false;
|
||||||
|
logFile << m_turn << "不叫地主,失去抢地主资格" << std::endl;
|
||||||
|
turnNext();
|
||||||
|
if (!m_Grad[m_turn]) // 如果没人有资格叫地主,说明没人叫地主
|
||||||
|
{
|
||||||
|
logFile << "没人叫地主,流局重开" << std::endl;
|
||||||
|
start();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::grab(bool isGrab)
|
||||||
|
{
|
||||||
|
if (m_landlord != -1)
|
||||||
|
return false;
|
||||||
|
if (isGrab)
|
||||||
|
{
|
||||||
|
logFile << m_turn << "抢地主" << std::endl;
|
||||||
|
m_lastPop = m_turn;
|
||||||
|
doubleMultiple();
|
||||||
|
for (turnNext(); !m_Grad[m_turn]; turnNext())
|
||||||
|
logFile << m_turn << "没资格抢,下一个" << std::endl;
|
||||||
|
logFile << m_turn << "有资格" << std::endl;
|
||||||
|
if (m_lastPop == m_turn) // 如果转一圈出来还是这个人,说明这个人是最后一个有资格抢地主的
|
||||||
|
{
|
||||||
|
logFile << m_turn << "成为地主" << std::endl;
|
||||||
|
setLandlords(m_lastPop);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m_Grad[m_lastPop] = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int temp = m_turn;
|
||||||
|
logFile << m_turn << "不抢" << std::endl;
|
||||||
|
for (turnNext(); !m_Grad[m_turn]; turnNext())
|
||||||
|
logFile << m_turn << "没资格抢,下一个" << std::endl;
|
||||||
|
logFile << m_turn << "有资格" << std::endl;
|
||||||
|
|
||||||
|
if (temp == m_turn) // 如果其它人都没资格再抢地主,则给最后抢地主的人地主(不叫 叫 不抢...)
|
||||||
|
{
|
||||||
|
setLandlords(m_lastPop);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果下一个有资格的就是叫地主的,同时他也是最后一个要当地主的,直接成为地主
|
||||||
|
if (m_turn == m_first && m_first == m_lastPop)
|
||||||
|
{
|
||||||
|
logFile << m_turn << "成为地主" << std::endl;
|
||||||
|
setLandlords(m_first);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m_Grad[temp] = false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::popCards(const PlayingCards & cards)
|
||||||
|
{
|
||||||
|
logFile << "出牌 牌型 " << cards.getType() << std::endl;
|
||||||
|
if (cards.getType() == c0)
|
||||||
|
return false;
|
||||||
|
if (!isSubset(cards.getVec()))
|
||||||
|
{
|
||||||
|
logFile << "没这个牌" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 王炸 天王老子对鬼最大
|
||||||
|
if (cards.getType() == c11)
|
||||||
|
{
|
||||||
|
logFile << "王炸" << std::endl;
|
||||||
|
doubleMultiple();
|
||||||
|
}
|
||||||
|
// 出牌阶段 只要 符合牌型的 手里有的 都可以出。
|
||||||
|
else if (isPopCards())
|
||||||
|
{
|
||||||
|
if (cards.getType() == c4) // 如果是炸弹(空炸) 倍数翻倍
|
||||||
|
{
|
||||||
|
logFile << "炸弹" << std::endl;
|
||||||
|
doubleMultiple();
|
||||||
|
}
|
||||||
|
// 其它的都可以出
|
||||||
|
}
|
||||||
|
// 否则就是上牌阶段
|
||||||
|
else if (cards.getType() == c4) // 炸弹
|
||||||
|
{
|
||||||
|
if (!(m_lastRoundCards < cards))// 没上家大
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 排除了炸弹和王炸后,如果牌型不同直接返回假
|
||||||
|
else if (cards.getType() != m_lastRoundCards.getType())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 排除了牌型不同后,若牌数量不同,一样返回假
|
||||||
|
else if (cards.getSize() != m_lastRoundCards.getSize())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 最后,如果牌型相同,数量相同,但大不过上家,一样返回假
|
||||||
|
else if (!(m_lastRoundCards < cards))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 最后的最后,牌肯定是得出出去的
|
||||||
|
m_lastPop = m_turn;
|
||||||
|
m_lastRoundCards = cards;
|
||||||
|
removeSubset(cards.getVec());
|
||||||
|
logFile << "出牌成功" << std::endl;
|
||||||
|
|
||||||
|
if (m_playerCards[m_turn].empty())
|
||||||
|
{
|
||||||
|
endGame();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cards.getType() != c11) // 如果是王炸,也不用轮到下家了
|
||||||
|
turnNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Room::pass()
|
||||||
|
{
|
||||||
|
logFile << "不出" << std::endl;
|
||||||
|
// 该轮为出牌阶段 无法不出
|
||||||
|
if (m_turn == m_lastPop) // 最后一个出牌的就是这个人
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
turnNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::Refresh()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 54; ++i)
|
||||||
|
std::swap(m_cards[i], m_cards[cardsU(e)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::distribution()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_playerCards.size(); ++i)
|
||||||
|
{
|
||||||
|
m_playerCards[i].clear();
|
||||||
|
m_playerCards[i].insert(m_playerCards[i].begin(),
|
||||||
|
m_cards.begin() + (i * 17), m_cards.begin() + ((i + 1) * 17));
|
||||||
|
std::sort(m_playerCards[i].begin(), m_playerCards[i].end());
|
||||||
|
logFile << i << "号玩家得到了:";
|
||||||
|
for (auto n : m_playerCards[i])
|
||||||
|
logFile << n << ' ';
|
||||||
|
logFile << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::endGame()
|
||||||
|
{
|
||||||
|
m_roomStatus = roomStatus_t::Waiting;
|
||||||
|
|
||||||
|
for (auto pid : m_PIDList)
|
||||||
|
{
|
||||||
|
server().playerReady(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
115
Landlords/Room.h
Normal file
115
Landlords/Room.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "define.h"
|
||||||
|
#include "Server.h"
|
||||||
|
#include "PlayingCards.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
enum roomStatus_t :char {
|
||||||
|
Waiting,
|
||||||
|
playing
|
||||||
|
};
|
||||||
|
|
||||||
|
const int roomPlayerLimit = 3;
|
||||||
|
|
||||||
|
class Room
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Room() = delete;
|
||||||
|
Room(roomID_t rid, playerID_t pid);
|
||||||
|
~Room();
|
||||||
|
|
||||||
|
roomID_t getID() const { return m_id; };
|
||||||
|
roomStatus_t getStatus() const { return m_roomStatus; }
|
||||||
|
const std::vector<playerID_t>& getPlayerIDList() const { return m_PIDList; }
|
||||||
|
size_t getSize() const { return m_PIDList.size(); }
|
||||||
|
// void setStatus(roomStatus_t status) { roomStatus = status; }
|
||||||
|
bool full() const { return m_PIDList.size() >= roomPlayerLimit; }
|
||||||
|
public:
|
||||||
|
bool playerJoin(playerID_t pid);
|
||||||
|
bool playerLeave(playerID_t pid);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 开始 进入playing状态
|
||||||
|
void start();
|
||||||
|
/********** 以下操作只有在进入playing状态后才可使用 ************/
|
||||||
|
|
||||||
|
// 得到地主牌
|
||||||
|
std::array<card_t, 3> getLandCards();
|
||||||
|
|
||||||
|
// 地主的ID 如果还没有地主,返回0
|
||||||
|
playerID_t getLandID() { return m_landlord==-1?0:m_PIDList[m_landlord]; }
|
||||||
|
|
||||||
|
// 得到目标玩家的手牌
|
||||||
|
const std::vector<card_t> &getPlayerCards(playerID_t pid);
|
||||||
|
|
||||||
|
// 得到目标玩家的剩余手牌数量
|
||||||
|
size_t getPlayerCardsSize(playerID_t pid);
|
||||||
|
|
||||||
|
// 得到当前轮到的玩家的ID
|
||||||
|
playerID_t getThisTurn() { logFile << "轮到:" << m_turn << std::endl; return m_PIDList.at(m_turn); }
|
||||||
|
|
||||||
|
// 叫地主,该函数返回真表示已经处理,返回假表示流局重开
|
||||||
|
bool coll(bool isColl);
|
||||||
|
// 叫地主了吗
|
||||||
|
bool isColledLand() { return m_first != -1; }
|
||||||
|
// 抢地主,有人成为地主返回真,否则返回假
|
||||||
|
bool grab(bool isGrab);
|
||||||
|
|
||||||
|
// 出牌,参数是出的牌,出牌成功返回真
|
||||||
|
// 若上牌时,牌型不合法或者大不过上家 返回假
|
||||||
|
// 如果出王炸,下轮任然是该玩家出牌
|
||||||
|
// 出牌操作会对参数进行排序
|
||||||
|
bool popCards(const PlayingCards & cards);
|
||||||
|
|
||||||
|
// 注意:出牌阶段无法pass,若这么做返回假
|
||||||
|
bool pass();
|
||||||
|
|
||||||
|
// 得到最后一轮手牌
|
||||||
|
const std::vector<card_t> & getLastRoundCards() { return m_lastRoundCards.getVec(); }
|
||||||
|
|
||||||
|
// 是否出牌阶段(非上牌阶段)
|
||||||
|
bool isPopCards() { return m_turn == m_lastPop; }
|
||||||
|
|
||||||
|
// 是否游戏已经结束
|
||||||
|
bool isEndGame() { return m_roomStatus == roomStatus_t::Waiting; }
|
||||||
|
// 结算分数 返回得分
|
||||||
|
int settle(playerID_t pid);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool operator==(roomID_t rid) { return m_id == rid; }
|
||||||
|
private:
|
||||||
|
int findPlayer(playerID_t pid);
|
||||||
|
void doubleMultiple() { m_multiple *= 2; }
|
||||||
|
void turnNext() { ++m_turn %= m_PIDList.size(); }
|
||||||
|
void setLandlords(int n);
|
||||||
|
bool isSubset(const std::vector<card_t> &sub);
|
||||||
|
bool removeSubset(const std::vector<card_t> &sub);
|
||||||
|
|
||||||
|
void Refresh();
|
||||||
|
void distribution();
|
||||||
|
|
||||||
|
|
||||||
|
// 游戏结束,进入等待状态,清理
|
||||||
|
void endGame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
roomID_t m_id;
|
||||||
|
roomStatus_t m_roomStatus;
|
||||||
|
std::vector<playerID_t> m_PIDList;
|
||||||
|
std::array<card_t, 54> m_cards;
|
||||||
|
std::array<std::vector<card_t>, roomPlayerLimit> m_playerCards;
|
||||||
|
PlayingCards m_lastRoundCards; // 最后一轮牌
|
||||||
|
/*********************************************************/
|
||||||
|
int m_first; // 第一个叫地主的玩家
|
||||||
|
bool m_Grad[roomPlayerLimit]; // 抢地主资格
|
||||||
|
/*********************************************************/
|
||||||
|
int m_lastPop; // 最后一个出牌/抢地主的玩家
|
||||||
|
int m_turn; // 当前轮到的玩家
|
||||||
|
int m_landlord; // 地主
|
||||||
|
int m_X; // 房间系数 得分公式 X * m (地主*2)
|
||||||
|
uint32_t m_multiple; // 倍数
|
||||||
|
};
|
||||||
|
|
284
Landlords/Server.cpp
Normal file
284
Landlords/Server.cpp
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Server.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
std::default_random_engine e;
|
||||||
|
std::uniform_int_distribution<int> landU(0, 2); // 选地主
|
||||||
|
|
||||||
|
std::uniform_int_distribution<int> cardsU(0, 53); // 洗牌
|
||||||
|
|
||||||
|
|
||||||
|
Server::Server()
|
||||||
|
{
|
||||||
|
logFile << "Server::Server()" << std::endl;
|
||||||
|
std::ifstream fin("data.dat");
|
||||||
|
if (!fin.is_open())
|
||||||
|
{
|
||||||
|
logFile << "data.dat 文件打开失败" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string str;
|
||||||
|
playerID_t pid;
|
||||||
|
std::string name;
|
||||||
|
int integral = 0;
|
||||||
|
while (fin.good() && std::getline(fin, str))
|
||||||
|
{
|
||||||
|
std::istringstream sin(str);
|
||||||
|
sin >> pid >> name >> integral;
|
||||||
|
m_playerList.emplace_back(pid);
|
||||||
|
m_playerList.back().setName(name);
|
||||||
|
m_playerList.back().setIntegral(integral);
|
||||||
|
}
|
||||||
|
fin.close();
|
||||||
|
|
||||||
|
std::random_device rd;
|
||||||
|
e.seed(rd());
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Server::~Server()
|
||||||
|
{
|
||||||
|
if (m_playerList.empty())
|
||||||
|
return;
|
||||||
|
std::ofstream fout("data.dat");
|
||||||
|
if (!fout.is_open())
|
||||||
|
{
|
||||||
|
logFile << "data.dat 文件打开失败" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto i : m_playerList)
|
||||||
|
{
|
||||||
|
fout << i.getID() << '\t' << i.getName() << '\t' << i.getIntegral() << std::endl;
|
||||||
|
}
|
||||||
|
fout.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Room * Server::getRoom(roomID_t rid)
|
||||||
|
{
|
||||||
|
if (m_roomList.empty())
|
||||||
|
return nullptr;
|
||||||
|
/*
|
||||||
|
auto it = m_roomList.begin();
|
||||||
|
for (; it != m_roomList.end(); ++it)
|
||||||
|
if (it->getID() == rid)
|
||||||
|
break;
|
||||||
|
if (it == m_roomList.end())
|
||||||
|
return nullptr;
|
||||||
|
else
|
||||||
|
return &(*it);
|
||||||
|
*/
|
||||||
|
// 由于该方法反复调用,并且房间列表确定已排序,所以采用二分搜索算法提高效率
|
||||||
|
int left = 0;
|
||||||
|
int right = m_roomList.size() - 1;
|
||||||
|
while (left <= right)
|
||||||
|
{
|
||||||
|
int mid = left + ((right - left) >> 1);
|
||||||
|
if (m_roomList[mid].getID() == rid)
|
||||||
|
return &m_roomList[mid];
|
||||||
|
else if (m_roomList[mid].getID() > rid)
|
||||||
|
right = mid - 1;
|
||||||
|
else
|
||||||
|
left = mid + 1;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player * Server::getPlayer(playerID_t pid)
|
||||||
|
{
|
||||||
|
if (m_playerList.empty())
|
||||||
|
return nullptr;
|
||||||
|
/*
|
||||||
|
auto it = m_playerList.begin();
|
||||||
|
for (; it != m_playerList.end(); ++it)
|
||||||
|
if (it->getID() == pid)
|
||||||
|
break;
|
||||||
|
if (it == m_playerList.end())
|
||||||
|
return nullptr;
|
||||||
|
else
|
||||||
|
return &(*it);
|
||||||
|
*/
|
||||||
|
// 由于该方法反复调用,并且房间列表确定已排序,所以采用二分搜索算法提高效率
|
||||||
|
int left = 0;
|
||||||
|
int right = m_playerList.size() - 1;
|
||||||
|
while (left <= right)
|
||||||
|
{
|
||||||
|
int mid = left + ((right - left) >> 1);
|
||||||
|
if (m_playerList[mid].getID() == pid)
|
||||||
|
return &m_playerList[mid];
|
||||||
|
else if (m_playerList[mid].getID() > pid)
|
||||||
|
right = mid - 1;
|
||||||
|
else
|
||||||
|
left = mid + 1;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
roomID_t Server::createRoom(playerID_t pid)
|
||||||
|
{
|
||||||
|
logFile << "玩家id:" << pid << " 试图创建房间" << std::endl;
|
||||||
|
Player *pplayer = getPlayer(pid);
|
||||||
|
if (pplayer->getCurrRoom() != 0)
|
||||||
|
{
|
||||||
|
logFile << "创建房间失败,因为该玩家正在房间中" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
roomID_t rid = 0;
|
||||||
|
if (m_roomList.empty())
|
||||||
|
rid = 1;
|
||||||
|
else
|
||||||
|
rid = m_roomList.back().getID() + 1;
|
||||||
|
m_roomList.push_back(Room(rid, pid));
|
||||||
|
pplayer->setCurrRoom(rid);
|
||||||
|
logFile << "玩家id:" << pid << " 创建房间成功,房间id:" << rid << std::endl;
|
||||||
|
return rid;
|
||||||
|
}
|
||||||
|
|
||||||
|
playerID_t Server::loginPlayer(Player player)
|
||||||
|
{
|
||||||
|
logFile << "玩家id:" << player.getID() << "尝试注册" << std::endl;
|
||||||
|
Player * pplayer = getPlayer(player.getID());
|
||||||
|
if (pplayer != nullptr)
|
||||||
|
{
|
||||||
|
logFile << "已有该玩家信息,无法重复注册" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
m_playerList.push_back(player);
|
||||||
|
std::sort(m_playerList.begin(), m_playerList.end());
|
||||||
|
return player.getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::joinRoom(playerID_t pid, roomID_t rid)
|
||||||
|
{
|
||||||
|
logFile << "玩家id:" << pid << " 尝试加入房间,房间id:" << rid << std::endl;
|
||||||
|
if (rid == 0)
|
||||||
|
{
|
||||||
|
logFile << "房间ID非法" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Player *pplayer = getPlayer(pid);
|
||||||
|
if (pplayer == nullptr)
|
||||||
|
{
|
||||||
|
logFile << "没有这个玩家" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pplayer->getCurrRoom() == rid)
|
||||||
|
{
|
||||||
|
logFile << "该玩家当前已在目标房间" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Room * proom = getRoom(rid);
|
||||||
|
if (proom == nullptr)
|
||||||
|
{
|
||||||
|
logFile << "找不到该房间" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 若玩家已在房间,则先退出当前房间
|
||||||
|
if (pplayer->getCurrRoom() != 0)
|
||||||
|
leaveRoom(pid);
|
||||||
|
if (proom->playerJoin(pid))
|
||||||
|
{
|
||||||
|
pplayer->setCurrRoom(rid);
|
||||||
|
pplayer->isReady = false;
|
||||||
|
logFile << "玩家id:" << pid << "成功加入房间:" << rid << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::leaveRoom(playerID_t pid)
|
||||||
|
{
|
||||||
|
logFile << "玩家id:" << pid << " 尝试退出当前房间" << std::endl;
|
||||||
|
Player * pplayer = getPlayer(pid);
|
||||||
|
if (pplayer == nullptr)
|
||||||
|
{
|
||||||
|
logFile << "没有这个玩家" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
if (rid == 0)
|
||||||
|
{
|
||||||
|
logFile << "这个玩家没有加入任何房间,无法退出" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it = std::find(m_roomList.begin(), m_roomList.end(), rid);
|
||||||
|
if (it->playerLeave(pid))
|
||||||
|
{
|
||||||
|
pplayer->setCurrRoom(0);
|
||||||
|
pplayer->isReady = false;
|
||||||
|
logFile << "玩家id:" << pid << " 已经退出当前房间,房间ID:" << rid << std::endl;
|
||||||
|
if (it->getPlayerIDList().empty())
|
||||||
|
{
|
||||||
|
logFile << "当前房间为空,删除该房间 id:" << rid << std::endl;
|
||||||
|
m_roomList.erase(it);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::playerReady(playerID_t pid)
|
||||||
|
{
|
||||||
|
Player *pplayer = getPlayer(pid);
|
||||||
|
roomID_t rid = pplayer->getCurrRoom();
|
||||||
|
logFile << "玩家id:" << pid << "尝试准备/取消准备" << std::endl;
|
||||||
|
if (pplayer == nullptr || rid == 0)
|
||||||
|
{
|
||||||
|
logFile << "无该玩家或者房间为空" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pplayer->isReady = !pplayer->isReady;
|
||||||
|
logFile << "设置成功,pplayer->isReady:" << pplayer->isReady << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::startGame(roomID_t rid)
|
||||||
|
{
|
||||||
|
Room *proom = getRoom(rid);
|
||||||
|
if (isRoomAllReady(proom))
|
||||||
|
{
|
||||||
|
proom->start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::isRoomAllReady(Room* proom)
|
||||||
|
{
|
||||||
|
if (proom == nullptr || !proom->full())
|
||||||
|
return false;
|
||||||
|
bool flag = true;
|
||||||
|
for (auto i : proom->getPlayerIDList())
|
||||||
|
{
|
||||||
|
// 若有人未准备则置flag为false
|
||||||
|
if (!getPlayer(i)->isReady)
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
// 若标识位未被置假表示所有人都已经准备
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
logFile << "房间id:" << proom->getID() << " 所有人已经准备" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Server & server()
|
||||||
|
{
|
||||||
|
static Server s;
|
||||||
|
return s;
|
||||||
|
}
|
40
Landlords/Server.h
Normal file
40
Landlords/Server.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "Player.h"
|
||||||
|
#include "Room.h"
|
||||||
|
class Room;
|
||||||
|
class Server
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Server();
|
||||||
|
~Server();
|
||||||
|
|
||||||
|
Room * getRoom(roomID_t rid);
|
||||||
|
Player * getPlayer(playerID_t pid);
|
||||||
|
|
||||||
|
roomID_t createRoom(playerID_t pid);
|
||||||
|
playerID_t loginPlayer(Player player);
|
||||||
|
bool joinRoom(playerID_t pid, roomID_t rid);
|
||||||
|
bool leaveRoom(playerID_t pid);
|
||||||
|
|
||||||
|
const std::vector<Room> & getRoomList() { return m_roomList; }
|
||||||
|
const std::vector<Player> & getPlayerList() { return m_playerList; }
|
||||||
|
|
||||||
|
// 若未在房间,返回假。若已经准备,则取消准备,若未准备,则准备
|
||||||
|
bool playerReady(playerID_t pid);
|
||||||
|
|
||||||
|
bool startGame(roomID_t rid);
|
||||||
|
private:
|
||||||
|
// 房间是否所有人都准备
|
||||||
|
bool isRoomAllReady(Room* proom);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Player> m_playerList;
|
||||||
|
std::vector<Room> m_roomList;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server &server(); // 单例
|
196
Landlords/appmain.cpp
Normal file
196
Landlords/appmain.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* CoolQ Demo for VC++
|
||||||
|
* Api Version 9
|
||||||
|
* Written by Coxxs & Thanks for the help of orzFly
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "string"
|
||||||
|
#include "cqp.h"
|
||||||
|
#include "appmain.h" //应用AppID等信息,请正确填写,否则酷Q可能无法加载
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int ac = -1; //AuthCode 调用酷Q的方法时需要用到
|
||||||
|
bool enabled = false;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 返回应用的ApiVer、Appid,打包后将不会调用
|
||||||
|
*/
|
||||||
|
CQEVENT(const char*, AppInfo, 0)() {
|
||||||
|
return CQAPPINFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 接收应用AuthCode,酷Q读取应用信息后,如果接受该应用,将会调用这个函数并传递AuthCode。
|
||||||
|
* 不要在本函数处理其他任何代码,以免发生异常情况。如需执行初始化代码请在Startup事件中执行(Type=1001)。
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, Initialize, 4)(int32_t AuthCode) {
|
||||||
|
ac = AuthCode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=1001 酷Q启动
|
||||||
|
* 无论本应用是否被启用,本函数都会在酷Q启动后执行一次,请在这里执行应用初始化代码。
|
||||||
|
* 如非必要,不建议在这里加载窗口。(可以添加菜单,让用户手动打开窗口)
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventStartup, 0)() {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=1002 酷Q退出
|
||||||
|
* 无论本应用是否被启用,本函数都会在酷Q退出前执行一次,请在这里执行插件关闭代码。
|
||||||
|
* 本函数调用完毕后,酷Q将很快关闭,请不要再通过线程等方式执行其他代码。
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventExit, 0)() {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=1003 应用已被启用
|
||||||
|
* 当应用被启用后,将收到此事件。
|
||||||
|
* 如果酷Q载入时应用已被启用,则在_eventStartup(Type=1001,酷Q启动)被调用后,本函数也将被调用一次。
|
||||||
|
* 如非必要,不建议在这里加载窗口。(可以添加菜单,让用户手动打开窗口)
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventEnable, 0)() {
|
||||||
|
enabled = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=1004 应用将被停用
|
||||||
|
* 当应用被停用前,将收到此事件。
|
||||||
|
* 如果酷Q载入时应用已被停用,则本函数*不会*被调用。
|
||||||
|
* 无论本应用是否被启用,酷Q关闭前本函数都*不会*被调用。
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventDisable, 0)() {
|
||||||
|
enabled = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=21 私聊消息
|
||||||
|
* subType 子类型,11/来自好友 1/来自在线状态 2/来自群 3/来自讨论组
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventPrivateMsg, 24)(int32_t subType, int32_t msgId, int64_t fromQQ, const char *msg, int32_t font) {
|
||||||
|
|
||||||
|
//如果要回复消息,请调用酷Q方法发送,并且这里 return EVENT_BLOCK - 截断本条消息,不再继续处理 注意:应用优先级设置为"最高"(10000)时,不得使用本返回值
|
||||||
|
//如果不回复消息,交由之后的应用/过滤器处理,这里 return EVENT_IGNORE - 忽略本条消息
|
||||||
|
return EVENT_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=2 群消息
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventGroupMsg, 36)(int32_t subType, int32_t msgId, int64_t fromGroup, int64_t fromQQ, const char *fromAnonymous, const char *msg, int32_t font) {
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=4 讨论组消息
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventDiscussMsg, 32)(int32_t subType, int32_t msgId, int64_t fromDiscuss, int64_t fromQQ, const char *msg, int32_t font) {
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=101 群事件-管理员变动
|
||||||
|
* subType 子类型,1/被取消管理员 2/被设置管理员
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventSystem_GroupAdmin, 24)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t beingOperateQQ) {
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=102 群事件-群成员减少
|
||||||
|
* subType 子类型,1/群员离开 2/群员被踢 3/自己(即登录号)被踢
|
||||||
|
* fromQQ 操作者QQ(仅subType为2、3时存在)
|
||||||
|
* beingOperateQQ 被操作QQ
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventSystem_GroupMemberDecrease, 32)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, int64_t beingOperateQQ) {
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=103 群事件-群成员增加
|
||||||
|
* subType 子类型,1/管理员已同意 2/管理员邀请
|
||||||
|
* fromQQ 操作者QQ(即管理员QQ)
|
||||||
|
* beingOperateQQ 被操作QQ(即加群的QQ)
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventSystem_GroupMemberIncrease, 32)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, int64_t beingOperateQQ) {
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=201 好友事件-好友已添加
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventFriend_Add, 16)(int32_t subType, int32_t sendTime, int64_t fromQQ) {
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=301 请求-好友添加
|
||||||
|
* msg 附言
|
||||||
|
* responseFlag 反馈标识(处理请求用)
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventRequest_AddFriend, 24)(int32_t subType, int32_t sendTime, int64_t fromQQ, const char *msg, const char *responseFlag) {
|
||||||
|
|
||||||
|
//CQ_setFriendAddRequest(ac, responseFlag, REQUEST_ALLOW, "");
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type=302 请求-群添加
|
||||||
|
* subType 子类型,1/他人申请入群 2/自己(即登录号)受邀入群
|
||||||
|
* msg 附言
|
||||||
|
* responseFlag 反馈标识(处理请求用)
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __eventRequest_AddGroup, 32)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, const char *msg, const char *responseFlag) {
|
||||||
|
|
||||||
|
//if (subType == 1) {
|
||||||
|
// CQ_setGroupAddRequestV2(ac, responseFlag, REQUEST_GROUPADD, REQUEST_ALLOW, "");
|
||||||
|
//} else if (subType == 2) {
|
||||||
|
// CQ_setGroupAddRequestV2(ac, responseFlag, REQUEST_GROUPINVITE, REQUEST_ALLOW, "");
|
||||||
|
//}
|
||||||
|
|
||||||
|
return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 菜单,可在 .json 文件中设置菜单数目、函数名
|
||||||
|
* 如果不使用菜单,请在 .json 及此处删除无用菜单
|
||||||
|
*/
|
||||||
|
CQEVENT(int32_t, __menuA, 0)() {
|
||||||
|
MessageBoxA(NULL, "这是menuA,在这里载入窗口,或者进行其他工作。", "" ,0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CQEVENT(int32_t, __menuB, 0)() {
|
||||||
|
MessageBoxA(NULL, "这是menuB,在这里载入窗口,或者进行其他工作。", "" ,0);
|
||||||
|
return 0;
|
||||||
|
}
|
2
Landlords/appmain.h
Normal file
2
Landlords/appmain.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#define CQAPPID "com.example.democ" //请修改AppID,规则见 http://d.cqp.me/Pro/开发/基础信息
|
||||||
|
#define CQAPPINFO CQAPIVERTEXT "," CQAPPID
|
226
Landlords/cqp.h
Normal file
226
Landlords/cqp.h
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* CoolQ SDK for VC++
|
||||||
|
* Api Version 9
|
||||||
|
* Written by Coxxs & Thanks for the help of orzFly
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define CQAPIVER 9
|
||||||
|
#define CQAPIVERTEXT "9"
|
||||||
|
|
||||||
|
#ifndef CQAPI
|
||||||
|
#define CQAPI(ReturnType) extern "C" __declspec(dllimport) ReturnType __stdcall
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CQEVENT(ReturnType, Name, Size) __pragma(comment(linker, "/EXPORT:" #Name "=_" #Name "@" #Size))\
|
||||||
|
extern "C" __declspec(dllexport) ReturnType __stdcall Name
|
||||||
|
|
||||||
|
typedef int32_t CQBOOL;
|
||||||
|
|
||||||
|
|
||||||
|
#define EVENT_IGNORE 0 //事件_忽略
|
||||||
|
#define EVENT_BLOCK 1 //事件_拦截
|
||||||
|
|
||||||
|
#define REQUEST_ALLOW 1 //请求_通过
|
||||||
|
#define REQUEST_DENY 2 //请求_拒绝
|
||||||
|
|
||||||
|
#define REQUEST_GROUPADD 1 //请求_群添加
|
||||||
|
#define REQUEST_GROUPINVITE 2 //请求_群邀请
|
||||||
|
|
||||||
|
#define CQLOG_DEBUG 0 //调试 灰色
|
||||||
|
#define CQLOG_INFO 10 //信息 黑色
|
||||||
|
#define CQLOG_INFOSUCCESS 11 //信息(成功) 紫色
|
||||||
|
#define CQLOG_INFORECV 12 //信息(接收) 蓝色
|
||||||
|
#define CQLOG_INFOSEND 13 //信息(发送) 绿色
|
||||||
|
#define CQLOG_WARNING 20 //警告 橙色
|
||||||
|
#define CQLOG_ERROR 30 //错误 红色
|
||||||
|
#define CQLOG_FATAL 40 //致命错误 深红
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 发送私聊消息, 成功返回消息ID
|
||||||
|
* QQID 目标QQ号
|
||||||
|
* msg 消息内容
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_sendPrivateMsg(int32_t AuthCode, int64_t QQID, const char *msg);
|
||||||
|
/*
|
||||||
|
* 发送群消息, 成功返回消息ID
|
||||||
|
* groupid 群号
|
||||||
|
* msg 消息内容
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_sendGroupMsg(int32_t AuthCode, int64_t groupid, const char *msg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 发送讨论组消息, 成功返回消息ID
|
||||||
|
* discussid 讨论组号
|
||||||
|
* msg 消息内容
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_sendDiscussMsg(int32_t AuthCode, int64_t discussid, const char *msg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 撤回消息
|
||||||
|
* msgid 消息ID
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_deleteMsg(int32_t AuthCode, int64_t msgid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 发送赞 发送手机赞
|
||||||
|
* QQID QQ号
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_sendLike(int32_t AuthCode, int64_t QQID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群员移除
|
||||||
|
* groupid 目标群
|
||||||
|
* QQID QQ号
|
||||||
|
* rejectaddrequest 不再接收此人加群申请,请慎用
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupKick(int32_t AuthCode, int64_t groupid, int64_t QQID, CQBOOL rejectaddrequest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群员禁言
|
||||||
|
* groupid 目标群
|
||||||
|
* QQID QQ号
|
||||||
|
* duration 禁言的时间,单位为秒。如果要解禁,这里填写0。
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupBan(int32_t AuthCode, int64_t groupid, int64_t QQID, int64_t duration);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群管理员
|
||||||
|
* groupid 目标群
|
||||||
|
* QQID QQ号
|
||||||
|
* setadmin true:设置管理员 false:取消管理员
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupAdmin(int32_t AuthCode, int64_t groupid, int64_t QQID, CQBOOL setadmin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置全群禁言
|
||||||
|
* groupid 目标群
|
||||||
|
* enableban true:开启 false:关闭
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupWholeBan(int32_t AuthCode, int64_t groupid, CQBOOL enableban);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置匿名群员禁言
|
||||||
|
* groupid 目标群
|
||||||
|
* anomymous 群消息事件收到的 anomymous 参数
|
||||||
|
* duration 禁言的时间,单位为秒。不支持解禁。
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupAnonymousBan(int32_t AuthCode, int64_t groupid, const char *anomymous, int64_t duration);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群匿名设置
|
||||||
|
* groupid 目标群
|
||||||
|
* enableanomymous true:开启 false:关闭
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupAnonymous(int32_t AuthCode, int64_t groupid, CQBOOL enableanomymous);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群成员名片
|
||||||
|
* groupid 目标群
|
||||||
|
* QQID 目标QQ
|
||||||
|
* newcard 新名片(昵称)
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupCard(int32_t AuthCode, int64_t groupid, int64_t QQID, const char *newcard);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群退出 慎用, 此接口需要严格授权
|
||||||
|
* groupid 目标群
|
||||||
|
* isdismiss 是否解散 true:解散本群(群主) false:退出本群(管理、群成员)
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupLeave(int32_t AuthCode, int64_t groupid, CQBOOL isdismiss);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群成员专属头衔 需群主权限
|
||||||
|
* groupid 目标群
|
||||||
|
* QQID 目标QQ
|
||||||
|
* newspecialtitle 头衔(如果要删除,这里填空)
|
||||||
|
* duration 专属头衔有效期,单位为秒。如果永久有效,这里填写-1。
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupSpecialTitle(int32_t AuthCode, int64_t groupid, int64_t QQID, const char *newspecialtitle, int64_t duration);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置讨论组退出
|
||||||
|
* discussid 目标讨论组号
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setDiscussLeave(int32_t AuthCode, int64_t discussid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置好友添加请求
|
||||||
|
* responseflag 请求事件收到的 responseflag 参数
|
||||||
|
* responseoperation REQUEST_ALLOW 或 REQUEST_DENY
|
||||||
|
* remark 添加后的好友备注
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setFriendAddRequest(int32_t AuthCode, const char *responseflag, int32_t responseoperation, const char *remark);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置群添加请求
|
||||||
|
* responseflag 请求事件收到的 responseflag 参数
|
||||||
|
* requesttype根据请求事件的子类型区分 REQUEST_GROUPADD 或 REQUEST_GROUPINVITE
|
||||||
|
* responseoperation REQUEST_ALLOW 或 REQUEST_DENY
|
||||||
|
* reason 操作理由,仅 REQUEST_GROUPADD 且 REQUEST_DENY 时可用
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setGroupAddRequestV2(int32_t AuthCode, const char *responseflag, int32_t requesttype, int32_t responseoperation, const char *reason);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取群成员信息
|
||||||
|
* groupid 目标QQ所在群
|
||||||
|
* QQID 目标QQ号
|
||||||
|
* nocache 不使用缓存
|
||||||
|
*/
|
||||||
|
CQAPI(const char *) CQ_getGroupMemberInfoV2(int32_t AuthCode, int64_t groupid, int64_t QQID, CQBOOL nocache);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取陌生人信息
|
||||||
|
* QQID 目标QQ
|
||||||
|
* nocache 不使用缓存
|
||||||
|
*/
|
||||||
|
CQAPI(const char *) CQ_getStrangerInfo(int32_t AuthCode, int64_t QQID, CQBOOL nocache);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 日志
|
||||||
|
* priority 优先级,CQLOG 开头的常量
|
||||||
|
* category 类型
|
||||||
|
* content 内容
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_addLog(int32_t AuthCode, int32_t priority, const char *category, const char *content);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取Cookies 慎用, 此接口需要严格授权
|
||||||
|
*/
|
||||||
|
CQAPI(const char *) CQ_getCookies(int32_t AuthCode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取CsrfToken 慎用, 此接口需要严格授权
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_getCsrfToken(int32_t AuthCode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取登录QQ
|
||||||
|
*/
|
||||||
|
CQAPI(int64_t) CQ_getLoginQQ(int32_t AuthCode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取登录QQ昵称
|
||||||
|
*/
|
||||||
|
CQAPI(const char *) CQ_getLoginNick(int32_t AuthCode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 取应用目录,返回的路径末尾带"\"
|
||||||
|
*/
|
||||||
|
CQAPI(const char *) CQ_getAppDirectory(int32_t AuthCode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 置致命错误提示
|
||||||
|
* errorinfo 错误信息
|
||||||
|
*/
|
||||||
|
CQAPI(int32_t) CQ_setFatal(int32_t AuthCode, const char *errorinfo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 接收语音,接收消息中的语音(record),返回保存在 \data\record\ 目录下的文件名
|
||||||
|
* file 收到消息中的语音文件名(file)
|
||||||
|
* outformat 应用所需的语音文件格式,目前支持 mp3 amr wma m4a spx ogg wav flac
|
||||||
|
*/
|
||||||
|
CQAPI(const char *) CQ_getRecord(int32_t AuthCode, const char *file, const char *outformat);
|
34
Landlords/define.h
Normal file
34
Landlords/define.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
using playerID_t = uint64_t;
|
||||||
|
using roomID_t = uint32_t;
|
||||||
|
|
||||||
|
extern std::ofstream logFile;
|
||||||
|
// 随机数发生器
|
||||||
|
extern std::default_random_engine e;
|
||||||
|
// 分布引擎
|
||||||
|
extern std::uniform_int_distribution<int> landU; // 选地主
|
||||||
|
|
||||||
|
extern std::uniform_int_distribution<int> cardsU; // 洗牌
|
||||||
|
|
||||||
|
enum card_t {
|
||||||
|
_3 = 1,
|
||||||
|
_4,
|
||||||
|
_5,
|
||||||
|
_6,
|
||||||
|
_7,
|
||||||
|
_8,
|
||||||
|
_9,
|
||||||
|
_10,
|
||||||
|
_J,
|
||||||
|
_Q,
|
||||||
|
_K,
|
||||||
|
_A,
|
||||||
|
_2,
|
||||||
|
_S,
|
||||||
|
_B
|
||||||
|
};
|
BIN
Landlords/dllmain.cpp
Normal file
BIN
Landlords/dllmain.cpp
Normal file
Binary file not shown.
76
Landlords/me.cqp.jie.landlords.json
Normal file
76
Landlords/me.cqp.jie.landlords.json
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// 打包前,应用的 .dll, .json 的文件名须以appid命名,应用AppInfo返回的内容须改为appid
|
||||||
|
// 如 appid=com.example.democ, 则dll及json文件需分别命名为 com.example.democ.dll、com.example.democ.json
|
||||||
|
{
|
||||||
|
"ret":1, // 返回码,固定为1
|
||||||
|
"apiver":9, // Api版本,本SDK为9
|
||||||
|
"name":"筱傑-斗地主", // 应用名称
|
||||||
|
"version":"1.0.0", // 应用版本
|
||||||
|
"version_id":1, // 应用顺序版本(每次发布时至少+1)
|
||||||
|
"author":"Example", // 应用作者
|
||||||
|
"description":"斗地主 -- 测试版本",
|
||||||
|
"event":[ // 事件列表,同一事件类型可重复定义(发布前请删除无用事件)
|
||||||
|
{
|
||||||
|
"id":1, // 事件ID
|
||||||
|
"type":21, // 事件类型
|
||||||
|
"name":"私聊消息处理", // 事件名称
|
||||||
|
"function":"_eventPrivateMsg", // 事件对应函数
|
||||||
|
"priority":30000 // 事件优先级(参见 cq.im/deveventpriority)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"type":2,
|
||||||
|
"name":"群消息处理",
|
||||||
|
"function":"_eventGroupMsg",
|
||||||
|
"priority":30000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"type":4,
|
||||||
|
"name":"讨论组消息处理",
|
||||||
|
"function":"_eventDiscussMsg",
|
||||||
|
"priority":30000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1001,
|
||||||
|
"type":1001,
|
||||||
|
"name":"酷Q启动事件",
|
||||||
|
"priority":30000,
|
||||||
|
"function":"_eventStartup"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1002,
|
||||||
|
"type":1002,
|
||||||
|
"name":"酷Q关闭事件",
|
||||||
|
"priority":30000,
|
||||||
|
"function":"_eventExit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1003,
|
||||||
|
"type":1003,
|
||||||
|
"name":"应用已被启用",
|
||||||
|
"priority":30000,
|
||||||
|
"function":"_eventEnable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1004,
|
||||||
|
"type":1004,
|
||||||
|
"name":"应用将被停用",
|
||||||
|
"priority":30000,
|
||||||
|
"function":"_eventDisable"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"menu":[ // 设置菜单(发布前请删除无用菜单,如果无需设置菜单请全部删除)
|
||||||
|
{
|
||||||
|
"name":"设置", //菜单名称
|
||||||
|
"function":"_menu" //菜单对应函数
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"status":[ // 悬浮窗状态(见 com.example.status 样例)
|
||||||
|
|
||||||
|
],
|
||||||
|
"auth":[ // 应用权限(发布前请删除无用权限)
|
||||||
|
101, //发送群消息 sendGroupMsg
|
||||||
|
103, //发送讨论组消息 sendDiscussMsg
|
||||||
|
106 //发送私聊消息 sendPrivateMsg
|
||||||
|
]
|
||||||
|
}
|
104
Landlords/recording.txt
Normal file
104
Landlords/recording.txt
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
-------- 开发日记 --------
|
||||||
|
2018/2/24 第一天
|
||||||
|
今天我日常梦游的过程中,突然翻到了远古时期下载的酷Q机器人软件。
|
||||||
|
闲着发慌的心理使我跑到了酷Q官网,我下载了最新版的酷Q Air,同时得到了一份SDK。
|
||||||
|
然后我就开始了在这个SDK之上编写程序的时光
|
||||||
|
|
||||||
|
上午,我突然想利用这个SDK来写一个游戏,我上网搜了许久,发现适合QQ这种聊天对话的游戏有是有,但别人写的已经够多了。
|
||||||
|
我就在想,能不能写一个比较少人写的游戏,或者是别人没有写过的。
|
||||||
|
突然,我想到我要写一个棋牌类的游戏,我翻了一下,很少有人这么干。
|
||||||
|
所以,我决定做一个斗地主游戏
|
||||||
|
|
||||||
|
下定决心后,我开始做设计文档,其中与 夏 沟通了需求,并答应他参与开发
|
||||||
|
设计文档写了差不多后,我开始建立一个基础的框架,实现了简单的 创建房间加入房间准备等功能
|
||||||
|
可是,不知道出了什么问题,当通过房间查询玩家数据时,数据错误?我不知道。
|
||||||
|
我猜测可能是我的设计有问题。我找了一晚上,未解决问题。
|
||||||
|
去群里请教了许多人,虽然没有解决问题,但是我学了很多设计上的知识
|
||||||
|
我决定重构
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2018/2/25 第二天
|
||||||
|
今天我起床之后,第一件事是打开电脑,然后才是洗漱
|
||||||
|
既然决定重构,我就给之前的项目文件加上了[弃坑]的标签
|
||||||
|
这也是我往常的习惯了。。
|
||||||
|
|
||||||
|
我将之前项目的基础框架给搬了过来,但是整个类都重新实现了一遍
|
||||||
|
这次我采用了ID访问制,所有访问对象的操作必须通过ID来得到该对象。
|
||||||
|
果然,上次的问题不存在了(虽然我也没在这里讲清楚上次发生了什么)
|
||||||
|
|
||||||
|
我花了一天时间,重新实现了基础操作
|
||||||
|
包括 菜单,创建房间,加入房间,退出房间。
|
||||||
|
查看玩家信息,查看房间信息,查看房间列表,查看玩家列表(这个明天做)
|
||||||
|
哦,还有一个注册功能,并且将玩家信息保存到了本地
|
||||||
|
|
||||||
|
2018/2/25 第三天
|
||||||
|
今天是学生们开学的日子,可惜校园时光已经远离我,我也马上要出去找工作了。
|
||||||
|
|
||||||
|
前两篇都是今天写的,今天要实现的内容有
|
||||||
|
实现基本的游戏功能,包括:
|
||||||
|
房间广播
|
||||||
|
准备/取消准备
|
||||||
|
开始游戏(这个是自动的,玩家都准备后自动开始)
|
||||||
|
洗牌发牌
|
||||||
|
叫牌(叫地主)
|
||||||
|
出牌
|
||||||
|
上牌
|
||||||
|
过牌
|
||||||
|
希望能在今天做完,做不完就留到明天吧。。
|
||||||
|
|
||||||
|
查看玩家列表 完成
|
||||||
|
|
||||||
|
房间广播 完成
|
||||||
|
遇到的问题,if (proom = nullptr)
|
||||||
|
谨记!
|
||||||
|
|
||||||
|
开始游戏 完成
|
||||||
|
|
||||||
|
洗牌发牌 完成
|
||||||
|
|
||||||
|
叫牌
|
||||||
|
经过一段时间的思考(水群)
|
||||||
|
我决定做成抢地主的模式
|
||||||
|
当某位玩家叫完地主后,按照次序每位玩家均有且只有一次“抢地主”的机会。
|
||||||
|
玩家选择“抢地主”后,如果没有其他玩家继续“抢地主”则地主权利属于该名“抢地主”的玩家。
|
||||||
|
如果没有任何玩家选择“抢地主”,则地主权利属于“叫地主”的玩家。
|
||||||
|
每“抢地主”一次,游戏倍数 *2 。
|
||||||
|
凡是有过“不叫地主”操作的玩家无法进行“抢地主”的操作。
|
||||||
|
|
||||||
|
叫地主抢地主功能BUG多多,明天再想
|
||||||
|
|
||||||
|
|
||||||
|
2018/2/27 第四天
|
||||||
|
|
||||||
|
今天要将叫地主抢地主功能修复,如果时间来得及,就开始写出牌功能
|
||||||
|
|
||||||
|
14:00 大致修复完成
|
||||||
|
|
||||||
|
开始写出牌功能
|
||||||
|
|
||||||
|
牌型识别与大小判断 完成
|
||||||
|
|
||||||
|
出牌/过牌 完成
|
||||||
|
|
||||||
|
2018/2/28 第五天
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
更新内容:
|
||||||
|
新增叫地主指令 "叫"
|
||||||
|
新增抢地主指令 "抢", "我抢"
|
||||||
|
新增发送聊天消息指令 "发" 例子 "发 你倒是快点出牌啊"
|
||||||
|
新增,当玩家出牌时会显示当前手牌
|
||||||
|
|
||||||
|
更新内容:
|
||||||
|
更新 发消息将不再带发字,游戏中直接发送
|
||||||
|
更新 轮到该玩家时才会显示牌
|
||||||
|
新增 发看牌得到牌局情况时,会显示地主与农民
|
||||||
|
|
||||||
|
更新内容:
|
||||||
|
修复 分数结算时消息重复
|
||||||
|
|
||||||
|
更新 在房间中也可以聊天
|
||||||
|
更新 去掉发送消息时返回发送成功的回复
|
||||||
|
更新 菜单内容
|
BIN
Landlords/stdafx.cpp
Normal file
BIN
Landlords/stdafx.cpp
Normal file
Binary file not shown.
BIN
Landlords/stdafx.h
Normal file
BIN
Landlords/stdafx.h
Normal file
Binary file not shown.
BIN
Landlords/targetver.h
Normal file
BIN
Landlords/targetver.h
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user