我们先来实现主函数部分:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define CLS system("cls")
#define PUS system("pause")
#define CLR system("color 0f")
#define PR printf
#define SC scanf
#define UNDEALT_PUKER -32
#define EMPTY_CARD 63
#define GET fgets(FC,32,fp);sscanf
void gotoxy(HANDLE HDO, int x, int y);
void printSmallPuker(int who, int n);
void getClientInfo();
void printPuker();
void AI(int who);
void initial();
void deal();
void _deal();
void over();
void clearInfo();
int home();
int play();
int AIplay();
int getMouseEvent();
int daipai(int n, int cmd[32]);
int shunzi_liandui(int n, int cmd[32]);
int isTherePuker(int special, int n, int cmd[32]);
int comparePuker(int recSpecial, int special, int recN, int n, int rec[32], int cmd[32]);
char fBuffer[64];
char space[32] = " ";
char color[9] = "*&#%";
char table[16] = "3456789XJQKA2RR";
char playerLevel[8]; //玩家等级
char playerName[16]; //玩家名字
char player1[16]; //电脑名字
char player2[16]; //电脑名字
char consoleColor[32]; //窗口颜色
char consoleTitle[32]; //窗口标题
char dt[16]; //登录校验
char cd[64]; //存档校验
char FC[32]; //文件内容 fileContent
char LED[512]; //主页滚动显示
int col, line; //窗口大小
int basis; //底分
int extra[3]; //三张底牌
int LEDlength; //主页 LED 数组长度
int AIcmdNum; //AIcommandNumber,存储 AI 出牌数量用于打印,
int AIcmd[32]; //AIcommand,存储 AI 出的牌
int mouse[2]; //鼠标坐标
int mark; //分数
int quit;
int atHome;
typedef struct{
int num; //扑克点数:0->12分别代表3->2,13为王
int color; //花色:0 ?,1 ?,2 ?,3 ?.
int owner; //归属,0为未发放
} puker_property;
typedef struct{
int card[20]; //持有的牌
int num; //扑克牌数
int rank; //总赢盘数
int isOver; //是否已结束
} player_property;
typedef struct{
int turn; //回合统计
int basis; //回合倍数
int who; //出牌权
int special; //回合特殊牌型
int record[3][32]; //农民玩家上回合记录
int isPass[3]; //玩家是否出过牌
int color; //最后一张牌的花色,纯属用于装饰
int hasPrinted; //是否打印完成,用于防止循环不出
}pass_property;
puker_property puker[64];
player_property player[3];
pass_property pass;
INPUT_RECORD inRec; // 返回数据记录
DWORD numRead; // 返回已读取的记录数
HANDLE HDO = GetStdHandle(STD_OUTPUT_HANDLE); // 获得标准输出设备句柄
HANDLE HDI = GetStdHandle(STD_INPUT_HANDLE); // 获取标准输入设备句柄
HWND hwnd = FindWindow("ConsoleWindowClass", NULL); // 控制台窗口句柄
COORD position; // 存储使用Windows API获取的坐标。由于后面开始游戏那里要点击,所以定义为全局变量
COORD size = {100, 32}; // 存储窗口大小
void gotoxy(HANDLE HDO, int x, int y) { //光标转移
position.X = x;
position.Y = y;
SetConsoleCursorPosition(HDO, position);
}
/************* 存档读取 **************/
void getClientInfo() {
FILE *fp; // 读取显示配置文件,具体参照 ACM 上的实验报告十三
if ((fp = fopen("Data/client.ini", "r")) == NULL) { PR("存档丢失或被破坏, 请拷贝新存档或自己作假一个存档!\n"); PUS; exit(0); }
GET(FC, "dt %s", dt); // 读取登录校验
GET(FC, "cd %s", cd); // 读取存档校验
GET(FC, "buffer %s", fBuffer); // 缓冲行
GET(FC, "player1 %s", player1); // 电脑 1 的名字
GET(FC, "player2 %s", player2); // 电脑 2 的名字
fgets(consoleColor, 32, fp); // 颜色属性
GET(FC, "playerName %s", playerName); // 玩家名字
GET(FC, "basis %d", &basis); // 底分
GET(FC, "title %s", consoleTitle); // 窗口标题
fclose(fp); // 关闭文件
SetConsoleTitle(consoleTitle); // 设置窗口标题
SetConsoleScreenBufferSize(HDO, size); // 设置缓冲区大小
mark = atoi(cd);
if (strlen(playerName) > 16 || strlen(player1) > 16 || strlen(player2) > 16) {
CLS; PR("\n\t注意:\n\t有玩家的名字过长。请重新设置名字,使其小于八个汉字。\n\t");
PR("Length of nick exceeds the limit. Reset to control within 16 Bytes.\n\t");
PUS; exit(0);
}
if (basis > 1000 ) {
CLS; PR("\n\t注意:\n\t底分过高。为创造良好的游戏体验,请调低底分。\n\t");
PR("Base score exceeds limit. Please lower it. \n\t");
PUS; exit(0);
}
}
/************* 游戏初始化 **************/
void initial() {
int i, j;
CONSOLE_CURSOR_INFO cursor_info = {1, 0}; // 定义一个光标结构体
SetConsoleCursorInfo(HDO, &cursor_info); // 隐藏控制台光标
getClientInfo(); //读取存档
//初始化扑克牌
for (i = 0; i < 13; i++)
for (j = 0; j < 4; j++) {
puker[i * 4 + j].num = i;
puker[i * 4 + j].color = j;
puker[i * 4 + j].owner = UNDEALT_PUKER;
}
puker[53].num = 14; // 大王赋值
puker[52].num = 13; // 小王赋值
puker[53].color = puker[52].color = 0;
puker[53].owner = puker[52].owner = UNDEALT_PUKER; // 出过的、没发的牌都标记为 UNDEALT_PUKER
puker[EMPTY_CARD].num = UNDEALT_PUKER; // 空牌指定的位置也标记为 UNDEALT_PUKER
//初始化玩家
for (i = 0; i < 3; i++) {
player[i].num = 0;
player[i].rank = 0;
player[i].isOver = 0;
for (j = 0; j < 20; j++)
player[i].card[j] = EMPTY_CARD;
}
//初始化出牌全局变量
pass.who = 0;
pass.turn = 0;
pass.basis = 1;
pass.special = 0;
pass.hasPrinted = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 32; j++) pass.record[i][j] = EMPTY_CARD;
pass.isPass[i] = 0;
}
}
/**************** 自动发牌 ***************/
void deal() {
int i = 0, j, rnd = 0, temp;
system(consoleColor);
srand((unsigned)time(NULL));
for (; i < 3; i++) { //抽出三张底牌
rnd = rand() % 54;
while (puker[rnd].owner != UNDEALT_PUKER) rnd = rand() % 54;
puker[rnd].owner = 0;
extra[i] = rnd;
PR("%d \n", extra[i]);
}
for (i = 0; i < 54; i++) { //发掉所有牌
if (puker[i].owner == UNDEALT_PUKER) {
rnd = rand() % 3; // 产生 [0,3) 的随机整数
while (player[rnd].num > 16) rnd = rand() % 3; // 若该玩家牌满,则重新选择牌主
puker[i].owner = rnd;
player[rnd].card[player[rnd].num] = i;
player[rnd].num++;
} else continue;
}
for (i = 0; i < 3; i++) { //将三张牌赋给地主
player[0].card[17 + i] = extra[i];
player[0].num++;
}
for (i = 0; i < 19; i++) //冒泡理牌,大->小
for (j = 0; j < 19 - i; j++) // j开始等于0,
if (player[0].card[j] > player[0].card[j + 1]) {
temp = player[0].card[j];
player[0].card[j] = player[0].card[j + 1];
player[0].card[j + 1] = temp;
}
printPuker();
}
/**************** 调试发牌 ***************/
void _deal() { int i = 0, rnd = 0; for (i = 0; i < 54; i++) { rnd = i > 19 ? i > 36 ? 2 : 1 : 0; puker[i].owner = rnd; player[rnd].card[player[rnd].num] = i; player[rnd].num++; } printPuker(); } // 只在调试环境下作用!
char levelStandard[23][7] = {"包身工","短工","长工","佃户","贫农","渔夫","猎人","中农","富农","掌柜","商人","衙役","小财主","大财主","小地主","大地主","知县","通判","知府","总督","巡抚","丞相","帝王"};
int standard[23] = {0,1000,2500,4000,8000,14000,23000,36500,50000,70000,100000,150000,220000,300000,400000,550000,770000,1000000,1400000,2000000,3000000,4500000,7000000};
/**************** 打印手牌 ****************/
void printPuker() {
CLS;
char joker[4] = "王";
char ch;
int i = 0, j;
int place;
//-------======= 打印3张牌 ======------//
gotoxy(HDO, 0, 0);
PR("%35s┏━━┓┏━━┓┏━━┓\n", space);
PR("%35s┃ ┃┃ ┃┃ ┃\n", space);
PR("%35s┃ ┃┃ ┃┃ ┃\n", space);
PR("%35s┃ ┃┃ ┃┃ ┃\n", space);
PR("%35s┗━━┛┗━━┛┗━━┛", space);
for (j = 0; j < 3; j++) {
ch = table[puker[extra[j]].num];
switch (ch) {
case 'X':
gotoxy(HDO, 37 + 8 * j, 1); PR("10");
gotoxy(HDO, 39 + 8 * j, 3); PR("10");
break;
case 'R':
gotoxy(HDO, 37 + 8 * j, 1);
if (puker[extra[j]].num == 13) PR("小");
else PR("大");
gotoxy(HDO, 39 + 8 * j, 3); PR("王");
break;
default:
gotoxy(HDO, 37 + 8 * j, 1); PR("%c", ch);
gotoxy(HDO, 39 + 8 * j, 3); PR("%2c", ch);
}
gotoxy(HDO, 39 + 8 * j, 2);
if (ch != 'R') PR("%c", color[puker[extra[j]].color]);
}
//-------======= 底分与倍数 ======------//
gotoxy(HDO, 68, 0); PR("底分:%d", basis);
gotoxy(HDO, 68, 1); PR("倍数:%d", pass.basis);
//-------======= 打印牌框 ======------//
if (player[0].num > 0) { //当手里有牌时执行
gotoxy(HDO, 45 - 2 * player[0].num, 21); // 将牌框按轴对称对齐
for (i = 0; i < player[0].num; i++) PR("┏━");
PR("━━━┓");
for (j = 22; j < 28; j++) {
gotoxy(HDO, 45 - 2 * player[0].num, j);
for (i = 0; i < player[0].num; i++) PR("┃ ");
PR(" ┃");
}
gotoxy(HDO, 45 - 2 * player[0].num, 28);
for (i = 0; i < player[0].num; i++) PR("┗━");
PR("━━━┛");
//-------======= 打印牌面 ======------//
place = 19;
for (i = player[0].num - 1; i >= 0; i--) { // 将牌面按轴对称对齐
gotoxy(HDO, 43 + 2 * player[0].num - 4 * i, 23);
PR("%2c", color[puker[player[0].card[i]].color]);
gotoxy(HDO, 43 + 2 * player[0].num - 4 * i, 22);
while (player[0].card[place] == EMPTY_CARD) place--;
ch = table[puker[player[0].card[place]].num];
switch (ch) {
case 'X': PR("10"); break;
default: PR("%2c", ch); break;
case 'R': //判断是大王还是小王
if (player[0].card[place] == 52) strcpy(space, "joker");
else strcpy(space, "JOKER");
for (j = 22; j < 27; j++) {
gotoxy(HDO, 43 + 2 * player[0].num - 4 * i, j);
PR("%2c", space[j - 22]);
}
}
place--;
}
//打印最后一张牌的牌面
gotoxy(HDO, 50 + 2 * player[0].num, 26); PR("%c", color[puker[player[0].card[0]].color]);
gotoxy(HDO, 49 + 2 * player[0].num, 27); PR("%2c", ch);
}
//-------======= 打印电脑 ======------//
strcpy(space, " "); gotoxy(HDO, 0, 7); PR(" ┏━━━━┓%73s┏━━━━┓\n", space); // 打印,没什么借鉴意义
for (j = 0; j < 6; j++) PR(" ┃┆ ┆┃%73s┃┆ ┆┃\n", space);
PR(" ┗━━━━┛%73s┗━━━━┛\n", space);
PR(" 农民:%6s%73s农民:%6s\n", player1, space, player2); PR(" 剩余: %2d 张%73s剩余: %2d 张\n", player[2].num, space, player[1].num);
gotoxy(HDO, 3, 8); PR("┌┈┈┐"); gotoxy(HDO, 3, 13); PR("└┈┈┘"); gotoxy(HDO, 88, 8); PR("┌┈┈┐"); gotoxy(HDO, 88, 13); PR("└┈┈┘");
gotoxy(HDO, 5, 10); PR("SIEE"); gotoxy(HDO, 90, 10); PR("SIEE"); gotoxy(HDO, 3, 11); PR("智慧信电"); gotoxy(HDO, 88, 11); PR("智慧信电");
gotoxy(HDO, 25, 30); PR("地主:%s", playerName); gotoxy(HDO, 25, 31); PR("剩余:%2d 张", player[0].num);
gotoxy(HDO, 60, 30); PR("等级:%s", playerLevel); gotoxy(HDO, 60, 31); PR("积分:%d", mark);
//for (i = 2; i > 0; i--) {gotoxy(HDO, 20, 33 - i);for (j = 16; j >= 0; j--) {PR("%c", color[puker[player[i].card[j]].color]);PR("%c ", table[puker[player[i].card[j]].num]); }PR("\n");} // 电脑手牌,仅在调试环境下生效
//-------======= 打印上回合记录 ======------//
if (pass.turn != 0 ) for (j = 1; j < 3; j++) {
if (pass.isPass[j] == 1 ) {
gotoxy(HDO, 144 - 64 * j, 11);
PR("不出");
} else {
for (i = 1; i < 32; i++)
if (pass.record[j][i] == EMPTY_CARD) {
place = i;
break;
}
printSmallPuker(j, place);
}
}
// 行列显示,仅在调试环境下作用
//for (i = 0; i < 90; i++) { gotoxy(HDO, i, 0); if (i % 10 )PR("%d", i % 10); } for (i = 0; i < 31; i++) { gotoxy(HDO, 0, i); PR("%d", i); }
}
/********************** 玩家出牌 **************************/
int play() {
char _cmd[32] = "";
int cmd[32];
int cmdNum = 0; // 记录每次出几张牌
int recNum = 0; // 记录上一回合玩家出了几张牌
int i = 0, j = 0, CtoI = 0; // CtoI 是字符转整形的临时变量
int special = 0; // 记录特殊牌类型:具体含义如何映射在后文会有注释
pass.isPass[0] = 0; // 初始化出牌标记
for (; i < 32; i++) cmd[i] = EMPTY_CARD; // 初始化 cmd
for (; j < 32; j++) pass.record[0][j] = EMPTY_CARD; // 初始化 record
CLS;
printPuker();
gotoxy(HDO, 0, 0);
PR("控制台\n\n");
PR("输入出牌:");
//-------======= 获取指令 ======------//
if (!pass.who) gets(_cmd);
cmdNum = strlen(_cmd);
if (!cmdNum && pass.hasPrinted) { // 如果出牌数为 0 ,且上家都出完牌,则可以确定玩家选择了不出牌
if (!pass.turn || pass.isPass[1] && pass.isPass[2]) {
PR("你不能不出牌!小老弟\n"); PUS;
return play();
}
gotoxy(HDO, 46, 19); PR("不出");
pass.isPass[0] = 1; // 标记该玩家为不出
for (j = 0; j < 32; j++) pass.record[0][j] = pass.record[2][j]; // 传递 record
pass.who++;
return AIplay();
}
i = j = 0;
while (i < cmdNum) {
if ((_cmd[i] < '1' || _cmd[i] > '9') && _cmd[i] != 'J' && _cmd[i] != 'Q' && _cmd[i] != 'K' && _cmd[i] != 'A' && _cmd[i] != 'j' && _cmd[i] != 'q' && _cmd[i] != 'k' && _cmd[i] != 'a' && _cmd[i] != '-' && _cmd[i] != '=') {
PR("错误:请输入正确的指令!\n"); PUS;
return play();
}
//-----===== 扑克点数转换为数值 ====----//
switch (_cmd[i]) {
case '1': cmd[j] = 7; i++; break;
case 'J': case 'j': cmd[j] = 8; break;
case 'Q': case 'q': cmd[j] = 9; break;
case 'K': case 'k': cmd[j] = 10; break;
case 'A': case 'a': cmd[j] = 11; break;
case '2': cmd[j] = 12; break;
case '-': cmd[j] = 13; break;
case '=': cmd[j] = 14; break;
default: CtoI = (int)_cmd[i]; if (CtoI > 50 && i < 58) cmd[j] = CtoI - 51; break;
}
i++, j++;
}
cmdNum = j; //单次出牌张数
//------------============ 判断指令是否可执行 ============------------//
// 特殊牌类型:0无效值,1单牌,2一对,3三张,4炸,5顺子,6连对,7飞机,8三带一,9三带一对,10四带二,11四带两对,12飞机带N,13飞机带N对,14王炸
// 1. 判断是否为特殊牌型
special = daipai(cmdNum, cmd); // 判断是否为带牌牌型
if (!special) special = shunzi_liandui(cmdNum, cmd); // 判断是否为顺子、连对、飞机
if (cmdNum == 2 && cmd[0] > 12 && cmd[1] > 12) special = 14; //出王炸不校验出牌顺序
isTherePuker(special, cmdNum, cmd); // 判断手上是否有足够的牌
// 2. 当1 ~ 4张牌时定义 special 类型
if (!special && cmdNum > 0 && cmdNum < 5) {
for (i = 0; i < cmdNum - 1; i++)
if (cmd[i] != cmd[i + 1]) {
PR("出牌不符合规则,请重新出牌!\n");
PUS; return play();
}
special = cmdNum;
}
// 3. 判断出牌是否符合出牌规则
if (!special) {
PR("出牌不符合规则,请重新出牌!\n");
PUS; return play();
}
if (pass.isPass[1] + pass.isPass[2] < 2 && pass.turn) { // 若其余玩家出过牌
for (i = 0; i < 32; i++) if (pass.record[2][i] == EMPTY_CARD) {
recNum = i;
break;
}
if (!comparePuker(pass.special, special, recNum, cmdNum, pass.record[2], cmd)) {
PR("出牌不能大过上家,请重新出牌%d!\n", special);
PUS; return play();
}
}
pass.special = special;
if (pass.special == 4 || pass.special == 14) {
pass.basis *= 2;
gotoxy(HDO, 68, 0); PR("底分:%d", basis);
gotoxy(HDO, 68, 1); PR("倍数:%d", pass.basis);
}
// 4. 抽出扑克牌,刷新页面
for (i = 0; i < cmdNum; i++)
for (j = 0; j < 20; j++)
if (puker[player[0].card[j]].num == cmd[i]) {
if (!i) pass.color = puker[player[0].card[j]].color;
puker[player[0].card[j]].owner = UNDEALT_PUKER;
player[0].card[j] = EMPTY_CARD;
player[0].num--;
break;
}
pass.who ++; //传递出牌权
if (pass.isPass[1] + pass.isPass[2] == 2 || !pass.turn) pass.special = special; //告知本次牌型
for (i = 0; i < 32; i++) pass.record[0][i] = cmd[i]; //传递存储 cmd
printPuker();
printSmallPuker(0, cmdNum);
pass.hasPrinted = 1; // 出牌指令挂起,防止误不出牌
// 5. 判断牌是否出完
if (!player[0].num){
player[0].isOver = 1;
Sleep(800);
for(i = 0; i < 3; i++) {
gotoxy(HDO, 42, 11); PR(" ");
//Sleep(500);
gotoxy(HDO, 42, 11); PR("地 主 胜 利");
//Sleep(500);
}
gotoxy(HDO, 38, 12); PUS;
over();
} else return AIplay();
//PR("%d ", pass.special);PUS;
return home();
}
/************************ 判断玩家出牌是否合法 ******************************/
int comparePuker(int recSpecial, int special, int recN, int n, int rec[32], int cmd[32]) {
if (special > 0 && special < 14 && special != 4) { // 当牌型不为炸时,只需判断第一张牌谁大谁小
if (recSpecial == special && rec[0] < cmd[0]) return 1;
} else if (special == 4) { // 当牌型为 4 炸时,判断谁大谁小
if (recSpecial != 4 && recSpecial != 14 || recSpecial == 4 && rec[0] < cmd[0]) return 1;
} else if (special == 14) return 1; // 王炸碾压芸芸众生!!
return 0;
}
/******************* 判断是否有牌 **********************/
int isTherePuker(int special, int n, int cmd[32]) {
int paiXu[32]; //临时牌序数组paiXu[]
int i, j, temp;
// 判断指令牌序
if (special < 8) {
for (i = 0; i < n - 1; i++) {
if (cmd[i] > cmd[i + 1]) {
PR("请按大小顺序出牌!\n"); PUS;
return play();
}
}
}
// 3. 判断是否有牌
//为避免带牌乱序,先排序 (临时牌序数组paiXu[])
for (i = 0; i < 32; i++) paiXu[i] = EMPTY_CARD;
for (i = 0; i < n; i++) paiXu[i] = cmd[i];
for (i = 0; i < n; i++)
for (j = 0; j < n - i; j++) // j开始等于0,
if (paiXu[j] > paiXu[j + 1]) {
temp = paiXu[j];
paiXu[j] = paiXu[j + 1];
paiXu[j + 1] = temp;
}
i = j = 0;
while (i < n && j < 20)
while (j < 20) {
if (puker[player[0].card[j]].num == paiXu[i]) {
i++, j++;
break;
}
j++;
}
if (i < n) {
PR("请在已有牌基础上出牌!\n");PUS;
return play();
}
return 0;
}
/************************** 判断顺子、连对或飞机 **************************/
int shunzi_liandui(int n, int cmd[32]) {
int k;
int _bool = 0;
for (k = 0; k < n - 1; k++) //非连续, 或存在 2 和 joker, 直接 return
if (cmd[k] + 1 < cmd[k + 1]) return 0;
for (k = 0; k < n; k++)
if (cmd[k] > 11) return 0;
if (n >= 5) { //顺子, 判断方法:各相邻牌是否相差且都相差 1 。
k = 0;
while (k < n - 1)
if (cmd[k] + 1 == cmd[k + 1]) k++;
else break;
if (k == n - 1) return 5;
}
if (n >= 6 && n % 2 == 0) { //连对, 判断方法:是否两两相连。
k = 0;
while (k < n - 2)
if (cmd[k] == cmd[k + 1] && cmd[k] + 1 == cmd[k + 2]) k += 2;
else break;
if (k == n - 2) {
if (cmd[k] == cmd[k + 1]) return 6;
else return 0;
}
}
if (n >= 6 && n % 3 == 0) { //飞机, 判断方法:是否三三相连。
k = 0;
while (k < n - 3)
if (cmd[k] == cmd[k + 1] && cmd[k + 1] == cmd[k + 2] && cmd[k] + 1 == cmd[k + 3]) k += 3;
else return 0;
if (k == n - 3) {
if (cmd[k] == cmd[k + 1] && cmd[k + 1] == cmd[k + 2]) return 7;
else return 0;
}
}
return 0;
}
/*********** 判断三带一,三带一对,四带二,四带两对,飞机带 N,飞机带 N 对 ***********/
int daipai(int n, int cmd[32]) {
int i;
if (cmd[0] == cmd[1] && cmd[1] == cmd[2]) { //先判断前三张是否一样
if (n == 4 && cmd[2] != cmd[3]) return 8; //三带一
if (n == 5 && cmd[3] == cmd[4]) return 9; //三带二
if (cmd[2] == cmd[3]) { //若第四张和第三张一样则晋升为四张
if (n == 6 && cmd[4] != cmd[5]) return 10; //四带一
if (n == 8 && cmd[4] == cmd[5] && cmd[6] == cmd[7] && cmd[5] != cmd[6]) return 11;//四带二
}
if (n > 4 && n % 4 == 0) { //判断飞机带 N 张
i = 3;
while (i < n - n / 4) {
if (cmd[i] < 12 && cmd[i] == cmd[i + 1] && cmd[i + 1] == cmd[i + 2] && cmd[i - 1] + 1 == cmd[i]) i += 3;
else return 0;
}
if (i == n - n / 4) {
if (cmd[i] == cmd[n - 1]) return 0;
else return 12;
}
}
if (n > 5 && n % 5 == 0) { //判断飞机带 N 对
i = 3;
while (i < n - 2 * (n / 5)) {
if (cmd[i] < 12 && cmd[i] == cmd[i + 1] && cmd[i + 1] == cmd[i + 2] && cmd[i - 1] + 1 == cmd[i]) i += 3;
else return 0;
}
if (i == n - 2 * (n / 5)) {
while (i < n) {
if (cmd[i] == cmd[i + 1] && cmd[i - 1] != cmd[i]) i += 2;
else return 0;
}
}
if (i == n) return 13;
}
}
return 0;
}
/******************************* 打印出牌缩略图 *********************************/
void printSmallPuker(int who, int n) {
int i, j, temp;
char ch;
char flower[4];
int smallPuker[32];
int borderY, borderX, contentX;
//根据不同出牌者定义打印坐标
//以下是显示配置,无太大借鉴意义
sw