// to24point1.cpp : 定义控制台应用程序的入口点。
//
#include <tchar.h>
#include <vector>
#include <string>
using namespace std;
//因为中间结果可能有非整数,所以使用float 保存数值
typedef pair<float,string> VALUE_DESC;
//
typedef vector<VALUE_DESC> VEC_DESC;
/**
* \fn string gen_op(char* op,string &desc1,string &desc2)
* \brief 生成二值计算的表达式
* \param op 操作符 + - * /
* \param desc1 第一个操作数的表达式
* \param desc2 第二个操作数的表达式
*/
string gen_op(char* op,string &desc1,string &desc2)
{
string result ="(";
result.append(op);
result.push_back(' ');
result.append(desc1);
result.push_back(' ');
result.append(desc2);
result.push_back(')');
return result;
}
/**
* \fn VEC_DESC four_calc(VALUE_DESC &a1,VALUE_DESC &a2)
* \brief 四则运算
* \param a1 --第一个值和它的表达式
* \param a2 --第二个值和它的表达式
* \return 值和它的表达式
*/
VEC_DESC four_calc(VALUE_DESC &a1,VALUE_DESC &a2)
{
#define APPEND_RESULT(vec,op,a1,a2) vec.push_back(make_pair(a1.first##op##a2.first,gen_op(#op,a1.second,a2.second)));
VEC_DESC result ;
char op[4] ={'+','-','*','/'};
for(int i=0;i<4;i++)
{
char c = op[i];
switch(c)
{
case '+':
{
APPEND_RESULT(result,+,a1,a2);
break;
}
case '-':
{
APPEND_RESULT(result,-,a1,a2);
APPEND_RESULT(result,-,a2,a1);
break;
}
case '*':
{
APPEND_RESULT(result,*,a1,a2);
break;
}
case '/':
{
if(a1.first!=0)
{
APPEND_RESULT(result,/,a2,a1);
}
if(a2.first!=0)
{
APPEND_RESULT(result,/,a1,a2);
}
break;
}
}
}
return result;
}
/**
* \fn void calc(VALUE_DESC value,VEC_DESC &vec,VEC_DESC &result)
* \brief 递归计算vec和输入的value 之间的值,结果保存result
* \param value - 输入的值,初始值为0
* \param vec - 一组数,初始为4个数
* \param result - 结果为最终通过四则混合运算计算的可能结果,很多很多
*/
void calc(VALUE_DESC value,VEC_DESC &vec,VEC_DESC &result)
{
if(value.first==0)//还没有中间结果
{
if(vec.size()==1) //得到结果
{
result.push_back(vec[0]);
return ;
}
for(size_t i=0;i<vec.size();i++) //顶层的计算,4个则可能有4种取的可能
{
VEC_DESC t = vec;
t.erase(t.begin()+i);
calc(vec[i],t,result);//输出可能的值
}
}
else
{
//有了中间结果,从vec中获取1个元素,参与运算,结果继续运算
for(size_t i=0;i<vec.size();i++)
{
VEC_DESC t = vec;
t.erase(t.begin()+i);
//中间结果
VEC_DESC vcalc=four_calc(value,vec[i]);
for(size_t j=0;j<vcalc.size();j++)
{
VEC_DESC tt = t;
tt.push_back(vcalc[j]);
//中间结果,剩下的元素,结果
calc(make_pair(0.0,string("")),tt,result);
}
}
}
}
//初始化数据
void init_vec_desc(VEC_DESC &vec,int value[],int len)
{
for(int i=0;i<len;i++)
{
char buf[10]={};
itoa(value[i],buf,10);
vec.push_back(make_pair(value[i],buf));
}
}
//获得等于24的结果
VALUE_DESC get_correct_value(VEC_DESC &r)
{
for(size_t i=0;i<r.size();i++)
{
if(r[i].first >=24.0000000 && r[i].first<24.00000001 )
{
return r[i];
}
}
return make_pair(0,"");
}
int to24(VEC_DESC &vec)
{
VEC_DESC r;
calc(make_pair(0.0,string("")),vec,r);
VALUE_DESC result = get_correct_value(r);
if(result.first==0)
{
printf("[%d %d %d %d] cannot calculate 24\n",(int)vec[0].first,(int)vec[1].first,(int)vec[2].first,(int)vec[3].first);
}
else
{
printf("[%d %d %d %d] : %s\n",(int)vec[0].first,(int)vec[1].first,(int)vec[2].first,(int)vec[3].first,result.second.c_str());
}
return 0 ;
}
void test()
{
VEC_DESC input;
VEC_DESC r;
int buf[][4]={
{5,1,4,2},
{3,3,3,1},
{5,5,5,1},
{1,1,6,8},
{1,1,6,9},
{1,1,7,10},
{1,1,8,8},
};
for(int i=0;i<sizeof(buf)/sizeof(buf[0]);i++)
{
input.clear();
init_vec_desc(input,buf[i],4);
to24(input);
}
}
void test1()
{
int i,j,k,m;
for(i=1;i<=13;i++)
{
for(j=1;j<=13;j++)
{
for(k=1;k<=13;k++)
{
for(m=1;m<=13;m++)
{
VEC_DESC input;
int buf[4]={i,j,k,m};
init_vec_desc(input,buf,4);
to24(input);
}
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
test1();
return 0;
VEC_DESC input;
VEC_DESC r;
int buf[4]={5,1,4,2};
printf("\nPlease input 4 number:");
scanf("%d%d%d%d",&buf[0],&buf[1],&buf[2],&buf[3]);
init_vec_desc(input,buf,4);
to24(input);
return 0;
}
https://blog.csdn.net/justin_bkdrong/article/details/45843051
这个才是“完整”代码,如果用VS2019编译,基本不用改。
#define _CRT_SECURE_NO_WARNINGS
#include <time.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int const NUMBERCOUNT = 4;
float const RESULT = 24;
bool isHit = false;
bool showanswer = true;
char* ExpressPool;
int PoolIdx;
int MAX_RESULT = 1500;
enum OPT {
PLU,//加
MIN,//减
MINBY,//被减
MUL,//乘
DIV,//除
DIVBY//被除
};
float cal(int ncount, float* nums, char* exps)
{
float a, b;
if (ncount == 2)
{
a = nums[0];
b = nums[1];
OPT opt;
float result = 0.0f;
for (opt = PLU; opt <= DIVBY; opt = (OPT)(opt + 1))
{
switch (opt)
{
case PLU:
result = a + b;
if (result == RESULT)
{
sprintf(ExpressPool + PoolIdx * 32, "%s+%s", exps, exps + 32);
PoolIdx++;
sprintf(ExpressPool + PoolIdx * 32, "%s+%s", exps + 32, exps);
PoolIdx++;
isHit = true;
}
break;
case MIN:
result = a - b;
if (result == RESULT)
{
sprintf(ExpressPool + PoolIdx * 32, "%s-%s", exps, exps + 32);
PoolIdx++;
isHit = true;
}
break;
case MINBY:
result = b - a;
if (result == RESULT)
{
sprintf(ExpressPool + PoolIdx * 32, "%s-%s", exps + 32, exps);
PoolIdx++;
isHit = true;
}
break;
case MUL:
result = a * b;
if (result == RESULT)
{
sprintf(ExpressPool + PoolIdx * 32, "%s*%s", exps, exps + 32);
PoolIdx++;
sprintf(ExpressPool + PoolIdx * 32, "%s*%s", exps + 32, exps);
PoolIdx++;
isHit = true;
}
break;
case DIV:
if (b == 0)continue;
result = a / b;
if (result == RESULT)
{
sprintf(ExpressPool + PoolIdx * 32, "%s/%s", exps, exps + 32);
PoolIdx++;
isHit = true;
}
break;
case DIVBY:
if (a)continue;
result = b / a;
if (result == RESULT)
{
sprintf(ExpressPool + PoolIdx * 32, "%s/%s", exps + 32, exps);
PoolIdx++;
isHit = true;
}
break;
}
}
}
else
{
for (int i = 0; i < ncount; i++)
{
for (int j = 0; j < ncount; j++)
{
if (i != j)
{
int newcount = ncount - 1;
float* num = new float[newcount];
char* newexps = (char*)malloc(32 * newcount);
memset(newexps, 0, 32 * newcount);
int idx = 1;
for (int m = 0; m < ncount; m++)
{
if (m != i && m != j)
{
num[idx] = nums[m];
strcpy(newexps + idx * 32, exps + m * 32);
idx++;
}
}
OPT opt;
for (opt = PLU; opt <= DIVBY; opt = (OPT)(opt + 1))
{
switch (opt)
{
case PLU:
num[0] = nums[i] + nums[j];
sprintf(newexps, "(%s+%s)", exps + i * 32, exps + j * 32);
break;
case MIN:
num[0] = nums[i] - nums[j];
sprintf(newexps, "(%s-%s)", exps + i * 32, exps + j * 32);
break;
case MINBY:
num[0] = nums[j] - nums[i];
sprintf(newexps, "(%s-%s)", exps + j * 32, exps + i * 32);
break;
case MUL:
num[0] = nums[i] * nums[j];
sprintf(newexps, "(%s*%s)", exps + i * 32, exps + j * 32);
break;
case DIV:
if (nums[j] == 0)continue;
num[0] = nums[i] / nums[j];
sprintf(newexps, "(%s/%s)", exps + i * 32, exps + j * 32);
break;
case DIVBY:
if (nums[i] == 0)continue;
num[0] = nums[j] / nums[i];
sprintf(newexps, "(%s/%s)", exps + j * 32, exps + i * 32);
break;
}
cal(newcount, num, newexps);
}
free(newexps);
delete(num);
}
}
}
}
return 0;
}
int autoanswer(float* num)
{
int ret = 0;
ExpressPool = (char*)malloc(MAX_RESULT * 32);
memset(ExpressPool, 0, MAX_RESULT * 32);
PoolIdx = 0;
char* exps = (char*)malloc(32 * NUMBERCOUNT);
memset(exps, 0, 32 * NUMBERCOUNT);
for (int i = 0; i < NUMBERCOUNT; i++)
{
if ((exps + i * 32) != 0)
sprintf(exps + i * 32, "%d", (int)num[i]);
}
isHit = false;
cal(NUMBERCOUNT, num, exps);
free(exps);
if (!isHit)
{
if (showanswer)
{
printf("无解!\n");
}
}
else
{
for (int i = 0; i < MAX_RESULT; i++)
{
char firstchar = *(ExpressPool + i * 32);
if (firstchar != '\0')
{
if (showanswer)
{
printf("%s = %d\n", ExpressPool + i * 32, (int)RESULT);
}
ret++;
for (int j = i + 1; j < MAX_RESULT; j++)
{
char newfirstchar = *(ExpressPool + j * 32);
if (newfirstchar != '\0')
{
char* str1 = (char*)(ExpressPool + i * 32);
char* str2 = (char*)(ExpressPool + j * 32);
int cmpresult = strcmp(ExpressPool + i * 32, ExpressPool + j * 32);
if (cmpresult == 0)
{
memset(ExpressPool + j * 32, '\0', 32);
}
}
}
}
}
}
free(ExpressPool);
return ret;
}
int main() {
float num[NUMBERCOUNT];
srand((unsigned int)(time(NULL)));
char c;
printf("\n\n");
printf("**********************************************************\n");
printf("* *\n");
printf("* 计算24游戏 *\n");
printf("* *\n");
printf("* 随机产生4个(0-9)的数字,判断是否能通过+-*/得到24 *\n");
printf("* *\n");
printf("* 茂大叔提供 *\n");
printf("* *\n");
printf("**********************************************************\n\n");
printf("[enter]=随机计算;a=用户答题;q=退出\n");
printf("请输入命令:");
c = getchar();
while (c != 'q') {
showanswer = true;
printf("备选数字为:");
for (int i = 0; i < NUMBERCOUNT; i++)
{
num[i] = (float)(rand() % 9 + 1);
printf(" %d", (int)num[i]);
}
if (c == 'a')
{
bool correct = false;
showanswer = false;
char ans[32] = "null";
int ret = autoanswer(num);
while (!correct)
{
printf("\n请输入你的答案(除最后一步外,每一个步骤均须用括号包围,输入0代表无解,输入q代表放弃):\n");
scanf("%s", ans);
getchar();
if (ans[0] == 'q')
{
free(ExpressPool);
showanswer = true;
printf("正确答案可以为:\n");
autoanswer(num);
printf("共计 %d 条:\n", ret);
break;
}
else
{
if (!isHit && ans[0] == '0')
{
correct = true;
}
else
{
for (int i = 0; i < 100; i++)
{
char firstchar = *(ExpressPool + i * 32);
if (firstchar != '\0')
{
char* str1 = (char*)(ExpressPool + i * 32);
int cmpresult = strcmp(ExpressPool + i * 32, ans);
if (cmpresult == 0)
{
correct = true;
}
}
}
}
if (correct)
{
printf("\n你真棒!\n");
}
else
{
printf("\n输入错误,请重试!\n");
}
}
}
}
if (c == '\n')
{
printf("\n不尝试自己做一做么?回车看答案!\n");
getchar();
printf("答案可以为:\n");
int ret = autoanswer(num);
printf("共计 %d 条:\n", ret);
}
if (c == 'm')
{
for (int n1 = 1; n1 < 10; n1++)
for (int n2 = 1; n2 < 10; n2++)
for (int n3 = 1; n3 < 10; n3++)
for (int n4 = 1; n4 < 10; n4++)
{
printf("\n备选数:%d %d %d %d\n======================\n", n1, n2, n3, n4);
num[0] = (float)n1;
num[1] = (float)n2;
num[2] = (float)n3;
num[3] = (float)n4;
int ret = autoanswer(num);
printf("共计 %d 条:\n", ret);
}
}
printf("\n[enter]=随机计算;a=用户答题;q=退出\n");
printf("请输入命令:");
c = getchar();
}
printf("再见~!");
return 0;
}