c语言实现加减乘除24算法

加减乘除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

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeOfCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值