程序猿玩游戏——用c语言求游戏《计算器——游戏》的解法

 
/*
编写人@wonder
版本:v0.1

因为对这个游戏感兴趣,想到用编程求解法,
固编写了本程序。
本程序用来求游戏《计算器-游戏》的解法。

输入:
开始数字start,最大步数step,目标数字target,
为三个数字,
(如123 3 321)
与可用的计算按钮
为若干字符串,用空格隔开,输入e结束。
(如r13 *-15 r < e)。

输出:
所有可行的按键顺序,可能有多个输出。

目前集成的运算有:
+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;
}//主函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值