#include <stdio.h>
#include "gtest/gtest.h"
#include "TestDemo.h"
#include "TestFanShu.h"
int main(int argc, char * argv[])
{
testing::InitGoogleTest(&argc, argv);
RUN_ALL_TESTS();
return 0;
}
#pragma once
int iAdd(int a, int b)
{
return a + b;
}
TEST(TestDemo, iAdd_test)
{
EXPECT_EQ(3, iAdd(1, 2));
}
TEST(TestDemo, cout_test)
{
int ax[3] = { 0, 1, 2 };
int ay[3] = { 0, 2, 2 };
for (int i = 0; i < 3; i++)
{
//补充输出信息
//EXPECT_EQ(ax[i], ay[i]) << "i = " << i;
}
}
#pragma once
#include "public.h"
class CFanShuTest : public testing::Test
{
protected:
virtual void SetUp()
{
oCurRoomRule.set_ding_pai(LZMJ::SAN_YAO_FEI);
oCurRoomRule.set_hei_san_feng(1);
oCurRoomRule.set_zhong_fa_bai(1);
oCurRoomRule.set_jiang_pai(LZMJ::WU_JIANG_PAI);
oGameLogic.vSetDingPaiType(oCurRoomRule.ding_pai());
oGameLogic.m_vInitRoomRule(&oCurRoomRule);
oGameLogic.m_vInitIdentifier("");
oGameLogic.m_vInitLeftCards(&m_oLeftCards);
oGameLogic.vSetDingPaiType(oCurRoomRule.ding_pai());
memset(&stHandCards, 0, sizeof(stHandCards));
}
virtual void TearDown()
{
}
LZMJ::LZMJM_TableRule oCurRoomRule;
CGameLogic oGameLogic;
SHandCards stHandCards;
CLeftCards m_oLeftCards;
};
TEST_F(CFanShuTest, FanShu1)
{
Card aucHandCards[] = {
0x11, 0x11, 0x11,
0x12, 0x13, 0x14,
0x15, 0x15, 0x15,
0x16, 0x17, 0x18,
0x19, 0x19
};
uint8_t ucHandCardsNum = sizeof(aucHandCards) / sizeof(aucHandCards[0]);
vGenHandCards(stHandCards, aucHandCards, ucHandCardsNum);
bool bRet = oGameLogic.m_bHu(stHandCards);
EXPECT_EQ(true, bRet);
EXPECT_EQ(2, oGameLogic.GetFanShu());
}
#ifndef DEFINE_HJ
#define DEFINE_HJ
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define Conn(x, y) x##y //connect x and y
#define ToChar(x) #@x //wrap x with single quote, return char
#define ToString(x) #x //wrap x with double quote, return string
#define MEM_B(x) (*((uint8_t*)(&x)))
#define MEM_W(x) (*((uint16_t*)(&x)))
#define ARR_SIZE(a) (( (sizeof(a)) / (sizeof(a[0])) ))
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif
#include <stdio.h>
#include <iostream>
#include "define.h"
using namespace std;
int main()
{
int n = Conn(123, 456);
char * str = Conn("Hello", "World");
printf("n = %d, str = %s\n", n, str); //n = 123456, str = HelloWorld
char a = ToChar(1);
printf("a = %c\n", a); //a = 1
char * pc = ToString(123321);
printf("pc = %s\n", pc); //pc = 123321
int iNum = 0x123456;
printf("%x %x\n", MEM_B(iNum), MEM_W(iNum)); //56 3456
printf("%s %d %s %s %s\n", __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__);
return 0;
}
RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format
JavaScript Object Notation (JSON) is a text format for the serialization of structured data. It is derived from the object literals of JavaScript, as defined in the ECMAScript Programming Language Standard, Third Edition [ECMA-262].
JSON can represent four primitive types (strings, numbers, booleans, and null) and two structured types (objects and arrays).
A string is a sequence of zero or more Unicode characters [UNICODE]. Note that this citation references the latest version of Unicode rather than a specific release. It is not expected that future changes in the UNICODE specification will impact the syntax of JSON.
An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.
An array is an ordered sequence of zero or more values.
RapidJSON 是只有头文件的 C++ 库。只需把 include/rapidjson 目录复制至系统或项目的 include 目录中。
在example目录下有很多使用的实例。
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include <cstdio>
using namespace rapidjson;
using namespace std;
int main()
{
const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
printf("Original JSON:\n %s\n", json);
Document document;
char buffer[sizeof(json)];
memcpy(buffer, json, sizeof(json));
if (document.ParseInsitu(buffer).HasParseError())
return 1;
printf("\nParsing to docuemnt succeed.\n");
printf("\nAccess values in document:\n");
assert(document.IsObject());
assert(document.HasMember("hello"));
assert(document["hello"].IsString());
printf("hello = %s\n", document["hello"].GetString());
Value::MemberIterator hello = document.FindMember("hello");
assert(hello != document.MemberEnd());
assert(hello->value.IsString());
assert(strcmp("world", hello->value.GetString()) == 0);
(void)hello;
assert(document["t"].IsBool());
printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
assert(document["f"].IsBool());
printf("f = %s\n", document["f"].GetBool() ? "true" : "false");
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
assert(document["i"].IsNumber());
assert(document["i"].IsInt());
printf("i = %d\n", document["i"].GetInt());
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
printf("pi = %g\n", document["pi"].GetDouble());
// Iterating array with iterators.
{
const Value & a = document["a"];
assert(a.IsArray());
for (SizeType i = 0; i < a.Size(); i++)
printf("a[%d] = %d\n", i, a[i].GetInt());
int y = a[0].GetInt();
(void)y;
printf("a = ");
for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
printf("%d ", itr->GetInt());
printf("\n");
}
// Iterating object member.
static const char * kTypeNames[] = {"Null","False","True","Object","Array","String","Number"};
for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); itr++)
printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]);
// Change i to a bigger number
{
uint64_t f20 = 1;
for (uint64_t j = 1; j <= 20; j++)
f20 *= j;
//document["i"] = f20;
document["i"].SetUint64(f20);
assert(!document["i"].IsInt());
assert(document["i"].IsUint64());
}
// Adding values to array.
{
Value & a = document["a"];
Document::AllocatorType & allocator = document.GetAllocator();
for (int i = 5; i <= 10; i++)
a.PushBack(i, allocator);
a.PushBack("Lua", allocator).PushBack("Mio", allocator);
}
// string values
{
//document["hello"] = "rapidjson"; //This will invoke strlen()
document["hello"].SetString("rapidjson", 9); //Faster version
}
// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
Value author;
{
char buffer2[10];
int len = sprintf(buffer2, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string.
author.SetString(buffer2, static_cast<SizeType>(len), document.GetAllocator());
// Shorter but slower version:
// document["hello"].SetString(buffer, document.GetAllocator());
// Constructor version:
// Value author(buffer, len, document.GetAllocator());
// Value author(buffer, document.GetAllocator());
memset(buffer2, 0, sizeof(buffer2)); // For demonstration purpose.
}
// Variable 'buffer' is unusable now but 'author' has already made a copy.
document.AddMember("author", author, document.GetAllocator());
assert(author.IsNull()); // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.
// Stringfy JSON
printf("\nModified JSON with reformatting:\n");
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
document.Accept(writer);
puts(sb.GetString());
return 0;
}
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/pointer.h"
#include <cstdio>
using namespace rapidjson;
using namespace std;
void ShowJSON(Document & d)
{
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
d.Accept(writer);
puts(sb.GetString());
}
void objDemo()
{
Document d;
Pointer("/project").Set(d, "RapidJSON");
Pointer("/stars").Set(d, 10);
ShowJSON(d);
if (Value * stars = Pointer("/stars").Get(d))
stars->SetInt(stars->GetInt() + 1);
ShowJSON(d);
Pointer("/a/b/0").Create(d);
ShowJSON(d);
Value & hello = Pointer("/hello").GetWithDefault(d, "world");
ShowJSON(d);
Value x("C++");
Pointer("/hello").Swap(d, x);
ShowJSON(d);
bool success = Pointer("/a").Erase(d);
assert(success);
ShowJSON(d);
}
void cDemo()
{
Document d;
SetValueByPointer(d, "/project", "RapidJSON");
SetValueByPointer(d, "/stars", 10);
ShowJSON(d);
if (Value * stars = GetValueByPointer(d, "/stars"))
stars->SetInt(stars->GetInt() + 1);
CreateValueByPointer(d, "/a/b/0");
Value & hello = GetValueByPointerWithDefault(d, "/hello", "world");
ShowJSON(d);
Value x("C++");
SwapValueByPointer(d, "/hello", x);
bool success = EraseValueByPointer(d, "/a");
assert(success);
ShowJSON(d);
CreateValueByPointer(d, "/1/0");
EraseValueByPointer(d, "/1/0");
SetValueByPointer(d, "/1/-", 123);
ShowJSON(d);
SetValueByPointer(d, "/1/a", 789);
ShowJSON(d);
}
int main()
{
cDemo();
return 0;
}
//最大的游戏玩家数
#define MAX_GAME_PLAY_USER 4
//兰州麻将中牌数
#define CARD_MAX_COUNT 136
//最多的手牌数量为14张
#define MAX_HANDCARD_NUM 14
//最多的固定牌数量
#define MAX_FIXCARD_NUM 4
//序数牌的张数: 1~9
#define MAX_XUSHU_NUM 9
//风牌的张数: 东南西北
#define MAX_FENG_NUM 4
//箭牌的张数: 中发白
#define MAX_JIAN_NUM 3
//最大杠操作,因为手牌最多14张,一个杠要用4张牌,所以手中最多同时存在3个杠。
#define MAX_GANG_COUNT 3
//一张非真实性的牌,填充假数据之用
#define INVALID_CARD 0xFF
//一个非真实性的玩家椅子号
#define INVALID_CHAIR 0x7F
#define NUM_MASK 0x0F
#define TYPE_MASK 0xF0
#define CardNum(c) ((c) & NUM_MASK)
#define CardType(c) (((c) & TYPE_MASK)>>4)
#define MJ_TYPE_WAN 0 //万, 0-8,各4张,共36张
#define MJ_TYPE_TIAO 1 //条, 0-8,各4张,共36张
#define MJ_TYPE_BING 2 //饼, 0-8,各4张,共36张
#define MJ_TYPE_FENG 3 //东南西北各4张,共16张
#define MJ_TYPE_JIAN 4 //中发白 各4张,共12张
#define MJ_TYPE_FLOWER 5 //花
//牌的种类数量(万,条,饼,风,箭)
#define MJ_TYPE_NUM 5
//牌数
#define MAX_ALL_GANG_COUNT 34
//最大牌面值
#define MAX_CARD 0x43
#define MAX_CARD_ARRAY_SIZE (MAX_CARD + 1)
#define WIK_NULL 0x00 //没有类型
#define WIK_LEFT 0x01 //左吃类型
#define WIK_CENTER 0x02 //中吃类型
#define WIK_RIGHT 0x04 //右吃类型
typedef uint8_t Card;
const Card g_CardWangData[] =
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,//万
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x00
};
const Card g_CardTiaoData[] =
{
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,//条
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x00
};
const Card g_CardTongData[] =
{
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,//筒
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x00
};
const Card g_CardFengData[] =
{
0x31, 0x32, 0x33, 0x34,//风
0x31, 0x32, 0x33, 0x34,
0x31, 0x32, 0x33, 0x34,
0x31, 0x32, 0x33, 0x34,
0x00
};
const Card g_CardJianData[] =
{
0x41, 0x42, 0x43, //箭
0x41, 0x42, 0x43,
0x41, 0x42, 0x43,
0x41, 0x42, 0x43,
0x00
};
const Card g_CardHuaData[] = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x00 /* 花 */ };
const Card g_CardGangData[] =
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,//万
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,//条
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,//筒
0x31, 0x32, 0x33, 0x34,//风
0x41, 0x42, 0x43 //箭
};
#define CardYiWan 0x01 //一万
#define CardYaoJi 0x11 //一条,幺鸡
#define CardYiTong 0x21 //一筒
#define CardJiuWan 0x09 //九万
#define CardJiuTiao 0x19 //九条
#define CardJiuTong 0x29 //九筒
//东南西北
#define CardDONG 0x31
#define CardNAN 0x32
#define CardXI 0x33
#define CardBEI 0x34
//中发白
#define CardZHONG 0x41
#define CardFA 0x42
#define CardBAI 0x43
用牌:序数牌、字牌,一共136张。
翻番:结算时分数乘2.
将牌(对子):2张相同的牌。
顺子: 指同花色三个连续的牌,如三四五万、六七八筒等。
刻子(坎子):3张相同的牌。
扑子:顺子和刻子。
嘴子:嘴子除了本身牌的意义外,还能顶替其他的牌。嘴子能顶替东南西北中发白中任意一张牌。但是只有当组成黑三风和中发白时,嘴子才能起作用。例如:[嘴子,东,南]可以组成一副黑三风,但是[嘴子,东,东]是不可以组成一副刻子的,[嘴子,东]也不可以组成一副对子。
嘴子-小鸡飞:幺鸡作为嘴子。
嘴子-鸡蛋双飞:幺鸡和一饼作为嘴子。
嘴子-三幺飞:幺鸡、一万和一饼作为嘴子。
嘴子-三九飞:九万、九条和九饼作为嘴子。
中发白:中发白三张各一张可以组成一副扑子。每一幅中发白翻番。
黑三风:东南西北任意取其中不同的三张可以组成一副扑子。每一幅黑三风翻番。 例如:[东、南、西], [东、南、北] 即可组成一副黑三风。但是[东、南、南]不行,因为三张牌每张都要不同。
听牌-不吃碰:听牌之后不能吃、碰,不能放杠,但是可以暗杠,可以续杠。但是如果杠会影响到胡的牌时,则不可以杠。
听牌-不点炮:听牌之后不会点炮,也就是说你打出去的牌,其他人不能胡。但是听牌之后打出去的第一张牌可以点炮。
甩牌:开局之后,每个玩家先各发13张手牌,然后进入甩牌阶段,可以甩出自己不需要的牌,可以甩的牌(一万、九万、一条、九条、一饼、九饼、东南西北中发白),甩牌的数量必须是3的倍数。甩牌结束之后轮到庄家摸牌,出牌。
报听:需要先听牌之后才可以胡牌。 听牌之后,打出一张牌,本轮操作时,其他玩家打出和自己相同的牌,自己不能胡牌。
悄悄胡:不需要听牌就可以直接胡牌。
七对:手牌中有7个对子,也可胡牌。七对胡牌翻番。
轮庄规则:首局随机一名玩家当庄。庄家胡牌或者荒庄,则庄家继续当庄,闲家胡牌则为轮庄(庄家的下一家当庄,逆时针方向)。如果开启了胡两次、胡到底,则无论输赢都采用轮庄。
胡牌:自摸胡牌2倍,赢3家。放炮胡牌3倍,赢1家。 如果底分为1,玩家A自摸胡牌,玩家A赢的分数为6分,其他三人各输2分。 如果底分为1,玩家A胡牌,玩家B放的炮,玩家A赢的分数为3分,玩家B输3分,其他两个人不输不赢。
截胡:玩家A放炮,多个玩家都可以胡牌时,最靠近玩家A的优先胡牌。没有一炮多响。
胡牌后玩家的操作顺序:玩家A放炮,其他玩家胡牌了,然后轮到放炮玩家的下一个玩家摸牌、出牌。
单调将:当设置了硬将时,不可以听将牌。例如设置了二五八硬将,手中有4副顺子+2万,不可以听2万。
洗澡规则:轮到自己回合,自己可以听牌,但是不报听,点击了过,打出了一张牌,打出的牌又是可以听的牌时,进入洗澡状态,处于洗澡状态下,刚摸到的那张手牌是不可以听的,但其他的手牌可以听。进入洗澡状态时的手牌如果改变了的话,洗澡状态就退出了。也就是说只要吃、碰、杠了,或者打出了一张不是刚摸到的牌(打出和刚摸到一样的牌也算打出刚摸到的牌),就退出洗澡状态。