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:
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
Room.cpp
|
||||
Landlords.vcxproj -> F:\C++\代码\斗地主\Landlords\Debug\me.cqp.jie.landlords.dll
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.16299.0
|
||||
Debug|Win32|F:\C++\代码\斗地主\Landlords\|
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
#define CQAPPID "me.cqp.jie.landlords" //请修改AppID,规则见 http://d.cqp.me/Pro/开发/基础信息
|
||||
#define CQAPPINFO CQAPIVERTEXT "," CQAPPID
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
@@ -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为无)
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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; // 牌的数量
|
||||
};
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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; // 倍数
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(); // 单例
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#define CQAPPID "com.example.democ" //请修改AppID,规则见 http://d.cqp.me/Pro/开发/基础信息
|
||||
#define CQAPPINFO CQAPIVERTEXT "," CQAPPID
|
||||
+226
@@ -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);
|
||||
@@ -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
|
||||
};
|
||||
Binary file not shown.
@@ -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
|
||||
]
|
||||
}
|
||||
@@ -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 第五天
|
||||
|
||||
|
||||
|
||||
更新内容:
|
||||
新增叫地主指令 "叫"
|
||||
新增抢地主指令 "抢", "我抢"
|
||||
新增发送聊天消息指令 "发" 例子 "发 你倒是快点出牌啊"
|
||||
新增,当玩家出牌时会显示当前手牌
|
||||
|
||||
更新内容:
|
||||
更新 发消息将不再带发字,游戏中直接发送
|
||||
更新 轮到该玩家时才会显示牌
|
||||
新增 发看牌得到牌局情况时,会显示地主与农民
|
||||
|
||||
更新内容:
|
||||
修复 分数结算时消息重复
|
||||
|
||||
更新 在房间中也可以聊天
|
||||
更新 去掉发送消息时返回发送成功的回复
|
||||
更新 菜单内容
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user