**
一下是三种判定四川麻将(血战到底)胡牌的算法,主要思想是递归+回溯~
Python写法:
**
# -*- coding: utf-8 -*-
# @Time :2022/2/18 14:15
# @Author :LuoLin01
class PmaJong(object):
def __init__(self):
self.m_TypeNum = []
self.m_CardNum = []
self.HasCouple = False
for i in range(3):
self.m_TypeNum.append(0)
self.m_CardNum.append([0]*9)
self.g_typedef = ['w', 't', 'd'] # 万、条、筒
self.m_GangNum = 0
def InitData(self, cards_str):
if not len(cards_str) or len(cards_str) % 2: # 必然是偶数才能判断是否完成
print("数据初始化出错")
return
cur_idx = 0
while cur_idx < len(cards_str):
cur_c = cards_str[cur_idx]
nNum = ord(cur_c) - ord('0')
cType = cards_str[cur_idx + 1]
for i in range(3):
if cType == self.g_typedef[i]:
self.m_TypeNum[i] += 1
self.m_CardNum[i][nNum - 1] += 1
break
cur_idx += 2
def IsSevenCouple(self):
if 14 == self.m_TypeNum[0] + self.m_TypeNum[1] + self.m_TypeNum[2]:
for i in range(3):
for j in range(9):
if self.m_CardNum[i][j] != 0 and self.m_CardNum[i][j] != 2:
return False
def IsWin(self):
if self.m_TypeNum[0] and self.m_TypeNum[1] and self.m_TypeNum[2]:
print("不是缺一门\n")
return False
if self.IsSevenCouple():
print("七小对\n")
return True
for i in range(3):
if not self.IsOneTypeWin(self.m_CardNum[i], self.m_TypeNum[i], i):
print("花色:%s不满足胡牌\n" % self.g_typedef[i])
return False
if not self.HasCouple:
print("没有对子,不能胡牌\n")
return False
if self.m_TypeNum[0] + self.m_TypeNum[1] + self.m_TypeNum[2] - 14 != self.m_GangNum:
print("你丫诈和,牌的数量不对.\n")
return False
print("正常胡牌\n")
return True
def IsOneTypeWin(self, pCards, Num, type):
print(pCards)
if not Num:
return True
tmp = ""
for i in range(9):
if pCards[i] >= 2 and not self.HasCouple:
pCards[i] -= 2
self.HasCouple = True
if self.IsOneTypeWin(pCards, Num - 2, type):
tmp += str(i+1) + self.g_typedef[type] + str(i+1) + self.g_typedef[type]
print("当前牌:%s\n", tmp)
return True
pCards[i] += 2
self.HasCouple = False
if pCards[i] == 4:
pCards[i] -= 4
if self.IsOneTypeWin(pCards, Num - 4, type):
self.m_GangNum += 1
tmp += (str(i + 1) + self.g_typedef[type]) * 4
print("当前牌:%s\n", tmp)
return True
pCards[i] += 4
if pCards[i] >= 3:
pCards[i] -= 3
if self.IsOneTypeWin(pCards, Num - 3, type):
tmp += (str(i + 1) + self.g_typedef[type]) * 3
print("当前牌:%s\n", tmp)
return True
pCards[i] += 3
if i < 7 and pCards[i] and pCards[i + 1] and pCards[i + 2]:
pCards[i] -= 1
pCards[i + 1] -= 1
pCards[i + 2] -= 1
if self.IsOneTypeWin(pCards, Num - 3, type):
tmp += str(i + 1) + self.g_typedef[type] + str(i + 2) + self.g_typedef[type] + str(i + 3) + self.g_typedef[type]
print("当前牌:%s\n", tmp)
return True
pCards[i] += 1
pCards[i + 1] += 1
pCards[i + 2] += 1
return False
if __name__ == "__main__":
cur_s = "1w1w1w2d3d4d2w3w4w7d8d9d5w5w"
mahJong = PmaJong()
mahJong.InitData(cur_s)
if mahJong.IsWin():
print("win !!!!!")
else:
print("False !!!!!")
## c#写法
using System;
namespace ConsoleApp1
{
class CSMahJangg
{
public CSMahJangg()
{
}
public int[] m_TypeNum = new int[3];
public int[][] m_CardNum =
{
new int[9],
new int[9],
new int[9],
};
public int m_GangNum = 0;
public char[] g_typedef = new char[] { 'w', 't', 'd' };
public void Init(string pCards)
{
int cur_idx = 0;
char pTmp = pCards[cur_idx];
int nNum = 0;
char cType;
while (cur_idx < pCards.Length)
{
pTmp = pCards[cur_idx];
nNum = pTmp - '0';
cType = pCards[cur_idx+1];
for (int i = 0; i < 3; i++)
{
if (cType == g_typedef[i])
{
m_TypeNum[i]++;
m_CardNum[i][nNum - 1]++;
break;
}
}
cur_idx += 2;
}
}
public bool IsSevenCouple()
{
if (14 == m_TypeNum[0] + m_TypeNum[1] + m_TypeNum[2])
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 9; j++)
{
if (m_CardNum[i][j] != 0 && m_CardNum[i][j] != 2)
{
return false;
}
}
}
return true;
}
return false;
}
public bool IsWin()
{
if (m_TypeNum[0] > 0 && m_TypeNum[1] > 0 && m_TypeNum[2] > 0)
{
//不是缺一门
Console.WriteLine("不是缺一门\n");
return false;
}
if (IsSevenCouple())
{
//七小对
Console.WriteLine("七小对\n");
return true;
}
//正常胡牌:有一个对子,其余的要么三支顺子,要么三支一样的(或四只)
bool HasCouple = false;
for (int i = 0; i < 3; i++)
{
if (!IsOneTypeWin(m_CardNum[i], m_TypeNum[i], ref HasCouple, i))
{
Console.WriteLine("花色:{0}不满足胡牌\n", g_typedef[i]);
return false;
}
}
if (!HasCouple)
{
Console.WriteLine("没有对子,不能胡牌\n");
return false;
}
if (m_TypeNum[0] + m_TypeNum[1] + m_TypeNum[2] - 14 != m_GangNum)
{
Console.WriteLine("你丫诈和,牌的数量不对.\n");
return false;
}
Console.WriteLine("正常胡牌\n");
return true;
}
public bool IsOneTypeWin(int [] pCards, int Num, ref bool HasCouple, int type) // 递归回溯求解
{
if (Num == 0)
{
return true;
}
string tmp = "";
for (int i = 0; i < 9; i++)
{
if (pCards[i] >= 2 && !HasCouple)
{
pCards[i] -= 2;
HasCouple = true;
if (IsOneTypeWin(pCards, Num - 2, ref HasCouple, type))
{
tmp += Convert.ToString(i + 1) + g_typedef[type] + Convert.ToString(i + 1) + g_typedef[type];
Console.WriteLine("当前牌:{0}\n", tmp);
return true;
}
pCards[i] += 2;
HasCouple = false;
}
if (pCards[i] == 4) // 有四个一样的
{
pCards[i] -= 4;
if (IsOneTypeWin(pCards, Num - 4, ref HasCouple, type))
{
tmp += Convert.ToString(i + 1) + g_typedef[type] + Convert.ToString(i + 1) + g_typedef[type] +
Convert.ToString(i + 1) + g_typedef[type] + Convert.ToString(i + 1) + g_typedef[type];
Console.WriteLine("当前牌:{0}\n", tmp);
m_GangNum++;
return true;
}
pCards[i] += 4;
}
if (pCards[i] >= 3)
{
pCards[i] -= 3;
if (IsOneTypeWin(pCards, Num - 3, ref HasCouple, type))
{
tmp += Convert.ToString(i + 1) + g_typedef[type] + Convert.ToString(i + 1) + g_typedef[type] +
Convert.ToString(i + 1) + g_typedef[type] ;
Console.WriteLine("当前牌:{0}\n", tmp);
return true;
}
pCards[i] += 3;
}
if (i < 7 && pCards[i]>0 && pCards[i + 1]>0 && pCards[i + 2]>0) // 顺子
{
pCards[i] -= 1;
pCards[i + 1] -= 1;
pCards[i + 2] -= 1;
if (IsOneTypeWin(pCards, Num - 3, ref HasCouple, type))
{
tmp += Convert.ToString(i + 1) + g_typedef[type] + Convert.ToString(i + 2) + g_typedef[type] +
Convert.ToString(i + 1) + g_typedef[type] + Convert.ToString(i + 3) + g_typedef[type];
Console.WriteLine("当前牌:{0}\n", "123");
return true;
}
pCards[i] += 1;
pCards[i + 1] += 1;
pCards[i + 2] += 1;
}
}
return false;
}
}
class Program
{
static void Main(string[] args)
{
CSMahJangg mj = new CSMahJangg();
string s = "2d1w1w1w2d3d4d2w3w4w7d8d9d5w5w";
mj.Init(s);
Console.WriteLine("当前牌:{0}\n", "123");
if (mj.IsWin())
{
Console.WriteLine("Win!!!!!");
}
else
{
Console.WriteLine("False!!!!!");
}
Console.ReadKey();
}
}
}
**
c++写法
**
#include <stdio.h>
#include <cstring>
#include<iostream>
#include <vector>
#define TEST 0
#if TEST
#define LOG(fmt, ...) printf("line=%d file=%s" fmt"\n", __LINE__, __FILE__, ##__VA_ARGS__)
#else
#define LOG(fmt, ...) printf( fmt"\n", ##__VA_ARGS__)
#endif
using std::vector;
const char g_typedef[3] = { 'w', 't', 'd' };//万、条、筒
class CMahJangg
{
public:
CMahJangg()
{
m_TypeNum = vector<int>(3, 0);
m_CardNum = vector<vector<int>>(3, vector<int>(9));
for (int i = 0; i < 3; i++)
{
m_TypeNum[i] = 0;
memset(log, 0, sizeof(char) * 100);
m_GangNum = 0;
}
}
void Init(char *pCards)
{
char *pTmp = pCards;
int nNum = 0;
char cType = 0;
while (*pTmp != '\0')
{
nNum = *pTmp - '0';
cType = *(pTmp + 1);
for (int i = 0; i < 3; i++)
{
if (cType == g_typedef[i])
{
m_TypeNum[i]++;
m_CardNum[i][nNum - 1]++;
break;
}
}
pTmp += 2;
}
}
bool IsSevenCouple()
{
if (14 == m_TypeNum[0] + m_TypeNum[1] + m_TypeNum[2])
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 9; j++)
{
if (m_CardNum[i][j] != 0 && m_CardNum[i][j] != 2)
{
return false;
}
}
}
return true;
}
return false;
}
bool IsWin()
{
if (m_TypeNum[0] && m_TypeNum[1] && m_TypeNum[2])
{
//不是缺一门
LOG("不是缺一门\n");
return false;
}
if (IsSevenCouple())
{
//七小对
LOG("七小对\n");
return true;
}
//正常胡牌:有一个对子,其余的要么三支顺子,要么三支一样的(或四只)
bool HasCouple = false;
for (int i = 0; i < 3; i++)
{
if (!IsOneTypeWin(m_CardNum[i], m_TypeNum[i], HasCouple, i))
{
LOG("花色:%c不满足胡牌\n", g_typedef[i]);
return false;
}
}
if (!HasCouple)
{
LOG("没有对子,不能胡牌\n");
return false;
}
if (m_TypeNum[0] + m_TypeNum[1] + m_TypeNum[2] - 14 != m_GangNum)
{
LOG("你丫诈和,牌的数量不对.\n");
return false;
}
LOG("正常胡牌\n");
return true;
}
void Print(vector<int> pCards, int type)
{
char t = g_typedef[type];
for (int i=0; i<9; i++ )
{
for (int j = 0; j < pCards[i]; j++)
{
std::cout << i+1 << "" << t << " ";
}
}
std::cout << std::endl;
}
bool IsOneTypeWin(vector<int> pCards, int Num, bool &HasCouple, int type) // 递归回溯求解
{
Print(pCards, type);
if (Num == 0)
{
return true;
}
char tmp[20] = { 0 };
for (int i = 0; i < 9; i++)
{
if (pCards[i] >= 2 && !HasCouple)
{
pCards[i] -= 2;
HasCouple = true;
if (IsOneTypeWin(pCards, Num - 2, HasCouple, type))
{
sprintf(tmp, "%d%c%d%c ", i + 1, g_typedef[type], i + 1, g_typedef[type]);
strcat(log, tmp);
LOG("当前牌:%s\n", log);
return true;
}
pCards[i] += 2;
HasCouple = false;
}
if (pCards[i] == 4) // 有四个一样的
{
pCards[i] -= 4;
if (IsOneTypeWin(pCards, Num - 4, HasCouple, type))
{
sprintf(tmp, "%d%c%d%c%d%c%d%c ", i + 1, g_typedef[type], i + 1, g_typedef[type], i + 1, g_typedef[type], i + 1, g_typedef[type]);
strcat(log, tmp);
LOG("当前牌:%s\n", log);
m_GangNum++;
return true;
}
pCards[i] += 4;
}
if (pCards[i] >= 3)
{
pCards[i] -= 3;
if (IsOneTypeWin(pCards, Num - 3, HasCouple, type))
{
sprintf(tmp, "%d%c%d%c%d%c ", i + 1, g_typedef[type], i + 1, g_typedef[type], i + 1, g_typedef[type]);
strcat(log, tmp);
LOG("当前牌:%s\n", log);
return true;
}
pCards[i] += 3;
}
if (i < 7 && pCards[i] && pCards[i + 1] && pCards[i + 2]) // 顺子
{
pCards[i] -= 1;
pCards[i + 1] -= 1;
pCards[i + 2] -= 1;
if (IsOneTypeWin(pCards, Num - 3, HasCouple, type))
{
sprintf(tmp, "%d%c%d%c%d%c ", i + 1, g_typedef[type], i + 2, g_typedef[type], i + 3, g_typedef[type]);
strcat(log, tmp);
LOG("当前牌:%s\n", log);
return true;
}
pCards[i] += 1;
pCards[i + 1] += 1;
pCards[i + 2] += 1;
}
}
return false;
}
private:
vector<int> m_TypeNum;
vector<vector<int>> m_CardNum;
int m_GangNum; // 杠的数量
char log[100]; //用作打印log
};
bool IsMahJangWin(char *pCard)
{
CMahJangg mj;
mj.Init(pCard);
return mj.IsWin();
}
int main()
{
char a[100] = "1w1w1w2d3d4d2w3w4w7d8d9d5w5w";
auto r = IsMahJangWin(a);
if (r)
{
LOG("win!!!!!");
}
else
{
LOG("Not Win!!!!");
}
return 0;
}
以上三种写法都可以运行,需要自取,不懂留言,有空看到尽力回复~
ps:每天都要进步,蛰伏,当遇到风口浪尖,希望能够随风起飞