24点求解C程序源代码

本文介绍了一个使用纯C语言编写的24点计算器程序。该程序从名为Inpute.txt的文件中读取四个数字及计算目标,然后输出所有可能的计算步骤到Result.txt文件。文章提供了完整的源代码,并详细解释了程序的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在浏览圈子讨论区的时候,发现有人在讨论机械求解24点的问题。其实求24点的程序写起来一点都不难,我记得以前大一的时候就写过一个,无奈找了半天都找不到,可能是重装系统的时候丢失了。好在今天休息,于是就静下心来写了一个。为了便于大家移植,我是用纯C写的。

  本程序的输入是一个名叫Inpute.txt的文本文件,里面存放着4个数和计算目标(这个程序可以指定计算结果,不是24也可以)。输出是一个名叫Result.txt的文本文件,由程序计算产生,记录的是运算步骤。

  Inpute.txt样例:

[3][3][8][8]=[24]

  Result.txt样例:

0000:
  第一步:{8.000000 / 3.000000 = 2.666667}
  第二步:{3.000000 - 2.666667 = 0.333333}
  第三步:{8.000000 / 0.333333 = 24.000000}
共有1种解。

  程序源代码(C文件):

  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <string.h>
  4. #define OPER_NUM  4
  5. char  s_cvOperator[OPER_NUM] = {'+''-''*''/'};
  6. char  s_cvOperType[OPER_NUM] = {  0,   1,   0,   1};
  7. double  s_dTarget;
  8. double  s_dvVals[4];
  9. char  s_cvOpers[3];
  10. char  s_cvUsed[4];
  11. int   s_iIndex;
  12. int   s_iNum;
  13. double s_dvRecords[3][2];
  14. char  s_sivSave[OPER_NUM * OPER_NUM * OPER_NUM * 24][200];
  15. double Compute(double v1, double v2, char oper);
  16. char Scan();
  17. char Outport();
  18. void main()
  19. {
  20.   int r;
  21.   FILE * fp, * ofp;
  22.   s_dvVals[0] = 3;
  23.   s_dvVals[1] = 3;
  24.   s_dvVals[2] = 8;
  25.   s_dvVals[3] = 8;
  26.   ofp = fopen("Result.txt""w");
  27.   if(ofp)
  28.   {
  29.     /* 清空输出文件 */
  30.     fclose(ofp);
  31.     /* 读取输入文件 */
  32.     fp = fopen("Input.txt""r");
  33.     if(fp)
  34.     {
  35.       r = fscanf(fp, 
  36.         "[%lf][%lf][%lf][%lf]=[%lf]",
  37.         &s_dvVals[0],
  38.         &s_dvVals[1],
  39.         &s_dvVals[2],
  40.         &s_dvVals[3],
  41.         &s_dTarget);
  42.       fclose(fp);
  43.       if(r == 5)
  44.       {
  45.         /* 搜索解 */
  46.        s_iIndex = 0;
  47.         s_iNum = 0;
  48.         Scan();
  49.         ofp = fopen("Result.txt""a");
  50.         if(ofp)
  51.         {
  52.           fprintf(ofp, "共有%d种解。/n", s_iNum);
  53.           fclose(ofp);
  54.         }
  55.         return;
  56.       }
  57.     }
  58.     ofp = fopen("Result.txt""a");
  59.     if(ofp)
  60.     {
  61.       fprintf(ofp, "读取输入文件时出错!/n注意文件格式,如:[3][3][8][8]=[24]/n", s_iNum);
  62.       fclose(ofp);
  63.     }
  64.   }
  65.   else
  66.   {
  67.     printf("打开输出文件失败!/n");
  68.     getch();
  69.   }
  70. }
  71. double Compute(double v1, double v2, char oper)
  72. {
  73.   switch(oper)
  74.   {
  75.   case '+':
  76.     return v1 + v2;
  77.     break;
  78.   case '-':
  79.     return v1 - v2;
  80.     break;
  81.   case '*':
  82.     return v1 * v2;
  83.     break;
  84.   case '/':
  85.     return v1 / v2;
  86.     break;
  87.   default:
  88.     return 0.0;
  89.     break;
  90.   }
  91.   return 0.0;
  92. }
  93. char Scan()
  94. {
  95.  int i, j, k;
  96.  double tmp;
  97.   double t;
  98.  s_iIndex++;
  99.  /* 取得一个操作数 */
  100.  for(i = 0; i < 4; i++)
  101.  {
  102.   if(s_cvUsed[i] != 1)
  103.   {
  104.    s_cvUsed[i] = 1;
  105.    /* 取得第二个操作数 */
  106.    for(j = 0; j < 4; j++)
  107.    {
  108.     if(s_cvUsed[j] != 1)
  109.     {
  110.      /* 记录这个操作数 */
  111.      tmp = s_dvVals[j];
  112.      /* 遍历所有支持的运算符 */
  113.      for(k = 0; k < OPER_NUM; k++)
  114.      {
  115.             s_cvOpers[s_iIndex - 1] = s_cvOperator[k];
  116.          s_dvRecords[s_iIndex - 1][0] = s_dvVals[i];
  117.          s_dvRecords[s_iIndex - 1][1] = tmp;
  118.             /* 避免重复 */
  119.             if(  s_cvOperType[k] == 0
  120.               && s_dvRecords[s_iIndex - 1][0] > s_dvRecords[s_iIndex - 1][1])
  121.             {
  122.               t = s_dvRecords[s_iIndex - 1][0];
  123.               s_dvRecords[s_iIndex - 1][0] = s_dvRecords[s_iIndex - 1][1];
  124.               s_dvRecords[s_iIndex - 1][1] = t;
  125.             }
  126.             s_dvVals[j] = Compute(
  127.               s_dvRecords[s_iIndex - 1][0],
  128.               s_dvRecords[s_iIndex - 1][1],
  129.               s_cvOperator[k]);
  130.             if(s_iIndex == 3)
  131.             {
  132.               if(s_dvVals[j] > s_dTarget - 0.00001 && s_dvVals[j] < s_dTarget + 0.00001)
  133.               {
  134.                 if(Outport())
  135.                 {
  136.                   s_iNum++;
  137.                 }
  138.               }
  139.             }
  140.             else
  141.             {
  142.               Scan();
  143.             }
  144.      }
  145.      /* 恢复这个操作数 */
  146.      s_dvVals[j] = tmp;
  147.     }
  148.    }
  149.    s_cvUsed[i] = 0;
  150.   }
  151.  }
  152.  s_iIndex--;
  153.   return 0;
  154. }
  155. char Outport()
  156. {
  157.   FILE * fp;
  158.   int i;
  159.   char cRepeated = 0;
  160.   char siTmp[200];
  161.   sprintf(siTmp,
  162.     "  第一步:{%lf %c %lf = %lf}/n"
  163.     "  第二步:{%lf %c %lf = %lf}/n"
  164.     "  第三步:{%lf %c %lf = %lf}",
  165.     s_dvRecords[0][0],
  166.     s_cvOpers[0],
  167.     s_dvRecords[0][1],
  168.     Compute(
  169.       s_dvRecords[0][0],
  170.       s_dvRecords[0][1],
  171.       s_cvOpers[0]),
  172.     s_dvRecords[1][0],
  173.     s_cvOpers[1],
  174.     s_dvRecords[1][1],
  175.     Compute(
  176.       s_dvRecords[1][0],
  177.       s_dvRecords[1][1],
  178.       s_cvOpers[1]),
  179.     s_dvRecords[2][0],
  180.     s_cvOpers[2],
  181.     s_dvRecords[2][1],
  182.     Compute(
  183.       s_dvRecords[2][0],
  184.       s_dvRecords[2][1],
  185.       s_cvOpers[2]));
  186.   /* 重复检查 */
  187.   for(i = 0; i < s_iNum; i++)
  188.   {
  189.     if(strcmp(siTmp, s_sivSave[i]) == 0)
  190.     {
  191.       cRepeated = 1;
  192.       break;
  193.     }
  194.   }
  195.   if(cRepeated == 0)
  196.   {
  197.     strcpy(s_sivSave[s_iNum], siTmp);
  198.     fp = fopen("Result.txt""a");
  199.     if(fp)
  200.     {
  201.       fprintf(fp, "%04d:/n%s/n", s_iNum, siTmp);
  202.       fclose(fp);
  203.     }
  204.   }
  205.   return 1 - cRepeated;
  206. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值