24点计算器源码(C语言 + C++语言)

一 C语言源码

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define EPS 1e-6
#define TARGET 24

// 四则运算计算
double calc(double a, double b, int op)
{
    switch(op)
    {
        case 0: return a + b;
        case 1: return a - b;
        case 2: return a * b;
        case 3: 
            if(fabs(b) < EPS) return -999999; // 除零非法
            return a / b;
        default: return 0;
    }
}

// 运算符转字符
char getOp(int op)
{
    switch(op)
    {
        case 0: return '+';
        case 1: return '-';
        case 2: return '*';
        case 3: return '/';
        default: return ' ';
    }
}

// 递归全排列(4个数)
int vis[4];
int num[4];
int buf[4];
int found = 0;

// 枚举3个运算符 op1 op2 op3
void dfsOp(int op1, int op2, int op3)
{
    double a = buf[0], b = buf[1], c = buf[2], d = buf[3];
    char o1 = getOp(op1), o2 = getOp(op2), o3 = getOp(op3);
    double r;

    // 结构1: ((a o1 b) o2 c) o3 d
    r = calc(calc(calc(a,b,op1), c, op2), d, op3);
    if(fabs(r - TARGET) < EPS)
    {
        printf("((%d%c%d)%c%d)%c%d = 24\n", (int)a,o1,(int)b,o2,(int)c,o3,(int)d);
        found = 1;
    }

    // 结构2: (a o1 (b o2 c)) o3 d
    r = calc(calc(a, calc(b,c,op2), op1), d, op3);
    if(fabs(r - TARGET) < EPS)
    {
        printf("(%d%c(%d%c%d))%c%d = 24\n", (int)a,o1,(int)b,o2,(int)c,o3,(int)d);
        found = 1;
    }

    // 结构3: a o1 ((b o2 c) o3 d)
    r = calc(a, calc(calc(b,c,op2), d, op3), op1);
    if(fabs(r - TARGET) < EPS)
    {
        printf("%d%c((%d%c%d)%c%d) = 24\n", (int)a,o1,(int)b,o2,(int)c,o3,(int)d);
        found = 1;
    }

    // 结构4: a o1 (b o2 (c o3 d))
    r = calc(a, calc(b, calc(c,d,op3), op2), op1);
    if(fabs(r - TARGET) < EPS)
    {
        printf("%d%c(%d%c(%d%c%d)) = 24\n", (int)a,o1,(int)b,o2,(int)c,o3,(int)d);
        found = 1;
    }

    // 结构5: (a o1 b) o2 (c o3 d)
    r = calc(calc(a,b,op1), calc(c,d,op3), op2);
    if(fabs(r - TARGET) < EPS)
    {
        printf("(%d%c%d)%c(%d%c%d) = 24\n", (int)a,o1,(int)b,o2,(int)c,o3,(int)d);
        found = 1;
    }
}

// 枚举三组运算符组合 0+ 1- 2* 3/
void enumOp()
{
    int o1,o2,o3;
    for(o1=0;o1<4;o1++)
        for(o2=0;o2<4;o2++)
            for(o3=0;o3<4;o3++)
                dfsOp(o1,o2,o3);
}

// 回溯生成4数字全排列
void dfsNum(int step)
{
    int i;
    if(step == 4)
    {
        enumOp();
        return;
    }
    for(i=0;i<4;i++)
    {
        if(!vis[i])
        {
            vis[i] = 1;
            buf[step] = num[i];
            dfsNum(step+1);
            vis[i] = 0;
        }
    }
}

int main()
{
    int i;
    printf("==== C语言24点计算器 ====\n");
    printf("请输入4个数字(空格隔开): ");
    for(i=0;i<4;i++)
    {
        scanf("%d", &num[i]);
    }
    printf("========================\n");

    // 初始化标记
    for(i=0;i<4;i++) vis[i] = 0;
    found = 0;

    dfsNum(0);

    if(!found)
    {
        printf("该组数字无法算出24点!\n");
    }
    return 0;
}

二 C++语言源码

cpp 复制代码
#include <iostream>
#include <vector>
#include <set>
#include <cmath>
#include <iomanip>
using namespace std;

const double EPS = 1e-6;
const int TARGET = 24;
// 运算符:0+ 1- 2* 3/
const char opChar[] = {'+', '-', '*', '/'};

