算24点小游戏
说明
分别使用C语言和C++实现算24点小游戏。考虑到会出现相同的数字组合,如果不排除就会产生重复结果,因此,用C语言实现了简单的set功能, C++则可以直接使用STL。
C file struct
|----cal24
|----cal24.h
|----cal24.c
|----set.h
|----set.c
|----main.c
|----CMakeLists.txt
C++ file struct
|----cal24
|----cal24.hpp
|----main.cpp
|----CMakeLists.txt
C代码
set.h
#ifndef __SET_H__
#define __SET_H__
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct _node;
typedef struct _node{
void *val;
struct _node *next;
} node;
typedef struct {
int size;
node *begain;
} set;
void set_insert(set *s, void *x, int data_size);
void set_free(set *s);
#endif
set.c
#include "set.h"
void set_insert(set *s, void *x, int data_size)
{
node *v = (node *)calloc(1, sizeof(node));
v->val = malloc(data_size);
memcpy(v->val, x, data_size);
v->next = NULL;
if(!s->begain) {
s->size = 1;
s->begain = v;
} else {
node *t = s->begain;
node *p = NULL;
char *insertv = (char*)v->val;
while(t) {
char *curr = (char *)t->val;
int countequal = 0;
for(int i=0; i<data_size; ++i)
countequal += (curr[i] == insertv[i]);
if(countequal == data_size)
return;
p = t;
t = t->next;
}
p->next = v;
++s->size;
}
}
void set_free(set *s)
{
node *t = s->begain;
node *x = t;
while(t) {
x = t->next;
free(t->val);
free(t);
t = x;
}
s->size = 0;
}
cal24.h
#ifndef __CAL24_H__
#define __CAL24_H__
#include "math.h"
#include "set.h"
#ifdef __cplusplus
extern "C" {
#endif
enum oper {add, sub, mul, _div};
void get_number_list(set *s, float a, float b, float c ,float d);
int cal24(set *s);
#ifdef __cplusplus
}
#endif
#endif
cal24.c
#include "cal24.h"
const char operc[5] = {'+', '-', '*', '/'};
int num = 0;
float oper_cal(float x, float y, enum oper c)
{
float res = 0;
switch (c) {
case add: res = x + y; break;
case sub: res = x - y; break;
case mul: res = x * y; break;
case _div: res = x / (y != 0 ? y : 0.01); break;
};
return res;
}
void bracket_cal(float a, float b, float c, float d, enum oper *cal)
{
float y = oper_cal(oper_cal(oper_cal(a, b, cal[0]), c, cal[1]), d, cal[2]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("((%.0f %c %.0f) %c %.0f) %c %.0f = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(oper_cal(a, b, cal[0]), oper_cal(c, d, cal[2]), cal[1]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("(%.0f %c %.0f) %c (%.0f %c %.0f) = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(oper_cal(a, oper_cal(b, c, cal[1]), cal[0]), d, cal[2]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("(%.0f %c (%.0f %c %.0f)) %c %.0f = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(a, oper_cal(oper_cal(b, c, cal[1]), d, cal[2]), cal[0]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("%.0f %c ((%.0f %c %.0f) %c %.0f) = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(a, oper_cal(b, oper_cal(c, d, cal[2]), cal[1]), cal[0]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("%.0f %c (%.0f %c (%.0f %c %.0f)) = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
}
int cal24(set *s)
{
float a,b,c,d;
float data[4];
enum oper cal[3] = {add, add, add};
node *t = s->begain;
printf("data has %d group(s) total\n", s->size);
while(t) {
memcpy(data, t->val, 4*sizeof(float));
a = data[0];
b = data[1];
c = data[2];
d = data[3];
for(enum oper c1 = add; c1 <= _div; ++c1) {
cal[0] = c1;
for(enum oper c2 = add; c2 <= _div; ++c2) {
cal[1] = c2;
for(enum oper c3 = add; c3 <= _div; ++c3) {
cal[2] = c3;
bracket_cal(a, b, c, d, cal);
}
}
}
t = t->next;
}
return num;
}
void get_number_list(set *s, float a, float b, float c ,float d)
{
float nums[4] = {a, b, c, d};
float t1, t2, t3, t4;
for(int i=0; i<4; ++i) {
t1 = nums[i];
for(int j=0; j<4; ++j) {
if(j != i) {
t2 = nums[j];
for(int k=0; k<4; ++k) {
if((k != i) && (k != j)) {
t3 = nums[k];
for(int r=0; r<4; ++r) {
if((r!=i) && (r !=j) &&(r !=k)) {
t4 = nums[r];
float insert[4] = {t1, t2, t3, t4};
set_insert(s, (void*)insert, 4*sizeof(float));
}
}
}
}
}
}
}
}
main.c
#include "cal24.h"
#include "stdio.h"
#define OPER(x,y,op) x op y
int main(void *arg)
{
float a, b, c, d;
set *s = (set *)calloc(1, sizeof(set));
s->size = 0;
s->begain = NULL;
printf("input 1st numbers:");
scanf("%f", &a);
printf("input 2nd numbers:");
scanf("%f", &b);
printf("input 3th numbers:");
scanf("%f", &c);
printf("input 4th numbers:");
scanf("%f", &d);
get_number_list(s, a, b, c, d);
int num = cal24(s);
printf("input numbers are %.0f, %.0f, %.0f, %.0f\n", a, b, c, d);
printf("There are %d calculation methods", num);
set_free(s);
free(s);
return 0;
}
CMakeLists.txt
project(test)
cmake_minimum_required(VERSION 3.24)
aux_source_directory(cal24 APP_SRC)
include_directories(cal24)
add_executable(${PROJECT_NAME} main.c ${APP_SRC})
C++代码
cal24.hpp
#ifndef __CAL24_HPP__
#define __CAL24_HPP__
#include <math.h>
#include <stdio.h>
#include <array>
#include <set>
enum oper {add, sub, mul, _div, other};
const char operc[5] = {'+', '-', '*', '/'};
oper &operator++(oper &d)
{
return d = (d == other) ? oper::add : oper(d+1);
}
static float oper_cal(float x, float y, enum oper c)
{
float res = 0;
switch (c) {
case add: res = x + y; break;
case sub: res = x - y; break;
case mul: res = x * y; break;
case _div: res = x / (y != 0 ? y : 0.01); break;
};
return res;
}
class Cal24 {
float a;
float b;
float c;
float d;
int num;
std::set<std::array<float, 4>> data;
void cal_numbers(const float &a, const float &b, const float &c, const float &d, enum oper *cal)
{
float y = oper_cal(oper_cal(oper_cal(a, b, cal[0]), c, cal[1]), d, cal[2]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("((%.0f %c %.0f) %c %.0f) %c %.0f = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(oper_cal(a, b, cal[0]), oper_cal(c, d, cal[2]), cal[1]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("(%.0f %c %.0f) %c (%.0f %c %.0f) = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(oper_cal(a, oper_cal(b, c, cal[1]), cal[0]), d, cal[2]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("(%.0f %c (%.0f %c %.0f)) %c %.0f = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(a, oper_cal(oper_cal(b, c, cal[1]), d, cal[2]), cal[0]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("%.0f %c ((%.0f %c %.0f) %c %.0f) = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
y = oper_cal(a, oper_cal(b, oper_cal(c, d, cal[2]), cal[1]), cal[0]);
if((fabs(y - 24.0) < 0.01)) {
++num;
printf("%.0f %c (%.0f %c (%.0f %c %.0f)) = 24\n",a, operc[cal[0]], b, operc[cal[1]], c, operc[cal[2]], d);
}
}
void cal24(const float &a, const float &b, const float &c, const float &d)
{
oper cal[3] = {add, add, add};
for(oper c1 = add; c1 <= _div; ++c1) {
cal[0] = (oper)c1;
for(oper c2 = add; c2 <= _div; ++c2) {
cal[1] = (oper)c2;
for(oper c3 = add; c3 <= _div; ++c3) {
cal[2] = (oper)c3;
cal_numbers(a, b, c, d, cal);
}
}
}
}
void init_set()
{
num = 0;
data.swap(std::set<std::array<float, 4>>());
std::array<float, 4> input({a, b, c, d});
float t1 = 0., t2 = 0., t3 = 0., t4 = 0.;
for(int i=0; i<4; ++i) {
t1 = input[i];
for(int j=0; j<4; ++j) {
if(j != i) {
t2 = input[j];
for(int k=0; k<4; ++k) {
if((k != i) && (k != j)) {
t3 = input[k];
for(int r=0; r<4; ++r) {
if((r!=i) && (r !=j) &&(r !=k)) {
t4 = input[r];
std::array<float, 4> tmp({t1, t2, t3, t4});
data.insert(tmp);
}
}
}
}
}
}
}
}
public:
Cal24():a(0), b(0), c(0), d(0), num(0), data(){}
~Cal24()
{
num = 0;
data.swap(std::set<std::array<float, 4>>());
//data.clear();
}
void get_numbers(const float &x, const float &y, const float &z, const float &w)
{
a = x;
b = y;
c = z;
d = w;
init_set();
}
void execute()
{
for(auto i = data.begin(); i != data.end(); ++i) {
float x = (*i)[0];
float y = (*i)[1];
float w = (*i)[2];
float z = (*i)[3];
cal24(x, y, w, z);
}
printf("input numbers are %.0f, %.0f, %.0f, %.0f\n", a, b, c, d);
printf("There are %d calculation methods", num);
}
};
#endif
main.cpp
#include <iostream>
#include "cal24.hpp"
int main()
{
float a, b, c, d;
std::cout<<"input number 1:";
std::cin >>a;
std::cout<<"input number 2:";
std::cin >>b;
std::cout<<"input number 3:";
std::cin >>c;
std::cout<<"input number 4:";
std::cin >>d;
Cal24 e;
e.get_numbers(a,b,c,d);
e.execute();
return 0;
}
CMakeLists.txt
project(test)
cmake_minimum_required(VERSION 3.24)
aux_source_directory(cal24 APP_SRC)
include_directories(cal24)
add_executable(${PROJECT_NAME} main.c ${APP_SRC})