/*
*24点
*田晨
*2018/10/6
*/
#include<stdio.h> //输入/输出库。
#include<stdlib.h> //标准工具库函数库。
#include<string.h> //字符函数库。
#include<ctype.h> //字符函数库。
#include<time.h> //时间函数库。
#include<dos.h> //系统接口函数库。
#include<easyx.h> //绘图函数库。
#include<conio.h> //控制台输入/输出函数库。
/*预处理*/
#define BeiJingColor1 RGB(225,225,255) //定义背景色
#define BeiJingColor2 RGB(255,255,255) //定义背景色
MOUSEMSG Mouse; //定义鼠标信息变量Mouse
/*声明自定义函数程序块*/
void WindowsInit(); //窗口初始化函数。
void DrawPoker(int x,int y,int Length,int Wideth,int Distance); //绘制扑克牌。
void DrawButton(int x,int y,int Length,int Wideth,char* String); //绘制按钮。
void ClearMessage1(); //清空消息区。
void ClearMessage2(int x,int y,int Length,int Wideth,int Distance); //清空扑克牌。
float jskhsz(); //去除括号并算括号内的式子,并分离十进制字符和加减乘除等字符,并把十进制字符转为浮点型的函数。
float jsccsz(); //计算式子中的乘除的函数。
float jsjjsz(); //计算式子中的加减函数。
int fjxt(int K,int L,int i); //判定系统是否出两张牌并防止出两张相同的牌的函数。
void chupai(); //出牌函数。
int yzmysz(); //检验用户输入式子是否满足使用所给的牌值和应用规定的符号的函数。
int NUM(const void *a,const void *b); //自定义比较函数
int khpd(int z,int f,int kh1[],int kh2[]); //判断括号是否符合规定函数,符合就返回1,不符合就返回0。
void PD24d(float UE); //检验用户输入式子是否等于24点的函数。
void gueize(); //输出规则函数。
/*主函数*/
int main() {
int c,i=1;
initgraph(840, 700);
WindowsInit(); //创建窗口。
chupai(); //开始出牌。
gueize(); //说明规则。
c=1;
do {
FlushMouseMsgBuffer(); //清除鼠标信息。
Mouse=GetMouseMsg(); //获取鼠标信息。
if(Mouse.x>700&&Mouse.x<820&&Mouse.mkLButton) { //bool mkLButton;(鼠标左键是否按下)
if(Mouse.y>140&&Mouse.y<180) { //重新出牌按钮坐标。
chupai();
c=1;
}
if(Mouse.y>200&&Mouse.y<240&&c==1) { //输入答案按钮坐标,其中c控制输入答案次数。
yzmysz();
c=0;
}
}
if(Mouse.y>300&&Mouse.y<340&&Mouse.mkLButton) { //bool mkLButton;(鼠标左键是否按下)
if(Mouse.x>490&&Mouse.x<650) { //查看游戏规则按钮坐标。
gueize();
}
if(Mouse.x>660&&Mouse.x<780) { //结束游戏按钮坐标。
closegraph(); //关闭界面
}
}
} while(i);
return 0;
}
void paint() {
loadimage(NULL, _T("D:\\card\1.jpg"));
}
/*界面程序块*/
void WindowsInit() {
setbkcolor(BeiJingColor1); //更换背景色
cleardevice(); //清除图形屏幕
settextstyle(40, 15, _T("微软雅黑")); //绘制标题
settextcolor(BLACK);
outtextxy(50,30,"欢迎来到24点游戏!!");
setlinecolor(BLACK);
DrawButton(700,140,120,40,"重新发牌"); //绘制按钮
DrawButton(700,200,120,40,"输入答案");
DrawButton(490,300,160,40,"查看游戏规则");
DrawButton(660,300,120,40,"结束游戏");
DrawButton(20,300,150,40,"信息提示区");
rectangle(20,350,780,680);
ClearMessage1();
DrawPoker(20,140,150,105,150); //绘制扑克牌
}
/*
*功能: 用于清除信息显示区的内容。
*形参: 无。
*返回值:无。
*/
void ClearMessage1() {
setfillcolor(BeiJingColor2);
solidrectangle(21,351,779,679);
}
/*
*功能: 用于清除扑克牌的内容。
*形参: 四张扑克牌的左上角位置x,y,长度Length,宽度Wideth,间距Distance。
*返回值: 无。
*/
void ClearMessage2(int x,int y,int Length,int Wideth,int Distance) {
int i;
setfillcolor(BeiJingColor1);
for(i=0; i<4; i++) {
solidrectangle(x+Distance*i+1,y+1,x+Wideth+Distance*i-1,y+Length-1);
}
}
/*
*功能: 绘制扑克牌图像。
*形参: 四张扑克牌的左上角位置x,y,长度Length,宽度Wideth,间距Distance。
*返回值:四个矩形方框(扑克牌外形)。
*/
void DrawPoker(int x,int y,int Length,int Wideth,int Distance) {
int i;
for(i=0; i<4; i++) {
rectangle(x+Distance*i,y,x+Wideth+Distance*i,y+Length);
}
}
/*
*功能: 绘制一个按钮
*形参: 按钮左上角坐标x,y,按钮长度Length,宽度Wideth,按钮中内容String
*返回值:一个按钮和其内容。
*/
void DrawButton(int x,int y,int Length,int Wideth,char* String) {
rectangle(x,y,x+Length,y+Wideth);
settextstyle(24, 0, _T("宋体"));
outtextxy(x+10,y+10,String);
}
/*计算式子程序块*/
int n;
char mysz[20]; //定义一数组存放用用户输入的式子。
/*
*功能: 去除括号并算括号内的式子,并分离十进制字符和加减乘除等字符,并把十进制字符转为浮点型。
*形参: 无。
*返回值:式子中的数或括号内的结果。
*/
float jskhsz() {
char sz[20];
float sumf;
int i;
if(mysz[n]=='(') { //计算括号内的式子。
n++;
sumf=jsjjsz();
}
if(mysz[n]==')')
n++;
for(i=0; isdigit(mysz[n])!=0; n++) { //判断用户输入式子是否有十进制字符,有则执行。(P53.isdigit()函数:判断字符是否是十进制字符,是则返回非0,否返回0。)
sz[i]=mysz[n];
i++;
sz[i]='\0';
sumf=(float)atoi(sz); //(float)强制转浮点型,(P320.atoi()函数:将字符串转整型。)
}
return(sumf);
}
/*
*功能: 计算式子中的乘除。
*形参: 无。
*返回值:乘除所得的值。
*/
float jsccsz() {
float sumc;
sumc=jskhsz(); //括号内式子优先级高,所以先运行flsf()函数。
while(mysz[n]=='*'||mysz[n]=='/') {
if(mysz[n]=='*') {
n++;
sumc=sumc*jskhsz(); //遇到乘号先调用flsf()函数检验下面式子是否有括号。
}
if(mysz[n]=='/') {
n++;
sumc=sumc/jskhsz();
}
}
return(sumc);
}
/*
*功能: 计算式子中的加减。
*形参: 无。
*返回值:式子总值。
*/
float jsjjsz() {
float sumj;
sumj=jsccsz(); //乘除的优先级更高,所以先运行chengchu()函数。
while(mysz[n]=='-'||mysz[n]=='+') {
if(mysz[n]=='+') {
n++;
sumj=sumj+jsjjsz(); //遇到加号先调用chenchu()函数检验下面式子是否有乘号。
}
if(mysz[n]=='-') {
n++;
sumj=sumj-jsjjsz();
}
}
return(sumj);
}
/*发牌与处理牌程序块*/
int cpz[4],CP1[5],CP2[5]; //定义数组cpz[4]存放四张牌对应的值。
/*
*功能: 判定系统是否出两张相同的牌并防止出两张相同的牌。
*形参: 确定牌第一字母的变量K,确定牌第二字母的变量J,确定发到第几张牌的变量i。
*返回值:1(当前牌与前面牌有相同),0(当前牌与前面牌不相同)
*/
int fjxt(int K,int L,int i) {
int p=0,j,t;
if(i==0) {
p=1;
} else {
for(j=0; j<i; j++) { //防止出两张相同的牌。
if(K==CP1[j]) { //先判定是否与第一个字符相同。
for(t=0; t<i; t++) { //在判定是否与第二个字符相同。
if(L==CP2[t]) {
goto kl;
}
}
}
}
kl:
if(j==i) { //若能运行完上面程序段,就可以输出。
p=1;
}
}
return(p);
}
/*
*功能: 出牌函数。
*形参: 无。
*返回值:无。
*/
void chupai() {
time_t t;
int X,Y,K,L,i,p;
char cpai[1];
char str2[16]="card\\";
int m[4];
X=0;
Y=0; //变量赋初值。
srand((unsigned)time(&t)); //初始化随机数发生器。(srand():初始化随机数发生器函数。)
ClearMessage2(20,140,150,105,150);
for(i=0; i<4; i++) {
K=rand()%5; //随机出一个0 ~ 4范围内的数,对应pai1数组中对应牌的第一字符。(rand():随机数发生器函数。)
CP1[i]=K;
if(K!=4) {
L=rand()%13; //随机出一个0 ~ 12范围内的数,对应pai2数组中对应牌的第二字符。
CP2[i]=L;
p=fjxt(K,L,i);
if(p==1) {
cpz[i]=L+1; //L+1为每张牌相应的值。
IMAGE img1,img2,img3,img4;
if (K==0) {
char str1[2];
char filename[]=".jpg";
m[i]=L+1;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img1, _T(str1));
putimage(20+i*150, 140, &img1);
} else if(K==1) {
char str1[2];
char filename[]=".jpg";
m[i]=L+14;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img2, _T(str1));
putimage(20+i*150, 140, &img2);
} else if (K==2) {
char str1[2];
char filename[]=".jpg";
m[i]=L+27;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img3, _T(str1));
putimage(20+i*150, 140, &img3);
} else if (K==3) {
char str1[2];
char filename[]=".jpg";
m[i]=L+40;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img4, _T(str1));
putimage(20+i*150, 140, &img4);
}
} else
i--;
} else { //大王和小王两张牌处理和输出。
Y++;
IMAGE img5,img6;
if(Y==1) { //大王和小王就两张牌,第一次无条件输出。
L=rand()%2; //随机出一个0 ~ 1范围内的数。
X=L; //变量X存放第一次随机输出的值。
cpz[i]=1;
if (L==0) {
char str1[2];
char filename[]=".jpg";
m[i]=53;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img5, _T(str1));
putimage(20+i*150, 140, &img5);
}
else if (L==1)
{
char str1[2];
char filename[]=".jpg";
m[i]=54;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img6, _T(str1));
putimage(20+i*150, 140, &img6);
}
} else if(Y==2) {
L=rand()%2;
if(X!=L) { //与第一次随机输出的值对比,若不相同则可以输出。
cpz[i]=1;
if (L==0) {
char str1[2];
char filename[]=".jpg";
m[i]=53;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img5, _T(str1));
putimage(20+i*150, 140, &img5);
}
else if (L==1)
{
char str1[2];
char filename[]=".jpg";
m[i]=54;
itoa(m[i],str1,10);
strcat(str1,filename);
loadimage(&img6, _T(str1));
putimage(20+i*150, 140, &img6);
}
} else
i--;
} else
i--;
}
}
ClearMessage1();
}
/*输入式子与检验用户输入式子是否正确程序块*/
int s1=0;
/*
*功能: 输入式子与检验用户输入式子是否满足使用所给的牌值和应用规定的符号。
*形参: 无。
*返回值:无。
*/
int yzmysz() {
char sz[5],szz[10];
int p,q,Q,M,MN,i,x,sc,KJ,z,f,zf,h1,h2,kh1[5],kh2[5];
int m,mypz[4];
float A;
loop:
InputBox(mysz,20,"请输入您以为正确的式子","输入","",0,0,true );
settextstyle(30, 0, _T("微软雅黑"));
outtextxy(30,360,"正在检验您的式子。。。。");
p=0;
q=0;
Q=0;
M=0;
MN=0;
sc=1;
KJ=0;
z=0;
f=0;
h1=0;
h2=0; //变量赋初值。
for(x=0,i=4; mysz[x]!='\0';) { //检验用户输入牌值与电脑给出的牌值是否相等。
if(isdigit(mysz[x])==0)
x++;
if(isdigit(mysz[x])!=0)
i--;
for(m=0; isdigit(mysz[x])!=0; x++) { //(isdigit()函数:判断字符是否是十进制数,是则执行函数,否则跳出。)
sz[m]=mysz[x];
m++;
sz[m]='\0';
mypz[i]=atoi(sz); //(atoi()函数:字符串转整型值。)
}
}
qsort(cpz,4,sizeof(cpz[0]),NUM); //快速排序。(qsort()函数:快速排序函数。)
qsort(mypz,4,sizeof(mypz[0]),NUM);
for(i=0; i<4; i++) { //用户输入的牌值和电脑出的牌值对比。
if(i>=4) {
p=1;
} else if(cpz[i]!=mypz[i]) {
p=1; //出现不相等p等于1。
}
}
for(x=0; mysz[x]!='\0'; x++) { //检验用户输入式子的数字是否超过四个,超过为错。
if(isdigit(mysz[x])==0) { //(isdigit()函数:判断字符是否是十进制数,是则执行函数,否则跳出。)
sc++;
}
if(sc>4) {
p=1;
}
}
if(p==1) { //p=1用户使用数不对。
setbkcolor(BeiJingColor2);
s1++;
ClearMessage1();
outtextxy(30,360,"您使用数不对哦!");
outtextxy(30,400,"您还有一次重新输入的机会!");
outtextxy(30,440,"您所输入式子为:");
outtextxy(30,480,mysz);
if(s1<=1) //判断输入次数是否超过设定的两次。
goto loop;
else {
setbkcolor(BeiJingColor2);
ClearMessage1();
outtextxy(30,360,"您使用数不对并且次数用完!");
outtextxy(30,400,"本次游戏结束。");
outtextxy(30,440,"您所输入式子为:");
outtextxy(30,480,mysz);
outtextxy(30,520,"如果想继续游戏请按重新发牌。");
s1=0;
goto ex;
}
} else if(p==0) { //p=0用户使用数正确,判断用户使用符号是否有错误。
for(x=0; mysz[x]!='\0'; x++) {
if(isdigit(mysz[x])==0) {
if(mysz[x]<40||mysz[x]>47||mysz[x]==44||mysz[x]==46) { //检验用户输入加减乘除等符号与规定的符号是否相等(用ASCII检验)
KJ=1;
goto sood;
} else if(mysz[x]==42||mysz[x]==43||mysz[x]==45||mysz[x]==47) { //'+''-''*''/'
if(isdigit(mysz[x-1])==0&&mysz[x-1]!=41) { //'+''-''*''/'前只能为十进制字符和')'
KJ=1;
goto sood;
}
if(isdigit(mysz[x+1])==0&&mysz[x+1]!=40) { //'+''-''*''/'后只能为十进制字符和'('
KJ=1;
goto sood;
}
} else {
if(mysz[x]==40) {
if(mysz[x+1]==41) { //出现'()'为错。
KJ=1;
goto sood;
}
z++; //记录'('的个数。
kh1[h1]=x; //记录'('的位置。
h1++;
}
if(mysz[x]==41) {
f++; //记录')'的个数。
kh2[h2]=x; //记录')'的位置。
h2++;
}
}
}
}
zf=khpd(z,f,kh1,kh2);
sood:
if(KJ==1||zf==0) {
setbkcolor(BeiJingColor2);
s1++;
ClearMessage1();
outtextxy(30,360,"您的符号使用号有错误哦!");
outtextxy(30,400,"您还有一次重新输入的机会!");
outtextxy(30,440,"您所输入式子为:");
outtextxy(30,480,mysz);
if(s1<=1) //判断输入次数是否超过设定的两次。
goto loop;
else {
setbkcolor(BeiJingColor2);
ClearMessage1();
outtextxy(30,360,"您的符号使用有错误并且次数用完!");
outtextxy(30,400,"本次游戏结束。");
outtextxy(30,440,"您所输入式子为:");
outtextxy(30,480,mysz);
outtextxy(30,520,"如果想继续游戏请按重新发牌。");
s1=0;
goto ex;
}
}
}
setbkcolor(BeiJingColor2);
ClearMessage1();
outtextxy(30,360,"正在检验您输入的式子是否等于24。。。");
outtextxy(30,400,"您所输入式子为:");
outtextxy(30,440,mysz);
n=0; //每次运行jiajian()函数都把n重新赋0值。
sprintf(szz,"%f",jsjjsz()); //把式子结果存于szz数组。
outtextxy(30,480,"计算结果为:\n");
outtextxy(30,520,szz);
n=0;
A=jsjjsz(); //计算用户输入式子。
PD24d(A); //调用PD24d()函数判断用户输入式子是否等于24点。
ex:
return 0;
}
/*
*功能: 自定义比较函数。
*形参: 数a,数b。
*返回值:数a与数b的差值。
*/
int NUM(const void *a,const void *b) {
return *(int *)a-*(int *)b;
}
/*
*功能: 判断括号是否符合规定。
*形参: "("的个数z,")"的个数f,存放'('位置的数组kh1[],存放')'位置的数组kh2[]。
*返回值:1(括号使用正确),0(括号使用错误)
*/
int khpd(int z,int f,int kh1[],int kh2[]) {
int i,zf=1;
if(z!=f) { //'('和')'个数比较。
zf=0;
} else {
for(i=0; i<z; i++) {
if(kh1[i]>kh2[i]) { //'('和')'位置比较。
zf=0;
}
}
}
return(zf);
}
/*
*功能: 检验用户输入式子结果是否等于24点。
*形参: 式子总值UE。
*返回值:无。
*/
void PD24d(float UE) {
if(UE==24.000000) {
outtextxy(30,560,"恭喜您通过!!!");
} else {
outtextxy(30,560,"您的计算有误!!!");
outtextxy(30,600,"本次游戏结束。");
}
}
/*输出规则的程序块*/
/*
*功能: 将规则输出到信息提示区。
*形参: 无。
*返回值:无。
*/
void gueize() {
ClearMessage1();
setbkcolor(BeiJingColor2);
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(30,360,"请仔细阅读规则:");
outtextxy(30,380,"一副牌54张牌,黑桃1~K,红桃1~k,方块1~k草花1~k以及大小王。");
outtextxy(30,400,"其中,A,K,Q,J及大、小王的点值分别为:1,13,12,11,1,1。其余点值就是牌值。");
}
文件资源