#include <iostream>
#include <string.h>
#include <string>
#include <iomanip>
#include <time.h>
#include <math.h>
#include <stack>
#include <windows.h>
using namespace std;
#define ILLEGAL -1000.00 //表达式不合法的计算结果
double arrNum[4] = {0}; //随机生成的四张牌
int arrFlag[4] = {0}; //标记数字的使用与否
string str[4]; //搜索所有解时用于保存相应的字符串
string sAllAnsw[1000]; //所有可能的答案
int nAllAnsw = 0; //所有可能的答案的种类
/* ** 算法实现 ** */
bool IsLegal(int num); //判断四个数中是否包含num,并且判断num是否重复使用
int Priority(char operators); //制定运算符优先级
int Isoperator(char ch); //判断是否为运算符
void Mid_To_Back(string mid,char back[],int& n); //将中缀表达式转换成后缀表达式
double GetNum(char back[],int& i); //获取后缀表达式从i个位置起的数字
double CalculateBack(char back[],int n); //计算后缀表达式
double CalcExpression(string mid); //计算一个中缀表达式的值
void searchAllAnsw(int n); //找到所有解
/* ** 菜单维持 ** */
void mainMenu(); //主菜单
void startGame(); //开始游戏
void help(); //帮助菜单
void answer(); //回答问题
void IsNoans(); //确认无解
void lookAnsw(); //查看所有答案
void clearData(); //清除一些对下一步有影响的数据
int main()
{
bool IsExit = false; //是否退出
while(!IsExit)
{
int item;
mainMenu();
cout<<"请选择:";
cin>>item;
switch(item)
{
case 1: startGame(); break;
case 2: help(); break;
case 3: IsExit = true;break;
}
}
return 0;
}
//判断四个数中是否包含num,并且判断num是否重复使用
bool IsLegal(int num)
{
int i = 0;
for(i = 0; i < 4; i++)
{
if(arrNum[i] == num && 0 == arrFlag[i])
{
arrFlag[i] = 1;
return true;
}
}
return false;
}
//制定运算符优先级
int Priority(char operators)
{
switch(operators)
{
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
case '(':
return 0;
case '#':
return -1;
default:
return -1;
}
}
//判断是否为运算符
int Isoperator(char ch)
{
switch(ch)
{
case '*':
case '/':
case '+':
case '-':
return 1;
default:
return 0;
}
}
//将中缀表达式转换成后缀表达式
void Mid_To_Back(string mid,char back[],int& n)
{ //mid为中缀表达式,back为后缀表达式,n记录back的长度
int i = 0;
n = 0;
stack <char> opstack; //存放运算符
int length = mid.size();
opstack.push('#'); //进入栈底作为"哨兵"
for(i = 0; i < length; i++) //对mid进行遍历
{
if((mid[i] >= '0' && mid[i] <= '9') || mid[i] == '.')
{
back[n++] = mid[i]; //为数字,直接进入back
}
else if( Isoperator(mid[i]) )
{ //为运算符
back[n++] = ' '; //加入空格以区分数字
while(Priority(mid[i]) <= Priority(opstack.top()))
{ //优先级不大于栈内运算符
back[n++] = opstack.top();
opstack.pop(); //取栈顶运算符到back,并出栈
}
opstack.push(mid[i]);//运算符入栈
}
else if('(' == mid[i])
{
opstack.push(mid[i]);//为左括号,直接入栈
}
else if(')' == mid[i])
{
while('(' != opstack.top())
{ //为右括号
back[n++] = opstack.top();
opstack.pop(); //将栈内左括号以上的运算符移动到back
}
opstack.pop(); //将左括号出栈
}
else
{
//......
}
}
while('#' != opstack.top())
{
back[n++] = opstack.top();
opstack.pop(); //将栈内运算符移动到back
}
}
//获取后缀表达式从i个位置起的数字
double GetNum(char back[],int& i)
{ //i为数字后的位置
double x1 = 0.0; //存放整数
double x2 = 0.0; //存放小数
int flag = 1; //判断是否移动到小数点
double k = 10.0;
while((back[i] >= '0' && back[i] <= '9') || back[i] == '.')
{ //一直计算到非数字和小数点(空格和运算符)
if(back[i] == '.')
{
flag = 0;
i++;
continue; //为小数点,该步不计算
}
if(flag) //小数点之前
{
x1 = x1*10 + (back[i] - '0');
}
else //小数点之后
{
x2 += (back[i] - '0') / k;
k = k * 10;
}
i++;
}
return (x1+x2);
}
//计算后缀表达式
//后缀表达式里只有数字、运算符、空格
double CalculateBack(char back[],int n)
{ //n为back的长度
stack <double> restack; //结果栈
double x1 = 0.0; //每次运算前一个数字
double x2 = 0.0; //每次运算后一个数字
int i = 0;
for(i = 0; i < n; i++)
{
if(back[i] >= '0' && back[i] <= '9')
{ //为数字,进入结过栈
restack.push(GetNum(back,i));
if(!IsLegal(restack.top()))
{ //判断这个数字是否合法
return ILLEGAL;
}
i--; //由于下一步i++,这里减1
}
else if(' ' == back[i])
{ //空格
continue;
}
else
{ //运算符
x2 = restack.top(); //在结果栈里取出两个作运算
restack.pop();
x1 = restack.top();
restack.pop();
switch(back[i])
{
case '+': //再将计算结果入结果栈
{
restack.push(x1+x2);
break;
}
case '-':
{
restack.push(x1-x2);
break;
}
case '*':
{
restack.push(x1*x2);
break;
}
case '/':
{
restack.push(x1/x2);
break;
}
default:break;
}
}
} //现在栈内只有一个数字
return restack.top(); //就是后缀表达式的值
}
//计算一个中缀表达式的值
double CalcExpression(string mid)
{
int n = 0;
double result = 0; //结果
char back[100];
Mid_To_Back(mid,back,n); //将中缀表达式转化成后缀表达式
result = CalculateBack(back,n);//计算后缀表达式的值
for(int i = 0; i < 4; i++)
{
if(0 == arrFlag[i])
{ //四个数没有用完
return ILLEGAL; //表达式不合法
}
}
return result;
}
//找到所有解
void searchAllAnsw(int n)
{
int i,j;
double num_a, num_b;
string str_a,str_b;
if(1 == n)
{
//if(fabs(arrNum[0] - 24) < 1E-6)
if(arrNum[0] - 24 == 0)
{
sAllAnsw[nAllAnsw++] = str[0];
}
}
else
{
for(i = 0; i < n; i++)
{
for(j = i+1; j < n; j++)
{
num_a = arrNum[i];
num_b = arrNum[j];
arrNum[j] = arrNum[n-1];
str_a = str[i];
str_b = str[j];
str[j] = str[n-1];
//加
arrNum[i] = num_a + num_b;
str[i] = '(' + str_a + "+" + str_b + ')';
searchAllAnsw(n-1);
//减
arrNum[i] = num_a - num_b;
str[i] = '(' + str_a + "-" + str_b + ')';
searchAllAnsw(n-1);
//反减
arrNum[i] = num_b - num_a;
str[i] = '(' + str_b + "-" + str_a + ')';
searchAllAnsw(n-1);
//乘
arrNum[i] = num_a * num_b;
str[i] = '(' + str_a + "*" + str_b + ')';
searchAllAnsw(n-1);
//除
if(num_b != 0)
{
arrNum[i] = num_a / num_b;
str[i] = '(' + str_a + '/' + str_b + ')';
searchAllAnsw(n-1);
}
//反除
if(num_a != 0)
{
arrNum[i] = num_b / num_a;
str[i] = '(' + str_b + '/' + str_a + ')';
searchAllAnsw(n-1);
}
arrNum[i] = num_a; //回溯
arrNum[j] = num_b;
str[i] = str_a;
str[j] = str_b;
}
}
}
}
//加载游戏主菜单
void mainMenu()
{
system("cls");
cout<<" >>>>>> 欢迎来到24点游戏 <<<<<<<"<<endl<<endl;
cout<<" 1、开始游戏 "<<endl<<endl;
cout<<" 2、查看帮助 "<<endl<<endl;
cout<<" 3、退出游戏 "<<endl<<endl;
}
//加载游戏菜单
void gameMenu()
{
string sPoker[] = {"0","A","2","3","4","5","6","7","8","9","10","J","Q","K"}; //13张牌
system("cls");
cout<<" >>>>>> 游戏菜单 <<<<<<<<"<<endl<<endl<<endl;
cout<<" "<<sPoker[(int)arrNum[0]]<<" "<<sPoker[(int)arrNum[1]]
<<" "<<sPoker[(int)arrNum[2]]<<" "<<sPoker[(int)arrNum[3]]<<endl<<endl;
cout<<" 1、开始答题 "<<endl<<endl;
cout<<" 2、确认无解 "<<endl<<endl;
cout<<" 3、查看答案 "<<endl<<endl;
cout<<" 4、返回主菜单 "<<endl<<endl;
}
//为开始游戏做一些准备
void startGame()
{
bool IsExit = false; //是否退出游戏菜单
srand(time(NULL));
for(int i = 0; i < 4; i++)
{ //随机获取4张牌
arrNum[i] = rand() % 13 + 1;
char ch[10];
itoa(arrNum[i],ch,10); //将数字转换为字符串
str[i] = ch;
}
while(!IsExit)
{
gameMenu();
fflush(stdin);
int item;
cout<<"请选择:";
cin>>item;
switch(item)
{
case 1: answer(); break;
case 2: IsNoans(); break;
case 3: lookAnsw(); break;
case 4: IsExit = true; break;
}
clearData();
}
}
//帮助菜单
void help()
{
cout<<"说明: 24点纸牌游戏一个益智类的数字游戏"<<endl;
cout<<"规则: 系统随机出四张牌 "<<endl;
cout<<" 你需要用加减乘除和括号使之等于24"<<endl;
fflush(stdin);
cout<<"按任意键返回主菜单"<<endl;
getchar();
}
void answer()
{
string sMid; //中缀表达式
cin>>sMid; //输入表达式
double result; //结果
result = CalcExpression(sMid);
if(ILLEGAL == result) //检验结果
{
cout<<"你输入的运算表达式不合法"<<endl;
}
else if(0 == result - 24)
{
cout<<"恭喜,回答正确 !"<<endl;
}
else
{
cout<<"大遗憾了! 回答错误"<<endl;
}
fflush(stdin);
cout<<"按任意键返回主菜单"<<endl;
getchar();
}
//确认无解
void IsNoans()
{
if(0 == nAllAnsw)
{
searchAllAnsw(4);
}
if(0 == nAllAnsw)
{
cout<<"回答正确!"<<endl;
}
else
{
cout<<"还有答案哦!"<<endl;
}
cout<<"按任意键返回"<<endl;
fflush(stdin);
getchar();
}
//查看所有答案
void lookAnsw()
{
if(0 == nAllAnsw)
{
searchAllAnsw(4);
}
for(int i = 0; i < nAllAnsw; i++)
{
cout<<left<<setw(2)<<i+1<<": "<<sAllAnsw[i]<<endl;
}
if(0 == nAllAnsw)
{
cout<<"无解!"<<endl;
}
cout<<"按任意键返回"<<endl;
fflush(stdin);
getchar();
}
//清除一些对下一步有影响的数据
void clearData()
{
for(int i = 0; i < nAllAnsw; i++)
{
sAllAnsw[i] = "";
}
nAllAnsw = 0;
}
#include <string.h>
#include <string>
#include <iomanip>
#include <time.h>
#include <math.h>
#include <stack>
#include <windows.h>
using namespace std;
#define ILLEGAL -1000.00 //表达式不合法的计算结果
double arrNum[4] = {0}; //随机生成的四张牌
int arrFlag[4] = {0}; //标记数字的使用与否
string str[4]; //搜索所有解时用于保存相应的字符串
string sAllAnsw[1000]; //所有可能的答案
int nAllAnsw = 0; //所有可能的答案的种类
/* ** 算法实现 ** */
bool IsLegal(int num); //判断四个数中是否包含num,并且判断num是否重复使用
int Priority(char operators); //制定运算符优先级
int Isoperator(char ch); //判断是否为运算符
void Mid_To_Back(string mid,char back[],int& n); //将中缀表达式转换成后缀表达式
double GetNum(char back[],int& i); //获取后缀表达式从i个位置起的数字
double CalculateBack(char back[],int n); //计算后缀表达式
double CalcExpression(string mid); //计算一个中缀表达式的值
void searchAllAnsw(int n); //找到所有解
/* ** 菜单维持 ** */
void mainMenu(); //主菜单
void startGame(); //开始游戏
void help(); //帮助菜单
void answer(); //回答问题
void IsNoans(); //确认无解
void lookAnsw(); //查看所有答案
void clearData(); //清除一些对下一步有影响的数据
int main()
{
bool IsExit = false; //是否退出
while(!IsExit)
{
int item;
mainMenu();
cout<<"请选择:";
cin>>item;
switch(item)
{
case 1: startGame(); break;
case 2: help(); break;
case 3: IsExit = true;break;
}
}
return 0;
}
//判断四个数中是否包含num,并且判断num是否重复使用
bool IsLegal(int num)
{
int i = 0;
for(i = 0; i < 4; i++)
{
if(arrNum[i] == num && 0 == arrFlag[i])
{
arrFlag[i] = 1;
return true;
}
}
return false;
}
//制定运算符优先级
int Priority(char operators)
{
switch(operators)
{
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
case '(':
return 0;
case '#':
return -1;
default:
return -1;
}
}
//判断是否为运算符
int Isoperator(char ch)
{
switch(ch)
{
case '*':
case '/':
case '+':
case '-':
return 1;
default:
return 0;
}
}
//将中缀表达式转换成后缀表达式
void Mid_To_Back(string mid,char back[],int& n)
{ //mid为中缀表达式,back为后缀表达式,n记录back的长度
int i = 0;
n = 0;
stack <char> opstack; //存放运算符
int length = mid.size();
opstack.push('#'); //进入栈底作为"哨兵"
for(i = 0; i < length; i++) //对mid进行遍历
{
if((mid[i] >= '0' && mid[i] <= '9') || mid[i] == '.')
{
back[n++] = mid[i]; //为数字,直接进入back
}
else if( Isoperator(mid[i]) )
{ //为运算符
back[n++] = ' '; //加入空格以区分数字
while(Priority(mid[i]) <= Priority(opstack.top()))
{ //优先级不大于栈内运算符
back[n++] = opstack.top();
opstack.pop(); //取栈顶运算符到back,并出栈
}
opstack.push(mid[i]);//运算符入栈
}
else if('(' == mid[i])
{
opstack.push(mid[i]);//为左括号,直接入栈
}
else if(')' == mid[i])
{
while('(' != opstack.top())
{ //为右括号
back[n++] = opstack.top();
opstack.pop(); //将栈内左括号以上的运算符移动到back
}
opstack.pop(); //将左括号出栈
}
else
{
//......
}
}
while('#' != opstack.top())
{
back[n++] = opstack.top();
opstack.pop(); //将栈内运算符移动到back
}
}
//获取后缀表达式从i个位置起的数字
double GetNum(char back[],int& i)
{ //i为数字后的位置
double x1 = 0.0; //存放整数
double x2 = 0.0; //存放小数
int flag = 1; //判断是否移动到小数点
double k = 10.0;
while((back[i] >= '0' && back[i] <= '9') || back[i] == '.')
{ //一直计算到非数字和小数点(空格和运算符)
if(back[i] == '.')
{
flag = 0;
i++;
continue; //为小数点,该步不计算
}
if(flag) //小数点之前
{
x1 = x1*10 + (back[i] - '0');
}
else //小数点之后
{
x2 += (back[i] - '0') / k;
k = k * 10;
}
i++;
}
return (x1+x2);
}
//计算后缀表达式
//后缀表达式里只有数字、运算符、空格
double CalculateBack(char back[],int n)
{ //n为back的长度
stack <double> restack; //结果栈
double x1 = 0.0; //每次运算前一个数字
double x2 = 0.0; //每次运算后一个数字
int i = 0;
for(i = 0; i < n; i++)
{
if(back[i] >= '0' && back[i] <= '9')
{ //为数字,进入结过栈
restack.push(GetNum(back,i));
if(!IsLegal(restack.top()))
{ //判断这个数字是否合法
return ILLEGAL;
}
i--; //由于下一步i++,这里减1
}
else if(' ' == back[i])
{ //空格
continue;
}
else
{ //运算符
x2 = restack.top(); //在结果栈里取出两个作运算
restack.pop();
x1 = restack.top();
restack.pop();
switch(back[i])
{
case '+': //再将计算结果入结果栈
{
restack.push(x1+x2);
break;
}
case '-':
{
restack.push(x1-x2);
break;
}
case '*':
{
restack.push(x1*x2);
break;
}
case '/':
{
restack.push(x1/x2);
break;
}
default:break;
}
}
} //现在栈内只有一个数字
return restack.top(); //就是后缀表达式的值
}
//计算一个中缀表达式的值
double CalcExpression(string mid)
{
int n = 0;
double result = 0; //结果
char back[100];
Mid_To_Back(mid,back,n); //将中缀表达式转化成后缀表达式
result = CalculateBack(back,n);//计算后缀表达式的值
for(int i = 0; i < 4; i++)
{
if(0 == arrFlag[i])
{ //四个数没有用完
return ILLEGAL; //表达式不合法
}
}
return result;
}
//找到所有解
void searchAllAnsw(int n)
{
int i,j;
double num_a, num_b;
string str_a,str_b;
if(1 == n)
{
//if(fabs(arrNum[0] - 24) < 1E-6)
if(arrNum[0] - 24 == 0)
{
sAllAnsw[nAllAnsw++] = str[0];
}
}
else
{
for(i = 0; i < n; i++)
{
for(j = i+1; j < n; j++)
{
num_a = arrNum[i];
num_b = arrNum[j];
arrNum[j] = arrNum[n-1];
str_a = str[i];
str_b = str[j];
str[j] = str[n-1];
//加
arrNum[i] = num_a + num_b;
str[i] = '(' + str_a + "+" + str_b + ')';
searchAllAnsw(n-1);
//减
arrNum[i] = num_a - num_b;
str[i] = '(' + str_a + "-" + str_b + ')';
searchAllAnsw(n-1);
//反减
arrNum[i] = num_b - num_a;
str[i] = '(' + str_b + "-" + str_a + ')';
searchAllAnsw(n-1);
//乘
arrNum[i] = num_a * num_b;
str[i] = '(' + str_a + "*" + str_b + ')';
searchAllAnsw(n-1);
//除
if(num_b != 0)
{
arrNum[i] = num_a / num_b;
str[i] = '(' + str_a + '/' + str_b + ')';
searchAllAnsw(n-1);
}
//反除
if(num_a != 0)
{
arrNum[i] = num_b / num_a;
str[i] = '(' + str_b + '/' + str_a + ')';
searchAllAnsw(n-1);
}
arrNum[i] = num_a; //回溯
arrNum[j] = num_b;
str[i] = str_a;
str[j] = str_b;
}
}
}
}
//加载游戏主菜单
void mainMenu()
{
system("cls");
cout<<" >>>>>> 欢迎来到24点游戏 <<<<<<<"<<endl<<endl;
cout<<" 1、开始游戏 "<<endl<<endl;
cout<<" 2、查看帮助 "<<endl<<endl;
cout<<" 3、退出游戏 "<<endl<<endl;
}
//加载游戏菜单
void gameMenu()
{
string sPoker[] = {"0","A","2","3","4","5","6","7","8","9","10","J","Q","K"}; //13张牌
system("cls");
cout<<" >>>>>> 游戏菜单 <<<<<<<<"<<endl<<endl<<endl;
cout<<" "<<sPoker[(int)arrNum[0]]<<" "<<sPoker[(int)arrNum[1]]
<<" "<<sPoker[(int)arrNum[2]]<<" "<<sPoker[(int)arrNum[3]]<<endl<<endl;
cout<<" 1、开始答题 "<<endl<<endl;
cout<<" 2、确认无解 "<<endl<<endl;
cout<<" 3、查看答案 "<<endl<<endl;
cout<<" 4、返回主菜单 "<<endl<<endl;
}
//为开始游戏做一些准备
void startGame()
{
bool IsExit = false; //是否退出游戏菜单
srand(time(NULL));
for(int i = 0; i < 4; i++)
{ //随机获取4张牌
arrNum[i] = rand() % 13 + 1;
char ch[10];
itoa(arrNum[i],ch,10); //将数字转换为字符串
str[i] = ch;
}
while(!IsExit)
{
gameMenu();
fflush(stdin);
int item;
cout<<"请选择:";
cin>>item;
switch(item)
{
case 1: answer(); break;
case 2: IsNoans(); break;
case 3: lookAnsw(); break;
case 4: IsExit = true; break;
}
clearData();
}
}
//帮助菜单
void help()
{
cout<<"说明: 24点纸牌游戏一个益智类的数字游戏"<<endl;
cout<<"规则: 系统随机出四张牌 "<<endl;
cout<<" 你需要用加减乘除和括号使之等于24"<<endl;
fflush(stdin);
cout<<"按任意键返回主菜单"<<endl;
getchar();
}
void answer()
{
string sMid; //中缀表达式
cin>>sMid; //输入表达式
double result; //结果
result = CalcExpression(sMid);
if(ILLEGAL == result) //检验结果
{
cout<<"你输入的运算表达式不合法"<<endl;
}
else if(0 == result - 24)
{
cout<<"恭喜,回答正确 !"<<endl;
}
else
{
cout<<"大遗憾了! 回答错误"<<endl;
}
fflush(stdin);
cout<<"按任意键返回主菜单"<<endl;
getchar();
}
//确认无解
void IsNoans()
{
if(0 == nAllAnsw)
{
searchAllAnsw(4);
}
if(0 == nAllAnsw)
{
cout<<"回答正确!"<<endl;
}
else
{
cout<<"还有答案哦!"<<endl;
}
cout<<"按任意键返回"<<endl;
fflush(stdin);
getchar();
}
//查看所有答案
void lookAnsw()
{
if(0 == nAllAnsw)
{
searchAllAnsw(4);
}
for(int i = 0; i < nAllAnsw; i++)
{
cout<<left<<setw(2)<<i+1<<": "<<sAllAnsw[i]<<endl;
}
if(0 == nAllAnsw)
{
cout<<"无解!"<<endl;
}
cout<<"按任意键返回"<<endl;
fflush(stdin);
getchar();
}
//清除一些对下一步有影响的数据
void clearData()
{
for(int i = 0; i < nAllAnsw; i++)
{
sAllAnsw[i] = "";
}
nAllAnsw = 0;
}