/* 编写人@wonder 版本:v0.1 因为对这个游戏感兴趣,想到用编程求解法, 固编写了本程序。 本程序用来求游戏《计算器-游戏》的解法。 输入: 开始数字start,最大步数step,目标数字target, 为三个数字, (如123 3 321) 与可用的计算按钮 为若干字符串,用空格隔开,输入e结束。 (如r13 *-15 r < e)。 输出: 所有可行的按键顺序,可能有多个输出。 目前集成的运算有: +n -n *n /n <n______<<去掉最后一位 n_______在最后加上数字n n=》m___将所有数字n换为数字m ^n______幂运算 !_______+/- r_______reverse s_______sum {_______<shift }_______>shift m_______mirror 共14种运算 可以求出131关以内的解 基本算法: 1.输入数据 2.用递归找出所有可能的操作,生成一操作顺序码 3.对每个操作码计算,如果可行就输出 以后应优化一下算法,每次递归进行一次运算 继续增加运算,求出所有关卡。 */ #include<stdio.h> #include<stdlib.h> #define R 10 int start,step,target; int OPNumber=0; char operate[6][R]; int debug = 0;//将值设为1开启debug模式 void inputDate() { char OPstring[R]; int i,j; printf("input start,step,target="); scanf("%d%d%d",&start,&step,&target); printf("input operate:\n"); for(i=0;i<6;i++){ scanf("%s",&OPstring); if(OPstring[0] == 'e')break; for(j=0;j<R;j++){ operate[i][j] = OPstring[j]; } OPNumber++; } system("cls");//输入结束,清屏 printf("start=%d,step=%d,target=%d\n",start,step,target); printf("all operate are:\n"); for(i=0;i<OPNumber;i++){ printf(operate[i]); printf("\n"); } printf("\n"); printf("\n"); }//输入数据 void outDate(int n){ int i=1; printf("result:\n"); while(n!=0){ printf("step %d : %s\n",i,operate[n%10-1]); n /= 10; i++; } printf("\n"); printf("\n"); }//对符合要求的结果输出 //比较复杂的运算放在单独的方法里 void OPadd(int *result,int number){ int lv=10; for(number;number>lv-1;lv*=10); if(*result<0)number = -number; *result = *result * lv + number; } void OPchange(int *result,int n){ int number1=0,number2=0; int number0 = *result; int i; int lv0=1,lv1=1,lv2=1; *result = 0; for(i=1;'0'<=operate[n%10-1][i]&&operate[n%10-1][i]<='9';i++){ number1 = number1*10+operate[n%10-1][i]-'0'; lv1 *= 10; } i++; for(i;'0'<=operate[n%10-1][i]&&operate[n%10-1][i]<='9';i++){ number2 = number2*10+operate[n%10-1][i]-'0'; lv2 *= 10; } for(number0;number0!=0;){ if(number0%lv1==number1){ number0 /= lv1; *result = *result + number2*lv0; lv0 *= lv2; } else{ *result = *result + number0%10*lv0; lv0 *= 10; number0 /= 10; } } //printf("number1=%d,number2=%d,lv1=%d,lv2=%d\n",number1,number2,lv1,lv2); //printf("result=%d\n",result); //printf("number1=%s,number2=%s",number1,number2); }//目前最复杂的运算,替换数字 void OPreverse(int *result){ int some; some = *result; *result = 0; for(some;some!=0;some /=10) *result = *result * 10 + some%10; }//反转数字 void OPsum(int *result){ int sum=0; for(*result;*result!=0;*result/=10) sum += *result % 10; *result = sum; }//对所有数字求和 void OPpow(int *result,int number){ int end=1; int i; for(i=0;i<number;i++) end *= *result; *result = end; }//幂运算 void OPshift(int *result,int p){//p为标识位,0表示{,1表示} int lv=10; int end; for(*result;*result>lv-1;lv*=10); lv /= 10; if(p) end = *result / 10 + *result % 10 * lv;//} else end = *result % lv * 10 + *result / lv;//{ *result = end; }//将数字左移或右移 void OPmirror(int *result){ int lv=1,x; for(lv;lv<*result+1;lv*=100){ x = *result % (lv*10) / lv; *result = *result * 10 + x; } }//镜像复制,将各数字反过来接在原数后面 void calculate(int code){ char OP; int number; int n = code; int result = start; int i; while(n!=0){ OP = operate[n%10-1][0]; number = 0; i=1; if(operate[n%10-1][1]=='-')i++;//解析出正负 for(i;'0'<=operate[n%10-1][i]&&operate[n%10-1][i]<='9';i++){ number = number*10+operate[n%10-1][i]-'0'; }//解析出操作中数字 if(operate[n%10-1][1]=='-') number = -number;//解析出正负 if(OP == '+')//分支判断出改进行什么操作 result += number; else if(OP == '-') result -= number; else if(OP == '*') result *= number; else if(OP == '/'){ if(result % number == 0) result /= number; else break; }//当除法结果为小数时,判为失败 else if(OP == '<') result /= 10; else if(OP == 'a') OPadd(&result,number); else if(OP == '>') OPchange(&result,n); else if(OP == '^') OPpow(&result,number); else if(OP == '!') result = -result; else if(OP == 'r') OPreverse(&result); else if(OP == 's') OPsum(&result); else if(OP == '{') OPshift(&result,0); else if(OP == '}') OPshift(&result,1); else if(OP == 'm') OPmirror(&result); n /= 10; if(debug)printf("result=%d\n",result);//测试用 if(result >9999999)break;//当结果超限时判为异常 if(result == target) outDate(code); //结果正确输出 } }//根据操作码计算,关键函数 void allCode(int n,int s) { if(n==0){ if(debug)printf("\ncode=%d\n",s);//测试用,显示操作码 calculate(s); } else for(int i=1;i<=OPNumber;i++) allCode(n-1,s*10+i); }//利用递归,找出所有可能的操作顺序,算出操作码,交给calculate函数计算 //注意操作是从最后一位向前操作 void renew(){ OPNumber = 0; } int main() { while(true){ renew(); inputDate(); allCode(step,0); } return 0; }//主函数
程序猿玩游戏——用c语言求游戏《计算器——游戏》的解法
最新推荐文章于 2024-09-20 14:09:11 发布