有没有人想过怎么用计算机来实现24点
就是扑克里的24点游戏,4个数,+-*/得24……偶还在想…… 电脑爱好者上曾经有这个编程的例子 穷举法吧 以下是引用yzhlinux在2004-5-1 9:53:31的发言:
穷举法吧
那你的代码要写P4,4=4*4*4*4=256行代码?? 256行代码,什么意思,就算是这样,256行算多吗?? 当然不是的,穷举是用程序去穷举,而不是在程序里先举好,并且不是p4,元素显然不止4个,至少是七个如:A+B+C+D 就又7个字符了,而穷举就是吧A,B,C,D,+,_,*,\,(,) 这个十个元素来排列组合,组合成一个四则运算表达试,然后传递给一个计算函数得出结果,如果是24 则表达试就是我们要求的了。比如:
function GetMach(A,B,C,D) as String '得到一个字符串组合如:(A+B*D)-C
function GetValue(MachString) as Float '得到字符串的计算值 ,可能是小数
那么程序就好写了:
GetNumber(&A,&B,&C,&D) ; '得到ABCD则四个数字,赋给A,B,C,D四个变量
do{
MachString = GetMach(A,B,C,D); '得到一个表达试的字符传
if(GetValue(MachString)==24) break;
}
print XXXXXX;
我现在试着在写,就是不知道有什么好办法解决重复的算式问题,比如
(5-2)*8*1
与
(5-2)*1*8
8*(5-2)*1
等等
花了一个上午,终于完成了
你参考参考吧,哈哈
[此贴子已经被作者于2004-5-2 13:43:13编辑过]
上面的发现有一点bug,
这个改过了
一个计算 24 点的小游戏
VB 编写
[此贴子已经被作者于2004-5-2 15:17:46编辑过]
#include <stdio.h>
#include <stdlib.h>
int EnumFormula(int min,int max,int num,int sum);
void ShowFormula(int *Num,int *Sym,int count,int sum);
double GetFormulaVal(int *Num,int *Sym,int count);
int EnumArray(int *Num,int min,int max,int count);
void InitArray(int *Num,int min,int max,int count);
const char cSym = {0,'+','-','*','/'};
int main(int argc, char *argv[])
{
printf("总计%d个式子\n",EnumFormula(1,10,4,24));
system("PAUSE");
return 0;
}
int EnumFormula(int min,int max,int num,int sum)
{
int *FormulaNum = (int*)calloc(num,sizeof(int)); //储存操作数
//储存操作符号
//最后一位用于穷举结束标记
// 1 - 4 代表 '+' '-' '*' '/'
int *FormulaSym = (int*)calloc(num,sizeof(int));
int result = 0;
// 初始化操作数和操作符号数组
int i;
for(i=0;i<num;i++) FormulaNum = min;
for(i=0;i<num;i++) FormulaSym = 1;
FormulaNum--;
InitArray(FormulaNum,min,max,num);
FormulaNum++;
// 穷举操作数和操作符号组合
while(FormulaSym == 1)
{
double t = GetFormulaVal(FormulaNum,FormulaSym,num) - sum;
if(t>-0.01 && t<0.01)
{
//printf("%d %d %d %d | %d %d %d",FormulaNum,FormulaNum,
//FormulaNum,FormulaNum,
// FormulaSym,FormulaSym,
// FormulaSym,FormulaSym);
ShowFormula(FormulaNum,FormulaSym,num,sum);
result++;
}
// 依次穷举操作数
//允许数字重复的穷举
//FormulaNum++;
//for(i=0;FormulaNum > max && i<num-1;i++)
//{
// FormulaNum = min;
// FormulaNum++;
//}
// 操作数穷举与操作符号穷举联接
//if(FormulaNum > max)
//{
// FormulaNum = min;
// FormulaSym++;
//}
// 不允许数字重复的穷举
// 数字必须从小到大的排列,防止重复
if((max - min)< num) exit(0); // 出错
if(EnumArray(FormulaNum,min,max,num))
{
FormulaSym++;
InitArray(FormulaNum,min,max,num);
FormulaNum++;
}
// 操作符号穷举
for(i=0;FormulaSym > 4 && i<num-1;i++)
{
FormulaSym = 1;
FormulaSym++;
}
}
//释放空间
free(FormulaNum);
free(FormulaSym);
return result;
}
// 计算算式结果
double GetFormulaVal(int *Num,int *Sym,int count)
{
int i,j;
double preresult;
preresult = Num;
i=1;j=0;
while(i<count)
{
switch(Sym)
{
case 1:
preresult += Num;
break;
case 2:
preresult -= Num;
break;
case 3:
preresult *= Num;
break;
case 4:
if(Num == 0) return -1000;
preresult /= Num;
break;
}
i++;j++;
}
return preresult; //进行修正
}
// 打印算式
void ShowFormula(int *Num,int *Sym,int count,int sum)
{
int i,j,len;
char *Formula = (char*)calloc(count*4,sizeof(char));
char temp;
itoa(Num,Formula,10);
i=1;j=0;
while(i<count)
{
itoa(Num,temp,10);
len = strlen(Formula);
switch(Sym)
{
case 1:
case 2:
Formula = cSym];
strcat(Formula,temp);
break;
case 3:
case 4:
// 如果上一个操作符号优先级低于当前的,应加上括号
if(j==0 || Sym > 2)
{
Formula = cSym];
strcat(Formula,temp);
}
else
{
int n;
char *FormulaTemp = (char*)calloc(len+1,sizeof(char));
for(n=0;n<len+1;n++)
{
FormulaTemp = Formula;
Formula = 0;
}
Formula = '(';
strcat(Formula,FormulaTemp);
free(FormulaTemp);
Formula =')';
Formula = cSym];
strcat(Formula,temp);
}
break;
}
i++;j++;
}
printf("%s",Formula);
printf("=%d\n",sum);
free(Formula);
}
// 以当前数组为基础得到一个从小到大排列的数组
// 返回非0表示穷举结束
int EnumArray(int *Num,int min,int max,int count)
{
int i,top;
top = count-1;
Num++;
while(Num>max-count+top+1 && top>=0)
{
top--;
Num++;
}
for(i=top+1;i<count;i++)
{
Num = Num+1;
}
if(Num > max) return 1;
else return 0;
}
// 不允许重复的初始化数组
void InitArray(int *Num,int min,int max,int count)
{
int i;
for(i=0;i<count;i++) Num=min+i;
Num--;
}
[此贴子已经被作者于2004-5-2 14:50:47编辑过]
本法穷举出所有用min - max之间的num个数组成算式,结果为sum的情况
如要具体的话,可以不穷举操作数,直接输入操作数,进行操作符号穷举 以下是引用游侠无极限在2004-5-2 14:41:26的发言:
#include <stdio.h>
#include <stdlib.h>
int EnumFormula(int min,int max,int num,int sum);
void ShowFormula(int *Num,int *Sym,int count,int sum);
double GetFormulaVal(int *Num,int *Sym,int count);
int EnumArray(int *Num,int min,int max,int count);
void InitArray(int *Num,int min,int max,int count);
const char cSym = {0,'+','-','*','/'};
int main(int argc, char *argv[])
{
printf("总计%d个式子\n",EnumFormula(1,10,4,24));
system("PAUSE");
return 0;
}
int EnumFormula(int min,int max,int num,int sum)
{
int *FormulaNum = (int*)calloc(num,sizeof(int)); //储存操作数
//储存操作符号
//最后一位用于穷举结束标记
// 1 - 4 代表 '+' '-' '*' '/'
int *FormulaSym = (int*)calloc(num,sizeof(int));
int result = 0;
// 初始化操作数和操作符号数组
int i;
for(i=0;i<num;i++) FormulaNum = min;
for(i=0;i<num;i++) FormulaSym = 1;
FormulaNum--;
InitArray(FormulaNum,min,max,num);
FormulaNum++;
// 穷举操作数和操作符号组合
while(FormulaSym == 1)
{
double t = GetFormulaVal(FormulaNum,FormulaSym,num) - sum;
if(t>-0.01 && t<0.01)
{
//printf("%d %d %d %d | %d %d %d",FormulaNum,FormulaNum,
//FormulaNum,FormulaNum,
// FormulaSym,FormulaSym,
// FormulaSym,FormulaSym);
ShowFormula(FormulaNum,FormulaSym,num,sum);
result++;
}
// 依次穷举操作数
//允许数字重复的穷举
//FormulaNum++;
//for(i=0;FormulaNum > max && i<num-1;i++)
//{
// FormulaNum = min;
// FormulaNum++;
//}
// 操作数穷举与操作符号穷举联接
//if(FormulaNum > max)
//{
// FormulaNum = min;
// FormulaSym++;
//}
// 不允许数字重复的穷举
// 数字必须从小到大的排列,防止重复
if((max - min)< num) exit(0); // 出错
if(EnumArray(FormulaNum,min,max,num))
{
FormulaSym++;
InitArray(FormulaNum,min,max,num);
FormulaNum++;
}
// 操作符号穷举
for(i=0;FormulaSym > 4 && i<num-1;i++)
{
FormulaSym = 1;
FormulaSym++;
}
}
//释放空间
free(FormulaNum);
free(FormulaSym);
return result;
}
// 计算算式结果
double GetFormulaVal(int *Num,int *Sym,int count)
{
int i,j;
double preresult;
preresult = Num;
i=1;j=0;
while(i<count)
{
switch(Sym)
{
case 1:
preresult += Num;
break;
case 2:
preresult -= Num;
break;
case 3:
preresult *= Num;
break;
case 4:
if(Num == 0) return -1000;
preresult /= Num;
break;
}
i++;j++;
}
return preresult; //进行修正
}
// 打印算式
void ShowFormula(int *Num,int *Sym,int count,int sum)
{
int i,j,len;
char *Formula = (char*)calloc(count*4,sizeof(char));
char temp;
itoa(Num,Formula,10);
i=1;j=0;
while(i<count)
{
itoa(Num,temp,10);
len = strlen(Formula);
switch(Sym)
{
case 1:
case 2:
Formula = cSym];
strcat(Formula,temp);
break;
case 3:
case 4:
// 如果上一个操作符号优先级低于当前的,应加上括号
if(j==0 || Sym > 2)
{
Formula = cSym];
strcat(Formula,temp);
}
else
{
int n;
char *FormulaTemp = (char*)calloc(len+1,sizeof(char));
for(n=0;n<len+1;n++)
{
FormulaTemp = Formula;
Formula = 0;
}
Formula = '(';
strcat(Formula,FormulaTemp);
free(FormulaTemp);
Formula =')';
Formula = cSym];
strcat(Formula,temp);
}
break;
}
i++;j++;
}
printf("%s",Formula);
printf("=%d\n",sum);
free(Formula);
}
// 以当前数组为基础得到一个从小到大排列的数组
// 返回非0表示穷举结束
int EnumArray(int *Num,int min,int max,int count)
{
int i,top;
top = count-1;
Num++;
while(Num>max-count+top+1 && top>=0)
{
top--;
Num++;
}
for(i=top+1;i<count;i++)
{
Num = Num+1;
}
if(Num > max) return 1;
else return 0;
}
// 不允许重复的初始化数组
void InitArray(int *Num,int min,int max,int count)
{
int i;
for(i=0;i<count;i++) Num=min+i;
Num--;
}
[此贴子已经被作者于2004-5-2 14:50:47编辑过]
printf("总计%d个式子\n",EnumFormula(1,10,4,24)); 的运行结果是:
1+4+9+10=24
1+5+8+10=24
1+6+7+10=24
1+6+8+9=24
2+3+9+10=24
2+4+8+10=24
2+5+7+10=24
2+5+8+9=24
2+6+7+9=24
3+4+7+10=24
3+4+8+9=24
3+5+6+10=24
3+5+7+9=24
3+6+7+8=24
4+5+6+9=24
4+5+7+8=24
这是什么意思?似乎是找出了 1 至 10 之间的和是24 的数据,这和完成计算24点,差很多吧?
比如用户输入 2 ,5,7,8 程序应该能得到计算这四个数据得到24的表达式才行啊,这样就可以写一个游戏了。
如: 1,5,7,8 有如下方法可以算出 24
((1+7)-5)*8 = 24
((7+1)-5)*8 = 24
(1+7)*(8-5) = 24
(7+1)*(8-5) = 24
((1-5)+7)*8 = 24
((7-5)+1)*8 = 24
(8-5)*(1+7) = 24
(8-5)*(7+1) = 24
8*(1+7-5) = 24
8*((1+7)-5) = 24
8*(1+(7-5)) = 24
8*(7+1-5) = 24
8*((7+1)-5) = 24
8*(7+(1-5)) = 24
8*(1-5+7) = 24
8*((1-5)+7) = 24
8*(7-5+1) = 24
8*((7-5)+1) = 24
结果是这样的:
1+4+9+10=24
1+5+8+10=24
1+6+7+10=24
1+6+8+9=24
2+3+9+10=24
2+4+8+10=24
2+5+7+10=24
2+5+8+9=24
2+6+7+9=24
3+4+7+10=24
3+4+8+9=24
3+5+6+10=24
3+5+7+9=24
3+6+7+8=24
4+5+6+9=24
4+5+7+8=24
1*5+9+10=24
1*6+8+10=24
1*7+8+9=24
2*3+8+10=24
2*4+6+10=24
2*4+7+9=24
2*5+6+8=24
3*4+5+7=24
4*5-6+10=24
(1+2)*5+9=24
(1+3)*4+8=24
1*2*7+10=24
1*3*5+9=24
6*7-8-10=24
(2+4)*5-6=24
2*3*5-6=24
(1+2+3)*4=24
(1-2+4)*8=24
(1-2+5)*6=24
(1-3+5)*8=24
(1-4+6)*8=24
(1-5+7)*8=24
(2-3+4)*8=24
(2-3+5)*6=24
(2-4+5)*8=24
(2-5+6)*8=24
(2-6+7)*8=24
(3-4+5)*6=24
(4+5-6)*8=24
(4+6-7)*8=24
(2*4-5)*8=24
(2*5-7)*8=24
1*2*3*4=24
1/2*6*8=24
1/3*8*9=24
2/3*4*9=24
2/4*6*8=24
2/5*6*10=24
2/6*8*9=24
3*4/5*10=24
5*6*8/10=24
总计57个式子 当然不会只考虑加法的情况,大概你复制的时候出现问题了,你可以下载这页最上面的那个程序
to游侠无极限
你的方法思路比较特别,不过似乎更浪费资源啊,如果范围是1,100,那么你的循环将更多,而目前只是 sum 的,如果加上有 -,*,/ 和括号的话,那么就更多了,并且,如果游戏中规定可以使用三角函数,那么你这样就无法穷举出来了。
参考我的代码中,由于是组合成合法的表达算式后在进行计算得到结果,判断是否24,所以对于符号的增加和三角函数的支持都很简单的实现了。都变成了字符串的组合而已 (2-1)*3*8 这个算式你就没有啊,这4个数字的组合都没有出现
[此贴子已经被作者于2004-5-2 15:32:12编辑过]
似乎少了很多算式 另外,玩游戏的时候应该是可以重复出现的,不规定4张牌都必须不一样吧。
用这个好了,只不过输入的时候要按从小到大
好象有BUG,我暂时不太清楚 以下是引用yzhlinux在2004-5-2 15:28:15的发言:
(2-1)*3*8 这个算式你就没有啊,这4个数字的组合都没有出现
本来为了防止诸如
1*2*3*4
1*3*4*2
2*3*4*1
等的重复,只使用了从小到大的数组,不过这样好象也丢了不少可行的式子
另外你的程序就是有这些重复的
PS:VB的程序感觉就是慢好多啊
[此贴子已经被作者于2004-5-2 15:42:01编辑过]