#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<time.h>

简单AI之斗地主电脑出牌C措辞实现篇日常装逼日常飞飞到垃圾堆

#define Arr_Len(arr) (sizeof(arr)/sizeof(arr[0]))

#define maxn 18

/

1.出牌办法 以-1结束

一对8的出发:8 8 -1

/

int cod[maxn] = { 0 };

int mycod[maxn];

int chu[maxn];

int rtmp[maxn] = { 0 }, mtmp[maxn] = { 0 };

int mx, mn;

struct LianD

{

int en; //连对结尾的牌号

int du; //最靠近的度数

int cnt; //连对的个数

int tem; //临时存储的结尾牌号

//复制值函数

void copfun(struct LianD Ld){

Ld->cnt = cnt;

Ld->du = du;

Ld->en = en;

Ld->tem = tem;

}

//初始化

void init(){

en = du = cnt = tem = 0;

}

};

enum AlgTyNn{

ShunZi = 1,

LianDui

};

int cmp(const void arg, const void brg){

int ar = (int )arg;

int br = (int )brg;

return ar - br;

}

void init(){

int i, hopg, cnt = 0;

memset(mycod, 0, sizeof(mycod));

mycod[cnt] = 17;

for (i = 3; i<16; i++)

cod[i] = 4;

cod[16] = 1; //一对王

cod[17] = 1;

srand(time(NULL));

while (cnt<maxn){

hopg = rand() % maxn;

if (hopg>0 && cod[hopg] > 0){

cod[hopg]--;

mycod[++cnt] = hopg;

}

}

qsort(mycod + 1, cnt - 1, sizeof(mycod - 1), cmp);

}

//对方输出

