提交源代码

上次创建Git仓库后忘记上传代码了。。

编译环境 VS2017
需要配合酷Q C++ SDK使用
This commit is contained in:
筱傑 2018-09-24 12:58:40 +08:00 committed by GitHub
parent 2cf768605a
commit 4656410829
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 2839 additions and 0 deletions

BIN
Landlords/CQP.lib Normal file

Binary file not shown.

View File

@ -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.

View File

@ -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.

BIN
Landlords/Debug/Player.obj Normal file

Binary file not shown.

Binary file not shown.

BIN
Landlords/Debug/Process.obj Normal file

Binary file not shown.

BIN
Landlords/Debug/Room.obj Normal file

Binary file not shown.

BIN
Landlords/Debug/Server.obj Normal file

Binary file not shown.

BIN
Landlords/Debug/dllmain.obj Normal file

Binary file not shown.

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Landlords/Debug/stdafx.obj Normal file

Binary file not shown.

BIN
Landlords/Debug/vc141.idb Normal file

Binary file not shown.

BIN
Landlords/Debug/vc141.pdb Normal file

Binary file not shown.

BIN
Landlords/Landlords.cpp Normal file

Binary file not shown.

3
Landlords/Landlords.h Normal file
View 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
View 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
View 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>

View 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>

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
/*
* ApiVerAppid
*/
CQEVENT(const char*, AppInfo, 0)() {
return CQAPPINFO;
}
/*
* AuthCodeQ读取应用信息后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为23)
* 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
View 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
View 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
View 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

Binary file not shown.

View File

@ -0,0 +1,76 @@
// .dll, .json appidAppInfoappid
// appid=com.example.democ, dlljson com.example.democ.dllcom.example.democ.json
{
"ret":1, // 1
"apiver":9, // ApiSDK9
"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
View 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

Binary file not shown.

BIN
Landlords/stdafx.h Normal file

Binary file not shown.

BIN
Landlords/targetver.h Normal file

Binary file not shown.