作者:罗傲宇
日期:2019/4/12
运行环境:Visual C++ 6.0
一、问题描述:
24点游戏是经典的纸牌益智游戏。
常见游戏规则:
从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要求编程解决24点游戏。
基本要求: 随机生成4个代表扑克牌牌面的数字字母,程序自动列出所有可能算出24的表达式。
1.程序风格良好(使用自定义注释模板)
2.列出表达式无重复。
提高要求:用户初始生命值为一给定值(比如3),初始分数为0。随机生成4个代表扑克牌牌面的数字或字母,由用户输入包含这4个数字或字母的运算表达式(可包含括号),如果表达式计算结果为24则代表用户赢了此局。
1. 程序风格良好(使用自定义注释模板)
2.使用计时器要求用户在规定时间内输入表达式,如果规定时间内运算正确则加分,超时或运算错误则进入下一题并减少生命值(不扣分)。
3.所有成绩均可记录在TopList.txt文件中。
二、算法设计思路及流程图:
算法分析:
1.基本要求:
先用rand()函数将四个1-13的随机数存入结构体
数组a[]中,其中symbol表示该数是否进行过操作,若为0则未进行过操作,若为1则表示已进行过操作;
caculate()函数返回两数进行基本操作后的值;
judgement()函数里面先将4个随机数的任意两个
数进行四种运算操作,在每一次运算操作后将该次操作结果赋给temp1;然后再将temp1与余下未进行操作数的任一个进行四种操作运算,在每一次操作后再将结果赋给temp2;然后再将temp2与余下的一个未进行操作的数进行四种操作运算,在每一次操作后再将结果赋给temp3,若temp324,则将操作数与操作符按序输出即为表达式。
2.提高要求
利用出栈入栈操作对中缀表达式进行运算并判断
定义栈内元素为结构体数组,该结构体类型包含操作数num和操作标识符symbol;若symbol1则进行’+’ ‘-’操作,若symbol==2则进行’’ ‘/’操作;
Init()函数初始化栈;
Push()函数将操作数入栈;
Pop()函数将栈顶元素取出;
dispaly()函数将表达式键入并用getchar()函数对输入的每个字符进行判断,若为个位整数,则入栈,若为’+’ ‘-’符则栈顶元素symbol为1,若为’’ ‘/’符则栈顶元素symbol为2,若为’(‘符则lay为1,若为’)’符则lay为0;判断栈顶第二个元素symbol的值,若为0,为出栈两个操作数合成十位数再入栈,若为2且lay不为1则出栈两个数进行’*’或‘/’操作后将结果入栈,若为1且lay为1则进行’+’ ‘-’操作后将结果入栈;上述操作完后出栈栈顶元素,返回栈顶元素。
在键入表达式前设置开始计时器start,在输入完后设置结束计时器end;
game()函数将display()输入的表达式运算结果进行判断,若为24且键入表达式时间(end-start)不多于30s,则得分+1,否则生命值-1,若生命值为0则游戏结束。
流程图:
1.基本要求
2.提高要求
三、代码实现
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define MAX 20
bool size=false; /*标志是否有运算结果,是则为true,否则为false*/
int line=1;
typedef struct /*定义操作数结构体,a为操作数的值,symbol标示进行的操作*/
{
double a;
int symbol;
}task;
typedef struct
{
task data[MAX];
int top;
}seqlist;
seqlist *Init() /*初始化栈*/
{
seqlist *s;
s=(seqlist *)malloc(sizeof(seqlist));
s->top=-1;
return s;
}
int Push(seqlist *s,double x) /*将操作数入栈*/
{
s->top++;
s->data[s->top].a=x;
s->data[s->top].symbol=0;
return 1;
}
int Pop(seqlist *s,double *x)
{
*x=s->data[s->top].a;
s->top--;
return 1;
}
struct Number /*24点随机四个数*/
{
int symbol;
double num;
}a[4];
double caculate(double num1,double num2,char caculate) /*计算两数的操作结果*/
{
switch(caculate)
{
case '+':
return(num1+num2);
case '-':
return(num1-num2);
case '*':
return(num1*num2);
case '/':
return(num1/num2);
}
return 0;
}
void judgement(char c[4]) /*列出四种数所有可能的情况*/
{
int i,j,m,n,o,p,q;
double temp1,temp2,temp3;
for(i=0;i<4;i++)
{
for(j=i+1;j<4;j++)
{
for(o=0;o<4;o++) /*四种数任取两种先进行运算*/
{
temp1=double(caculate(a[i].num,a[j].num,c[o]));
a[i].symbol=0;
a[j].symbol=0;
for(m=0;m<4;m++)
{
if(a[m].symbol!=0)
{
for(p=0;p<4;p++) /*任取剩余一个数与上一个结果进行运算*/
{
temp2=caculate(temp1,a[m].num,c[p]);
a[m].symbol=0;
for(n=0;n<4;n++)
{
if(a[n].symbol!=0)
{
for(q=0;q<4;q++) /*将最后一个数与上一次结果进行运算得到结果*/
{
temp3=caculate(temp2,a[n].num,c[q]);
if(temp3==24) /*若结果等于24,则打印出该表达式*/
{
if(o<2&&p<2&&q<2)
printf("\n%d%c%d%c%d%c%d",int(a[i].num),c[o],int(a[j].num),c[p],int(a[m].num),c[q],int(a[n].num));
else if(o<2&&p<2&&q>=2)
printf("\n(%d%c%d%c%d)%c%d",int(a[i].num),c[o],int(a[j].num),c[p],int(a[m].num),c[q],int(a[n].num));
else if(o<2&&p>=2)
printf("\n(%d%c%d)%c%d%c%d",int(a[i].num),c[o],int(a[j].num),c[p],int(a[m].num),c[q],int(a[n].num));
else if(o>2&&p<2&&q>2)
printf("\n((%d%c%d)%c%d)%c%d",int(a[i].num),c[o],int(a[j].num),c[p],int(a[m].num),c[q],int(a[n].num));
else if(o>2)
printf("\n%d%c%d%c%d%c%d",int(a[i].num),c[o],int(a[j].num),c[p],int(a[m].num),c[q],int(a[n].num));
size=true;
}
}
}
}
a[m].symbol=1;
}
}
}
a[j].symbol=1;
}
}
a[i].symbol=1;
}
}
int display() /*对输入的表达式进行运算并判断的函数*/
{
seqlist *s;
char ch,ch2;
char ch3[MAX];
int i=0,lay;
double o1,o2,temp,ch1; /*o1表示栈顶元素,o2表示栈顶第二个元素,temp临时存储两数操作后的值*/
s=Init();
printf("\n\n\t\t请输入表达式:");
while((ch=getchar())!='\n')
{
if(ch==' ')
continue;
if(ch>47&&ch<58)
{
ch1=ch-48;
Push(s,ch1);
}
else if(ch=='+'||ch=='-')
{
s->data[s->top].symbol=1;
ch3[i++]=ch;
continue;
}
else if(ch=='*'||ch=='/')
{
s->data[s->top].symbol=2;
ch2=ch;
continue;
}
else if(ch=='(')
{
lay=1;
}
else if(ch==')')
{
lay=0;
}
if(lay!=1&&s->data[s->top-1].symbol==2)
{
Pop(s,&o1);
Pop(s,&o2);
temp=caculate(o2,o1,ch2);
Push(s,temp);
}
if(lay==1&&s->data[s->top-1].symbol==1)
{
Pop(s,&o1);
Pop(s,&o2);
temp=caculate(o2,o1,ch3[--i]);
Push(s,temp);
}
if(s->top!=0&&s->data[s->top-1].symbol==0)
{
Pop(s,&o1);
Pop(s,&o2);
temp=o2*10+o1;
Push(s,temp);
}
}
for(int j=i;j>0;j--)
{
Pop(s,&o1);
Pop(s,&o2);
temp=caculate(o2,o1,ch3[j-1]);
Push(s,temp);
}
Pop(s,&o1);
return((int)o1);
}
void game() /*开始游戏*/
{
FILE *fp;
fp=fopen("TopList.txt","at");
int i,j,m,sum[4];
double temp;
clock_t end,start; /*设置计时器计算键入表达式时间*/
i=3;
m=0;
printf(" *************输入表达式请在30s内输入*************\n\n\n");
while(i)
{
if(line!=0)
{
line--;
if(getchar()=='\n')
continue;
}
srand((int)time(0));
for(j=0;j<4;j++)
{
sum[j]=rand()%13+1;
}
printf("\t四个随机数为:");
for(j=0;j<4;j++)
printf("%-4d",(int)sum[j]);
start=clock(); /*记录刚开始输入表达式时间*/
if(display()==24)
{
end=clock(); /*记录输入表达式后时间*/
temp=(double)(end-start)/1000;
if(temp<30)
m++;
else
{
printf("\t\t输入超时!");
i--;
}
}
else
i--;
printf("\n\t\t\t\t得分:%d\n\n",m);
}
fprintf(fp,"该次游戏的总得分为:%d\n\n",m);
fclose(fp);
printf("***----------------游戏结束----------------***\n");
}
void menu() /*选择是否继续游戏的菜单函数*/
{
int choose;
printf("\n\t\t请选择是否进行游戏:");
printf("\n\t\t\t1.进行游戏");
printf("\n\t\t\t2.结果程序");
printf("\n\n\t\t选择序号:");
scanf("%d",&choose);
switch(choose)
{
case 1:
system("cls");
game();
break;
case 2:
return;
}
}
int main()
{
char c[4]={
'+','-','*','/'};
srand((int)time(0));
for(int i=0;i<4;i++)
{
a[i].num=rand()%13+1;
a[i].symbol=1;
}
printf("四个随机数为:");
for(i=0;i<4;i++)
printf("%4d",(int)a[i].num);
printf("\n可满足表达式:");
judgement(c);
if(!size)
printf("无!");
printf("\n");
menu();
return 0;
}
四、调试截图
1.judgement()函数无法输出小括号
发现是代码中确实运算符的优先级判断,修改之后的代码为:
运行截图:
五、测试截图
主要函数截图:
display()函数:
运行截图:
judgement()函数:
运行截图:
六、运行截图
七、个人总结
有关设置计时器有了更清晰的认知,更深入了解了有关穷举法的使用,对于随机数函数rand(),需要自己设置随机数种子(seed),否则在调用时会自动设随机种子为1,然后每次运行程序所产生的随机数都是一样的,故需要利用srand()设好随机种子,此次代码中我用的是当前秒数作为随机种子。
这次作业还使用到了数据结构栈的操作,复习了半个多小时的有关操作以及这次的实际应用,让我对于入栈出栈的操作更加的熟悉。
SQL Server DATEPART() 函数 定义和用法DATEPART() 函数用于返回日期/时间的单独部分,比如年、月、日、小时、分钟等等。语法DATEPART(datepart,date)date 参数是合法的日期表达式。datepart 参数可以是下列的值: datepart缩写年yy, yyyy季度qq,
Spring Boot 之FilterRegistrationBean –支持web Filter 排序的使用Spring 提供了FilterRegistrationBean类,此类提供setOrder方法,可以为filter设置排序值,让spring在注册web filter之前排序后再依次注册。 写一个普通的filter:[java] view plain copy print?pac
LVS集群中的IP负载均衡技术章文嵩 ([email protected]) 2002 年 4 月本文在分析服务器集群实现虚拟网络服务的相关技术上,详细描述了LVS集群中实现的三种IP负载均衡技术(VS/NAT、VS/TUN和VS/DR)的工作原理,以及它们的优缺点。1.前言在 前面文章中,讲述了可伸缩网络服务的几种结构,它们都需要一个前端的负载调度器(或者多个进行主从备份)...
import torch.nn as nnimport torchclass VGG(nn.Module): def __init__(self, features, num_classes=1000, init_weights=False): super(VGG, self).__init__() self.features = features self.classifier = nn.Sequential( nn.D
Linux 操作系统Shell编程快速入门、shell函数,Shell编程综合案例(定时备份数据库)。
本篇文章介绍了组件自定义事件的原理以及使用的方法,在实际开发中,组件的自定义事件也是一个小技巧,能有效提高开发的效率
BDC在FICO模块是经常用到的,用于批量过账程序时使用的,但是稳定性不如使用BAPI的好,但是BDC可以有多种T-CODE进行过账,也有不同的模式,功能也不错,但是在写程序或者是出现问题的时候需要考虑下面几个问题:1、可以在程序加入BDC的模式选择,默认为N模式,但是可以选择A模式,方便调试。当然这个也可以debug进去之后进行改值。2、LOOP里面有call BDC的情况,在每一次ca...
关于 iwiw 是一种新的基于 nl80211 的用于无线设备的CLI配置实用程序。它支持最近已添加到内核所有新的驱动程序。采用无线扩展接口的旧工具iwconfig已被废弃,强烈建议切换到 iw 和 nl80211。像Linux内核的其余部分,iw 仍处于开发阶段。功能被随时添加。 iw 的唯一文档就是此页和“iw help”的输出。 请帮助扩大这个
数论四大定理之威尔逊定理数论四大定理之威尔逊定理 - 简书威尔逊定理及其证明 - clockwhite - 博客园数论四大定理之威尔逊定理_L__ear的博客-程序员秘密_威尔逊定理威尔逊定理威尔逊定理_Michael_Li的博客-程序员秘密_威尔逊定理威尔逊定理_jkchen's Haven-程序员秘密威尔逊定理 数论威尔逊定理 数论_初学者-程序员秘密_威尔逊定理如何用最简单明了的话语解释威尔逊定理吗?哪种证明威尔逊定理的方法最简单?如何用最简
在我们的F盘里面有一个文件把这些原有的文件全部替换一下即可,之前我们数据库里面写一个User.java代码块,今天我们要改为动态的,所以要更换。1.把我们不要的先删掉了,这些是当时为了搭建项目,被选中的可以删掉了,还要其他被选中的,目前我们只做了登录和主界面。在我们的login.js里面把我们的login.jsp里面的script里面的方法给复制过去。还有我们的main.js里面把我们的mian.jsp里面的script里面的方法给复制过去。现在我们把它变为活的UserAction.java代码块。....
1.引入 <properties> <dubbo-spring-boot-starter.version>2.7.5</dubbo-spring-boot-starter.version> <dubbo-registry-nacos.version>2.7.5</dubbo-registry-nacos.version> </properties> <dependencies&g
torch.randn(*sizes, out=None)→ Tensor功能:从标准正态分布(均值为0,方差为1)中抽取的一组随机数。返回一个张量sizes (int…) - 整数序列,定义输出张量的形状out (Tensor, optinal) - 结果张量eg:random = torch.randn(2, 3)out: 0.5419 0.1594 -0.0413...