void inputs(){

int cnt = 0;

memset(chu, 0, sizeof(chu));

while (1){

scanf(\"大众%d\"大众, &chu[++cnt]);

if (chu[cnt]<0) break;

}

chu[0] = cnt - 1; //最开头放置纸牌的数目

}

//打印剩余

void output(){

printf(\公众\n 剩牌系: \n\公众);

//剩余牌系

int cont = 0;

for (int j = 3; j<maxn; j++){

cont += mtmp[j];

for (int k = 0; k<mtmp[j]; k++){

printf(\公众%d \"大众, j);

}

}

mtmp[0] = cont;

printf(\公众\t剩牌数: [ %d ]\公众, mtmp[0]);

puts(\"大众\公众);

}

//计数排序

void connt(int tmp, const int ss[]){

//memset(tmp ,0 ,sizeof(tmp));

tmp[0] = ss[0];

for (int i = 1; i <= ss[0]; i++)

tmp[ss[i]]++; //计数排序

}

//判断是否有炸弹或者王炸

void ZhaDan(){

for (int i = 3; i<maxn; i++)

if (mtmp[i] == 4){

printf(\公众%d %d %d %d \公众, i, i, i, i);

mtmp[i] -= 4;

output();

return;

}

if (mtmp[16] == 1 && mtmp[17] == 1){

printf(\"大众%d %d \"大众, 16, 17);

mtmp[16] = mtmp[17] = 0;

output();

return;

}

puts(\"大众没有牌能压过!
\公众);

return;

}

//如果是连对处理方案

void AlgLDOrShZi(int var){

int i = mn + 1, len = mx - mn + 1, kk = 0;

struct LianD Ld, Tmpld;

Ld.init();

//韶光繁芜度为0(n^2)

for (i = mn + 1; i<15; i++){

Tmpld.init();

Tmpld.tem = i;

for (int j = i; j<i + len; j++){

if (mtmp[j] >= var){

if (mtmp[j] == var){

Tmpld.du++;

}

Tmpld.cnt++;

}

else{

Tmpld.init();

Tmpld.tem = j + 1;

}

if (Tmpld.cnt == len){

Tmpld.en = Tmpld.tem;

if (Ld.en == 0 || Ld.du<Tmpld.du)

Tmpld.copfun(&Ld);

break;

}

}

}

if (Ld.cnt == len){

puts(\"大众提示:\"大众);

for (i = Ld.en; i<Ld.en + len; i++){

mtmp[i] -= var;

kk = 0;

while (kk++<var)

printf(\"大众%d \"大众, i);

}

output();

}

else{

//寻求炸弹或者王炸

ZhaDan();

}

}

//三带的处理情形

void AlgShanDai(){

int pos = 0, cnt = 0, res = 0, fcnt = 0;

int mcnt = 0, mpos = 0;

//剖析牌型

for (int i = mn; i <= mx; i++){

if (rtmp[i] == 3){

pos = i;

cnt++;

}

else if (rtmp[i]>0){

res += rtmp[i]; //统计剩余牌的数量

fcnt++;

}

}

if ((fcnt == cnt&&res%cnt == 0) || (fcnt<cnt && (fcntres == cnt || 0 == res)));

else{

puts(\"大众输出的牌不符合规则!
请重新输出:\"大众);

return;

}

res /= cnt;

for (int i = pos - cnt + 2; i <= pos; i++){

if (rtmp[i] != 3){

puts(\"大众输出的牌不符合规则!
请重新输出:\"大众);

return;

}

}

//如果为三带情形 即 cnt =1

for (int i = pos - cnt + 2; i<17; i++){

if (mtmp[i] == 3){

mpos = i;

mcnt++;

}

else

mcnt = 0;

if (mcnt == cnt) break;

}

//查询副牌是否能够知足

if (mcnt == cnt){

//解释有办理方案

int stpos = mpos - cnt + 1;

int src[maxn] = { 0 }, tt = 0;

bool tag = false;

for (int i = 3; i<17; i++){

//知足不再连续范围之内的即可333444不能为3,4

if (i<stpos || i>mpos){

if (mtmp[i] >= res){

for (int kk = 0; kk<mtmp[i]; kk += res){

src[tt++] = i;

if (tt == cnt){

tag = true;

break;

}

}

}

}

if (tag) break;

}

if (tt == cnt){

//则办理方案为

int mstpos = mpos - cnt + 1;

for (int i = mstpos; i <= mpos; i++){

printf(\"大众%d %d %d \公众, i, i, i);

mtmp[i] -= 3;

}

//打印副牌

for (int i = 0; i<tt; i++){

for (int k = 0; k<res; k++){

printf(\"大众%d \"大众, src[i]);

}

mtmp[src[i]] -= res;

}

output(); //打印剩余牌

}

}

else{

//查询是否有炸弹

ZhaDan();

}

}

//四带情形

void AlgSiDai(){

if (chu[0]>4) ZhaDan();

else{

for (int i = chu[1] + 1; i<15; i++){

if (mtmp[i] == 4){

printf(\公众%d %d %d %d \公众, i, i, i, i);

mtmp[i] -= 4;

output();

return;

}

}

if (mtmp[16] == 1 && mtmp[17] == 1){

printf(\"大众%d %d \"大众, 16, 17);

mtmp[16] = mtmp[17] = 0;

output();

return;

}

puts(\"大众没有牌能压过!
\"大众);

return;

}

}

//对子的情形

void AlgDuiZi(){

for (int i = chu[1] + 1; i<16; i++)

{

if (mtmp[i]>1 && mtmp[i]<4){

printf(\"大众%d %d \n\"大众, i, i);

mtmp[i] -= 2;

output();

return;

}

}

ZhaDan();

}

//对付个子的情形

void AlgGreZi(){

for (int i = chu[1] + 1; i<18; i++)

{

if (mtmp[i]>0 && mtmp[i]<4){

printf(\公众%d \n\公众, i);

mtmp[i] -= 1;

output();

return;

}

}

ZhaDan();

}

//查询对应的方案

//对子

bool IsDuiZi(){

if (chu[0] == 2) //则必定是对子

return true;

return false;

}

//个子

bool IsGreZi(){

if (chu[0] == 1) //则必定是对子

return true;

return false;

}

//判断是否是顺子

bool IsShunZi(){

//顺子的条件

if (chu[0]>4){

if ((mx - mn + 1 == chu[0]) && mx<15)

return true;

}

return false;

}

//判断是否是连对

bool IsLianDui(){

if (chu[0]>5 && mx<15){

for (int i = mn; i <= mx; i++)

if (rtmp[i] != LianDui)

return false;

return true;

}

return false;

}

//判断是否是三带

bool IsShanDai(){

for (int i = mn; i <= mx; i++)

if (rtmp[i] == 3)

return true;

return false;

}

//判断是否是四带或者炸弹

bool IsSiDai(){

for (int i = mn; i <= mx; i++)

if (rtmp[i] == 4)

return true;

return false;

}

//统计判断

void AlgMxn(){

//求最大值,最小值

for (int i = 3; i <= 17; i++)

if (rtmp[i]>0){

mn = i;

break;

}

for (int i = 17; i >= 3; i--)

if (rtmp[i]>0){

mx = i;

break;

}

}

void print(){

int i;

for (i = 1; i<17; i++)

printf(\"大众%d \公众, mycod[i]);

printf(\"大众%d\n\公众, mycod[17]);

}

//检测出牌方

bool checked(){

for (int i = 1; i<maxn; i++){

if (cod[i]<rtmp[i])

return false;

}

if (IsGreZi()

|| IsDuiZi()

|| IsShunZi()

|| IsSiDai()

|| IsShanDai()){

for (int i = 1; i <= chu[0]; i++){

cod[chu[i]]--;

}

}

return true;

//如果为一对王

if (chu[0] == 2 && mtmp[16] == 1 && mtmp[17] == 1)

return true;

return false;

}

int main(int argc, char argv)

{

init();

memset(mtmp, 0, sizeof(mtmp));

connt(mtmp, mycod);

print();

while (true){

printf(\"大众请出牌:\n\"大众);

while (1){

inputs();

memset(rtmp, 0, sizeof(rtmp));

connt(rtmp, chu);

AlgMxn();

if (checked()) break;

else

puts(\"大众输出的牌不符合规则!
请重新输出:\"大众);

}

//如果知足顺子

if (IsGreZi())

AlgGreZi();

else

if (IsDuiZi())

AlgDuiZi();

else

if (IsShunZi())

AlgLDOrShZi(ShunZi);

else

if (IsLianDui())

AlgLDOrShZi(LianDui); //对付连对的情形

else

if (IsShanDai())

AlgShanDai();

else

if (IsSiDai())

AlgSiDai();

if (mtmp[0]<1){

puts(\公众恭喜你,win!\"大众);

break;

};

}

return 0;

}