小游戏代码及说明
//
/*
6-6
二十一点游戏
*/
#包含“conio.h”
#包含" stdlib.h "
#包含“time.h”
#包含“math.h”
#include "string.h"/*
从一副扑克牌中任选四张。
2-10按点数计算(为方便起见,10用T表示),J、Q、K、A统一按1计算。
要求通过加减乘除四则运算得到数字24。
这个程序可以随机抽卡,用试错法求解。
*/void GivePuzzle(char* buf)
{
char card[] = {'A ',' 2 ',' 3 ',' 4 ',' 5 ',' 6 ',' 7 ',' 8 ',' 9 ',' T ',' J ',' Q ',' K ' };for(int I = 0;我& lt4;i++){
buf[I]= card[rand()% 13];
}
}
无效洗牌(char * buf)
{
for(int I = 0;我& lt5;i++){
int k = rand()% 4;
char t = buf[k];
buf[k]= buf[0];
buf[0]= t;
}
}
int GetCardValue(int c)
{
if(c=='T ')返回10;
if(c & gt;= ' 0 ' & amp& ampc & lt='9 ')返回c-' 0 ';
返回1;
}
char GetOper(int n)
{
开关(n)
{
案例0:
返回“+”;
案例1:
返回'-';
案例二:
返回“*”;
案例三:
返回“/”;
} return“”;
} double my calc(double op 1,double op2,int oper)
{
开关(操作)
{
案例0:
返回op 1+op2;
案例1:
返回op 1-op2;
案例二:
返回op 1 * op2;
案例三:
if(fabs(op2)>0.0001)
返回op 1/op2;
其他
返回100000;
}返回0;
}
void MakeAnswer(char* answer,int type,char* question,int* oper)
{
char p[4][3];
for(int I = 0;我& lt4;i++)
{
if(问题[i] == 'T ')
strcpy(p[i]," 10 ");
其他
sprintf(p[i]," %c ",问题[I]);
}
开关(类型)
{
案例0:
sprintf(答案," %s %c (%s %c (%s %c %s))",
p[0],GetOper(oper[0]),p[1],GetOper(oper[1]),p[2],GetOper(oper[2]),p[3]);
打破;
案例1:
sprintf(答案," %s %c ((%s %c %s) %c %s)",
p[0],GetOper(oper[0]),p[1],GetOper(oper[1]),p[2],GetOper(oper[2]),p[3]);
打破;
案例二:
sprintf(答案,"(%s %c %s) %c (%s %c %s)",
p[0],GetOper(oper[0]),p[1],GetOper(oper[1]),p[2],GetOper(oper[2]),p[3]);
打破;
案例三:
sprintf(答案,“((%s %c %s) %c %s) %c %s”,
p[0],GetOper(oper[0]),p[1],GetOper(oper[1]),p[2],GetOper(oper[2]),p[3]);
打破;
案例4:
sprintf(答案,"(%s %c (%s %c %s)) %c %s ",
p[0],GetOper(oper[0]),p[1],GetOper(oper[1]),p[2],GetOper(oper[2]),p[3]);
打破;
}
}
bool TestResolve(char* question,int* oper,char*答案)
{
//等待考生完成。
int type[5]={0,1,2,3,4 };//计算类型
双p[4];
double sum = 0;
//
for(int I = 0;我& lt4;I++) //循环获得积分。
{
p[I]= GetCardValue(int(question[I]));
} for(I = 0;我& lt5;i++)
{
MakeAnswer(答案,类型[i],问题,操作);//获得可能的答案
开关(类型[i])
{
案例0:
sum=MyCalcu(p[0],MyCalcu( p[1],MyCalcu(p[2],p[3],oper[2]),oper[1],oper[0]);//A*(B*(c*D))
打破;
案例1:
sum=MyCalcu(p[0],MyCalcu(MyCalcu(p[1],p[2],oper[1]),p[3],oper[2],oper[0]);//A *(B * C)* D)
打破;
案例二:
sum=MyCalcu(MyCalcu(p[0],p[1],oper[0]),MyCalcu(p[2],p[3],oper[2],oper[1]);// (A*B)*(C*D)
打破;
案例三:
sum = my calcu(my calcu(my calcu(p[0],p[1],oper[0]),p[2],oper[1]),p[3],oper[2]);//((A*B)*C)*D
打破;
案例4:
sum=MyCalcu(MyCalcu(p[0],MyCalcu(p[1],p[2],oper[1]),oper[0],p[3],oper[2]);//(A*(B*C))*D
打破;
}
if(sum==24)返回true
}
返回false
}
/*
使用随机试错法:是通过随机数生成加减乘除组合,并通过大量测试命中的解决方案。
提示:
1.需要考虑用括号控制计算顺序的问题,比如:(10-4) * (3+A),其实计算顺序的个数是有限的:
A*(B*(c*D))
a *(B * C)* D)
(A*B)*(C*D)
((A*B)*C)*D
(A*(B*C))*D
2.需要考虑计算结果是一个分数的情况:(3+(3/7)) * 7。
3.标题中卡片的位置可以随意交换。
*/
bool TryResolve(char* question,char* answer)
{
int oper[3];//存储运算符,0:加法1:减法2:乘法3:除法。
for(int I = 0;我& lt1000 * 1000;i++)
{
//打乱卡片的顺序
洗牌(问题);
//随机生成的运算符
for(int j = 0;j & lt3;j++)
oper[j]= rand()% 4;if( TestResolve(question,oper,answer))返回true
}返回false
}
int main(int argc,char* argv[])
{
//初始化随机种子
srand((无符号)时间(空));char buf 1[4];//主题
char buf 2[30];//回答
printf(" * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ");
Printf("计算24 \ n ");
Printf("A J Q K按1计算,其他按卡点计算\ n ");
Printf("目标是通过四次运算组合结果:24 \ n ");
printf(" * * * * * * * * * * * * * * * * * * * * * * * * * \ n \ n ");
for(;;)
{
give puzzle(buf 1);//给出一个问题
printf(" Title:");
for(int j = 0;j & lt4;j++){
if( buf1[j] == 'T ')
printf(" 10 ");
其他
printf("%c ",buf 1[j]);
} printf(" \ n按任意键查看答案...\ n ");
getch();If (try resolve (buf1,buf 2))//解决问题
Printf ("reference: %s\n ",buf 2);
其他
Printf("可能无解...\ n ");Printf("按任意键进入下一个主题,按X键退出...\ n ");
if(getch()= = ' x ')break;
}返回0;
}