#include "stdafx.h"
#include "mahjong.h"
#include "Structs.h"
#include <functional>
/**
card_num 牌的数量
op_num 拆牌类型
**/
CHAI_ITEM* Mahjong::get_chai_item(char card_num, int* op_num)
{
*op_num = 0;
if (card_num == 1)
{
*op_num = 2;
return chai_item1;
}
if (card_num == 2) {
*op_num = 3;
return chai_item2;
}
if (card_num == 3) {
*op_num = 2;
return chai_item3;
}
if (card_num == 4) {
*op_num = 3;
return chai_item4;
}
printf("%s","get_huisu_item fail");
return chai_item1;
}
int Mahjong::check_zi_complete(Matrix matrix_temp, int laizi_num, bool& jiang, bool group)
{
int n = 0;
int jiang_num = 0;
for (int i = 3; i < 5; i++)
{
for (int j = 1; j < NCOLS; j++)
{
if (matrix_temp[i][j] == 0)continue;
if (matrix_temp[i][j] == 1 || matrix_temp[i][j] == 4)
{
++n;
++jiang_num;
}
else if (matrix_temp[i][j] == 2)
{
++jiang_num;
}
}
}
if (jiang_num > 0)
{
n = n + jiang_num - 1;
jiang_num = 1;
}
jiang = jiang_num>0 ? true : false;
return n;
}
int Mahjong::check_color_complete(Card* color_cards,int row, bool& jiang, int total_laizi,bool group)
{
Card cards[12] = { 0 };
memcpy(cards, color_cards, 10);
if (total_laizi == 0)
{
int yu = cards[0] % 3;
if (yu == 1) return ERROR_RET;
if (jiang && yu == 2) return ERROR_RET;
}
for (int i = 0; i <= total_laizi; i++)
{
int yu = (i + cards[0]) % 3;
if (yu == 1)continue;
bool cur_jiang = jiang;
if (chai_pos_calc(1, cards,row, cur_jiang, i,group) != ERROR_RET)
{
jiang = cur_jiang;
return i;
}
}
return ERROR_RET;
}
int Mahjong::chai_pos_calc(int pos, Card* cards,int row, bool& jiang, int total_laizi, bool group)
{
if (pos > 9) return 0;
int n = cards[pos];
if (n == 0)
{
return chai_pos_calc(pos + 1, cards,row, jiang, total_laizi,group);
}
//获取所有可拆解情况
int op_num = 0;
CHAI_ITEM* p = NULL;
p = get_chai_item(n, &op_num);
for (int i = 0; i < op_num; i++)
{
CHAI_ITEM& pi = p[i];
if (jiang && pi.jiang) continue;
int old_pos = cards[pos];
int old_pos1 = cards[pos + 1];
int old_pos2 = cards[pos + 2];
printf("%d:%d:%d \n", cards[pos], cards[pos + 1], cards[pos + 2]);
int laizi = 0;
if (cards[pos] - pi.a < 0)
{
laizi += pi.a - cards[pos];
cards[pos] = 0;
}
else
{
cards[pos] -= pi.a;
}
if (cards[pos + 1] - pi.b < 0)
{
laizi += pi.b - cards[pos + 1];
cards[pos + 1] = 0;
}
else
{
cards[pos + 1] -= pi.b;
}
if (cards[pos + 2] - pi.c < 0)
{
laizi +=pi.c -cards[pos + 2];
cards[pos + 2] = 0;
}
else
{
cards[pos + 2] -= pi.c;
}
bool e = jiang || pi.jiang;
int result = ERROR_RET;
if (laizi <= total_laizi)
{
result = chai_pos_calc(pos + 1, cards,row, e, total_laizi - laizi,group);
}
cards[pos] = old_pos;
cards[pos + 1] = old_pos1;
cards[pos + 2] = old_pos2;
if (result != ERROR_RET)
{
jiang = e;
return laizi + result;
}
}
return ERROR_RET;
}
bool Mahjong::hu_laizi(BYTE byCard, bool group)
{
//重置胡牌的每组牌数据
if (group)
{
m_groups.clear();
}
Matrix matrix_temp;
for (int i = 0; i < NROWS; ++i)
{
for (int j = 0; j < NCOLS; ++j)
{
matrix_temp[i][j] = matrix[i][j];
}
}
//统计癞子数量
int laizi_num = 0;
getLaiziNum(matrix_temp,laizi_num);
bool jiang = false;
//检查东西南北中发白
int need_laizi = check_zi_complete(matrix_temp, laizi_num, jiang, group);
if (need_laizi > laizi_num) return false;
for (int row = 0; row < 3; row++) //万桶条判断是否满足胡牌条件
{
need_laizi += check_color_complete(matrix_temp[row], row, jiang, laizi_num - need_laizi, group);
if (need_laizi > laizi_num) return false;
}
////检查万
//surplus_laizi = laizi_num - need_laizi1;
//int need_laizi2 = check_color_complete(, jiang, surplus_laizi, group);
//if (need_laizi1 + need_laizi2 > laizi_num) return false;
////检查筒
//surplus_laizi = laizi_num - need_laizi1 - need_laizi2;
//int need_laizi3 = check_color_complete(matrix_temp[1], jiang, surplus_laizi, group);
//if (need_laizi1 + need_laizi2 + need_laizi3 > laizi_num) return false;
////检查条
//surplus_laizi = laizi_num - need_laizi1 - need_laizi2 - need_laizi3;
//int need_laizi4 = check_color_complete(matrix_temp[2], jiang, surplus_laizi, group);
//if (need_laizi1 + need_laizi2 + need_laizi3 + need_laizi4 > laizi_num) return false;
return true;
}
bool Mahjong::hu(BYTE byCard, bool group)
{
//重置胡牌的每组牌数据
if (group)
{
m_groups.clear();
}
//检查定缺
if (m_bUserCfg[100])
{
if (
(0 == m_bUserDingQueHuaSe && matrix[0][0]>0) ||
(1 == m_bUserDingQueHuaSe && matrix[1][0]>0) ||
(2 == m_bUserDingQueHuaSe && matrix[2][0]>0)
)
{
return false;
}
}
//检查是否胡七小对
if (is_qi_xiao_dui() != 0)
{
hu_type = COMMON_HU;
return true;
}
//检查是否胡十三幺
if (m_bUserCfg[101])
{
if (is_shi_san_yao())
{
hu_type = COMMON_HU;
return true;
}
}
//获取飘胡状态
bool byPiaoHu = is_piao_hu();
//检查花色数量
int nHuaSeCount = GetHuaSeCount();
if (m_bUserCfg[102] && nHuaSeCount != 3) //三色全
{
if (m_bUserCfg[103])
{
if (nHuaSeCount == 2)
{
return false;
}
}
else if (m_bUserCfg[104] && GetHuaSeCountZi() != true)
{
return false;
}
else
{
return false;
}
}
bool success = false;
success = CheckHu332(group);
//胡牌
if (success)
{
hu_type = COMMON_HU;
return true;
}
return false;
}
bool Mahjong::hu_if_add(Card card, bool group)
{
int row = get_suits(card);
int col = get_face(card);
if (row >= NROWS || col >= NCOLS)
{
return false;
}
matrix[row][col] += 1;
matrix[row][0] += 1;
bool result = hu_laizi(card, group);
matrix[row][col] -= 1;
matrix[row][0] -= 1;
return result;
}
// 分解为 刻 顺 组合
bool Mahjong::complete(int row, bool group)
{
//一副花色的牌是否完整 即可分解成N个顺或刻
Card* suits = matrix[row];
if (suits[0] == 0)
return true;
//寻找第一张牌
int j = 1;
for (; j != NCOLS; ++j)
{
if (suits[j] != 0)
break;
}
//刻
if (suits[j] >= 3)
{
suits[j] -= 3;
suits[0] -= 3;
if (group)
m_groups.push_back(Group(make_card(row, j), make_card(row, j), make_card(row, j)));
bool result = complete(row, group);
suits[j] += 3;
suits[0] += 3;
if (!result && group)
m_groups.pop_back();
return result;
}
//顺
if (row < 3 && j < 8 && suits[j + 1] > 0 && suits[j + 2] > 0)
{
suits[j] -= 1;
suits[j + 1] -= 1;
suits[j + 2] -= 1;
suits[0] -= 3;
if (group)
m_groups.push_back(Group(make_card(row, j), make_card(row, j + 1), make_card(row, j + 2)));
bool result = complete(row, group);
suits[j] += 1;
suits[j + 1] += 1;
suits[j + 2] += 1;
suits[0] += 3;
if (!result && group)
m_groups.pop_back();
return result;
}
return false;
}
bool Mahjong::hu_shun_first(bool group)
{
if (group)
m_groups.clear();
int jrow = -1; //包含将的行
//满足3,3,3,3,2模型
for (int i = 0; i <= 4; ++i) {
int rem = matrix[i][0] % 3;
if (rem == 1) {
return false;
}
else if (rem == 2) {
if (jrow != -1)
return false;
jrow = i;
}
}
//先计算没有将牌的花色
for (int i = 0; i <= 4; ++i) {
if (i != jrow)
if (!complete_shun_first(i, group))
return false;
}
//该列表中包含将牌,采用逐个测试方式
//指示除掉将后能否通过
bool success = false;
Card* jsuits = matrix[jrow];
#ifdef GB_MAHJONG
//先以2张牌为将,避免将刻子拆分
//Fix:手牌 111,222,333,444,55 拆分成了 111,22,234,345,345,
//一般来说(起码在国标中)刻字的番型比顺子更高
for (int j = 1; j <= 9; ++j) {
if (jsuits[j] == 2) {
jsuits[j] -= 2;
jsuits[0] -= 2;
if (group)
m_groups.push_back(Group(m