加减乘除24是一种扑克牌游戏,在一副扑克中随机抽取4张牌,使用牌上面的数字通过加减乘除计算出结果等于24的组合,先算出来的人获胜。曾经在学校的时候,实现过了这样的算法,列举出所有组合。现在发出来当做记录吧。
ac_cal24.h
#ifndef AC_CAL24_H
#define AC_CAL24_H
/// <summary>
/// 计算4个数加减乘除等于24的所有组合
/// </summary>
/// <param name="a">[in]数字1</param>
/// <param name="b">[in]数字2</param>
/// <param name="c">[in]数字3</param>
/// <param name="d">[in]数字4</param>
/// <param name="strResult">[out]结果缓存</param>
/// <param name="strResultLen">[in]结果缓存长度</param>
/// <param name="numberWritten">[out]实际写入结果缓存长度</param>
/// <returns>结果总长度:指示结果的真实长度,如果结果缓存长度较小时,结果缓存的内容是不完整的,只有结果缓存长度大于此返回值,结果才是完整的</returns>
int acf_cal24Point(int a, int b, int c, int d, char* strResult, int strResultLen,int* numberBytesWritten);
#endif
ac_cal24.c
#include "ac_cal24.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
static double getResult(double a, double b, int ch);
static double getCalResult(double num[4], int i, int j, int k, int l);
static char transferC(int n);
int acf_cal24Point(int a, int b, int c, int d, char* strResult, int strResultLen, int* numberWritten)
{
char strOneLine[128];
double num[] = { a, b, c, d };
double tNum[4];
double result;
int i, j, k, l, m;
int i1, j1, k1, l1;
j = -1; k = 0; l = 0; m = 0;
int pos = 0;
int len;
int sumLen = 0;
/*********************************************/
for (i = 0; i < 24; i++)/*计算所有排列方式*/
{
if (i % 6 == 0)
{
k = -1;
j++;
}
if (i % 2 == 0)
{
k++; l = -1; m = -1;
}
if (k == 4)
k = 0;
k = k % 4;
while (k == j)
{
k++;
}
l++;
if (l == 4)
l = 0;
l = l % 4;
while (l == k || l == j)
{
l++;
}
m++;
if (m == 4)
m = 0;
m = m % 4;
while (m == j || m == k || m == l)
{
m++;
if (m == 4)
m = 0;
m = m % 4;
}
if (k > 3)
{
if (k == 4)
k = 0;
k = k % 4;
}
if (l > 3)
{
if (k == l)
l = 0;
l = l % 4;
}
if (m > 3)
{
if (l == 4)
l = 0;
m = m % 4;
}
//将一次结果放入临时数组中
tNum[0] = num[j];
tNum[1] = num[k];
tNum[2] = num[l];
tNum[3] = num[m];
//对此排列方式加入加减乘除进行计算
for (i1 = 0; i1 < 4; i1++)//3个运算符4种情况+-*/排列组合
for (j1 = 0; j1 < 4; j1++)
for (k1 = 0; k1 < 4; k1++)
{
for (l1 = 0; l1 < 4; l1++)//加括号4种情况(1)不加;(2)前2个数;(3)前2个数后2个数;(4)前三个数;
{
result = getCalResult(tNum, i1, j1, k1, l1);//计算,ijk为运算符,l为括号标记
if (result == 24.00)//判断输出结果
{
char c1, c2, c3;
c1 = transferC(i1);
c2 = transferC(j1);
c3 = transferC(k1);
switch (l1)
{
case 0:
sprintf(strOneLine, "%d%c%d%c%d%c%d=24\n", (int)tNum[0], c1, (int)tNum[1], c2, (int)tNum[2], c3, (int)tNum[3]);
break; case 1:
sprintf(strOneLine, "(%d%c%d)%c%d%c%d=24\n", (int)tNum[0], c1, (int)tNum[1], c2, (int)tNum[2], c3, (int)tNum[3]);
break; case 2:
sprintf(strOneLine, "(%d%c%d)%c(%d%c%d)=24\n", (int)tNum[0], c1, (int)tNum[1], c2, (int)tNum[2], c3, (int)tNum[3]);
break; case 3:
sprintf(strOneLine, "(%d%c%d%c%d)%c%d=24\n", (int)tNum[0], c1, (int)tNum[1], c2, (int)tNum[2], c3, (int)tNum[3]);
break;
default:
break;
}
len = strlen(strOneLine);
if (pos + len < strResultLen)
{
memcpy(strResult + pos, strOneLine, len);
sumLen += len;
}
pos += len;
}
}
}
}
if(numberWritten)
*numberWritten = sumLen;
return pos;
}
static double getResult(double a, double b, int ch)//根据给定运算符给出2数计算结果
{
switch (ch)
{
case 0:
return a + b;
case 1: return a - b;
case 2: return a * b;
case 3:if (b == 0)
return 20000000;
return a / b;
default: return 0;
}
}
static double getCalResult(double num[4], int i, int j, int k, int l)
{
double a1, a2, a3;//暂时存放结果的变量
int b1, b2, b3, pure;//与上面变量a1,a2,a3对应的判断符(c没bool),pure为特殊判断
b1 = 0; b2 = 0; b3 = 0; pure = 0; a1 = 0; a2 = 0; a3 = 0;
/***************************//*第一部分*
运算符i
/*****************************/
if (l == 0 || l == 3)//括号(1)不加;(2)前2个数;(3)前2个数后2个数;(4)前三个数;
{
if (i >= 2)//大于等于2为乘或除 必得出a1
{
//a1=num[0]*num[1];
a1 = getResult(num[0], num[1], i);/*因为是情况(1)或(4)且第一个运算符为乘除,
可以直接运算得到第一个数a1;1*1 */
b1 = 1;
}
}
else if (l == 1 || l == 2)//括号(2)前2个数;(3)前2个数后2个数;必得出a1
{
a1 = getResult(num[0], num[1], i);
b1 = 1;
}
/*************************//*第一部分*
运算符j
/*************************//*第二部分*/
if (l == 0 || l == 1)//括号(1)不加;(2)前2个数;
{
if (j >= 2)//大于等于2为乘或除
{
if (b1 == 1)
{
//a2=num[2]*a1;
a2 = getResult(a1, num[2], j);//a1有值且与下一个数是乘除,直接与下一数计算;(1?1)*1或1*1*1
b2 = 1;
}
else
{
//a1=num[1]*num[2];
a1 = getResult(num[1], num[2], j);//a1没值,第2位与第3位数想乘除
b1 = 1;
}
}
else//j为加减
{
pure = 1;//a1=第1位第2位数计算结果且与第3位数没有必须计算关系
//a1=num[0]+num[1];
a1 = getResult(num[0], num[1], i);
b1 = 1;
}
}
else if (l == 3)//括号(4)前三个数; 必得出a2
{ //按无括号的加减乘除优先级继续运算
if (b1 == 1)
{
a2 = getResult(a1, num[2], j);
b2 = 1;
}
else
{
if (j >= 2)//大于等于2为乘或除
{
a1 = getResult(num[1], num[2], j);
b1 = 1;
a2 = getResult(num[0], a1, i);
b2 = 1;
}
else
{
a1 = getResult(num[0], num[1], i);
b1 = 1;
a2 = getResult(a1, num[2], j);
b2 = 1;
}
}
}
/*************************//*第二部分*
运算符k
/*************************//*第三部分*/
if (l == 2)//括号(3)前2个数后2个数;
{
a2 = getResult(num[2], num[3], k);
b2 = 1;
a3 = getResult(a1, a2, j);
b3 = 1;
}
else
{
if (k >= 2)//大于等于2为*/
{
if (pure == 1)//a1=前2个数,说明j为+-
{ //a2=num[2]*num[3];
a2 = getResult(num[2], num[3], k);
b2 = 1;
//a3=a1+a2;
a3 = getResult(a1, a2, j);
b3 = 1;
}
else if (b1 == 1 && b2 != 1)//a1=中间2个数,说明i为+-
{
//a2=num[3]*a1;
a2 = getResult(a1, num[3], k);
b2 = 1;
// a3=num[0]+a2;
a3 = getResult(num[0], a2, i);
b3 = 1;
}
else if (b2 == 1)//剩最后一位数
{
// a3=num[3]*a2;
a3 = getResult(a2, num[3], k);
b3 = 1;
}
}
else//小于2为+-
if (pure == 1)//a1=前2个数,说明j为+-
{
//a2=a1+num[2];
a2 = getResult(a1, num[2], j);
//a3=a2+num[3];
a3 = getResult(a2, num[3], k);
b3 = 1;
}
else
if (b1 == 1 && b2 != 1)//a1=中间2个数,说明i为+-
{
//a2=num[0]+a1;
a2 = getResult(num[0], a1, i);
//a3=a2+num[3];
a3 = getResult(a2, num[3], k);
//a3=getResult(num[1],num[2],j);
}
else
if (b2 == 1)//剩最后一位数
{
//a3=num[3]+a2;
a3 = getResult(a2, num[3], k);
b3 = 1;
}
}
/*************************//*第三部分*/
return a3;
}
static char transferC(int n)//运算符字符化
{
char ch;
switch (n)
{
case 0:ch = '+';
break;
case 1:ch = '-';
break;
case 2:ch = '*';
break;
case 3:ch = '/';
break;
default:
ch = '0';
break;
}
return ch;
}
main.cpp
extern"C" {
#include"Algorithm/ac_cal24.h"
}
unsigned char buf[1024 * 1024];
int main(int argc, char** argv) {
int len;
acf_cal24Point(5,6,8,3, (char*)buf, 1024 * 1024, &len);
buf[len] = 0;
printf("%s",buf);
}
输出结果:
(5-6/3)*8=24
(6-5)*8*3=24
(6-5)*(8*3)=24
(6-5)*3*8=24
(6-5)*(3*8)=24
(6*8)/(5-3)=24
(8*6)/(5-3)=24
(8*3)*(6-5)=24
(8*3)/(6-5)=24
(3*8)*(6-5)=24
(3*8)/(6-5)=24