// 四则运算函数
double calculate(double a, double b, int op)
{
    switch (op)
    {
        case 0: return a + b;
        case 1: return a - b;
        case 2: return a * b;
        case 3:
            if (fabs(b) < EPS) return -9999999; // 除零直接返回非法值
            return a / b;
        default: return 0;
    }
}

// 遍历5种括号结构,验证是否等于24,存入结果集合去重
void checkAllFormat(double n1, double n2, double n3, double n4, int o1, int o2, int o3, set<string>& res)
{
    char c1 = opChar[o1], c2 = opChar[o2], c3 = opChar[o3];
    double val;

    // 结构1: ((a o1 b) o2 c) o3 d
    val = calculate(calculate(calculate(n1, n2, o1), n3, o2), n4, o3);
    if (fabs(val - TARGET) < EPS)
    {
        string s = "((" + to_string((int)n1) + c1 + to_string((int)n2) + ")" + c2 + to_string((int)n3) + ")" + c3 + to_string((int)n4);
        res.insert(s);
    }

    // 结构2: (a o1 (b o2 c)) o3 d
    val = calculate(calculate(n1, calculate(n2, n3, o2), o1), n4, o3);
    if (fabs(val - TARGET) < EPS)
    {
        string s = "(" + to_string((int)n1) + c1 + "(" + to_string((int)n2) + c2 + to_string((int)n3) + "))" + c3 + to_string((int)n4);
        res.insert(s);
    }

    // 结构3: a o1 ((b o2 c) o3 d)
    val = calculate(n1, calculate(calculate(n2, n3, o2), n4, o3), o1);
    if (fabs(val - TARGET) < EPS)
    {
        string s = to_string((int)n1) + c1 + "((" + to_string((int)n2) + c2 + to_string((int)n3) + ")" + c3 + to_string((int)n4) + ")";
        res.insert(s);
    }

    // 结构4: a o1 (b o2 (c o3 d))
    val = calculate(n1, calculate(n2, calculate(n3, n4, o3), o2), o1);
    if (fabs(val - TARGET) < EPS)
    {
        string s = to_string((int)n1) + c1 + "(" + to_string((int)n2) + c2 + "(" + to_string((int)n3) + c3 + to_string((int)n4) + "))";
        res.insert(s);
    }

    // 结构5: (a o1 b) o2 (c o3 d)
    val = calculate(calculate(n1, n2, o1), calculate(n3, n4, o3), o2);
    if (fabs(val - TARGET) < EPS)
    {
        string s = "(" + to_string((int)n1) + c1 + to_string((int)n2) + ")" + c2 + "(" + to_string((int)n3) + c3 + to_string((int)n4) + ")";
        res.insert(s);
    }
}

// 枚举3个运算符组合
void enumOperator(vector<double> nums, set<string>& ansSet)
{
    for (int o1 = 0; o1 < 4; o1++)
        for (int o2 = 0; o2 < 4; o2++)
            for (int o3 = 0; o3 < 4; o3++)
                checkAllFormat(nums[0], nums[1], nums[2], nums[3], o1, o2, o3, ansSet);
}

// 回溯生成4个数全排列
void permute(vector<int>& src, vector<double>& cur, vector<bool>& vis, set<string>& ans)
{
    if (cur.size() == 4)
    {
        enumOperator(cur, ans);
        return;
    }
    for (int i = 0; i < 4; i++)
    {
        if (!vis[i])
        {
            vis[i] = true;
            cur.push_back((double)src[i]);
            permute(src, cur, vis, ans);
            cur.pop_back();
            vis[i] = false;
        }
    }
}

int main()
{
    cout << "==== C++ 24点计算器 ====" << endl;
    vector<int> num(4);
    cout << "请输入4个数字,空格分隔:";
    for (int i = 0; i < 4; i++)
        cin >> num[i];

    set<string> answer;
    vector<double> temp;
    vector<bool> used(4, false);
    permute(num, temp, used, answer);

    cout << "========================" << endl;
    if (answer.empty())
    {
        cout << "该组数字无法计算出24点!" << endl;
    }
    else
    {
        cout << "共找到 " << answer.size() << " 种解法:" << endl;
        for (auto& expr : answer)
            cout << expr << " = 24" << endl;
    }
    return 0;
}