第一篇:《24点游戏》的优秀教学设计
教学目标:
1、理解24点游戏的规则,掌握24点游戏的运算技巧
2、操作实践算24点的扑克游戏,巩固加强有理数的四则运算
3、寓教于乐,培养合作精神和创新意识,激发学生对数学学习的兴趣 教学重点:游戏规则
教学难点:
计算的方法,特别是四张牌的计算的多样化
教学用具:
课件、扑克牌
教学过程:
一、创设情境,激发兴趣
师:(出示扑克牌)这是什么?你们玩过扑克牌吗?都用扑克牌玩过哪些游戏?今天老师也想用扑克牌和你们一起玩个游戏,叫做“算24点”。下面来了解一下它的游戏规则。
二、熟悉游戏规则,掌握计算方法
(一)第一关:幸运对对碰(2个数算24点)
课件出示:本关规则:老师出一张牌,你们也出一张牌或说一个数学,使这两个数字碰出的得数是24,这就叫“幸运对对碰”。
1、老师出一张牌8,你能从自己手中拿出一张牌,用加、减、乘、除法和我这张牌进行计算,算出24吗?
2、不错,是3,3×8=24.你是怎样想到3的?(口诀:三八二十四)
3、教师依次出牌4、9.让学生从自己手里拿出一张牌,进行对对碰。提问:9和谁怎样算24?(15加9等于24)
师:对,没有口诀是几九二十四,这时候我们就不能再用乘法,而是改用加法或减法。
(二)第二关:幸运拆拆猜(3个数算24点)
课件出示:本关规则:算24点时,将A看做“1”,从A—9这9张牌中任意抽出3张,经过加、减、乘、除的计算后得到24。所抽每张牌上的数都要用,而且只能用一次。
师:现在给你三张牌,你们能把牌上的数字加减乘除,算出结果24吗?
1、出示7 6 3,提示学生:见到6,想4。7和3这两张牌怎样算,能够得到4?
2、学生交流、汇报:7-3=4,4×6=24。教师板书。
现在我们三个小组来个比赛,每组推选1名代表来闯关,看看哪组表现得最棒!提示:如果有困难,你可以使用2条求助热线:(1)求助本组的其他同学;(2)求助全班同学。
课件出示三个小动物,每个动物后面都有一组数,学生选自己喜欢的动物。
出示三组数①2、3、4 ②9、8、3 ③3、5、9让学生边算边寻找算24的秘诀。
师:哪一组先来?(一个一个上去,不要三个一起上去)你选择哪个动物?(课件出示)。
注意提醒全班学生:注意了,他在算的时候,我们也要动脑筋算哦,如果他算不出来,有可能会求助你哦!
(算不出来时可以提醒:你可以使用求助热线的)
(注意每组的方式方法,表扬,反馈让大家去评点)如:对不对啊?真聪明!
下面哪一组来?(选择,算)真了不起,掌声送给他!
师过渡:刚才这三位同学都很棒,!
师:你们的计算的方法多种多样,你们发现什么诀窍没有?(多数可以凑3和8,4和6,应用口诀进行计算,不能应用口诀的再想办法进行加、减、乘、除混合算。)
(三)第三关:幸运大比拼
方法掌握了吗?那好,下面我们来个幸运大比拼。
(听好游戏规则,课件)这次我们三人小组合作,每人从自己的9张牌中任意抽出一张牌,把它放在桌上,然后每人思考,谁先想好就由谁先说,如果这三张牌算不出来,请组长把这三个数字记录下来,待会儿我们大家一起讨论。然后把各自的牌收回去,洗洗牌,再继续出牌玩。看看哪个小组成功算出的速度快,方法多!
学生活动,教师巡视指导。
交流算法,提供算不出来的情况,其他组帮忙计算。
(四)第四关:终极大挑战
课件出示:本关规则:同组同学选出四张牌,谁先算出最后结果是24,谁就胜出。如果计算结果得不到24,就换牌再算。
师:三张牌算24点我们已经会玩了,你们敢不敢挑战更高难度的?
生:敢!
课件出示1、2、5、8(课件出示四张牌)哇!四张牌呢,可难多了,你们怕不怕? 生试着算,说不同的答案。
师小结:用四张牌算24点的确难度大了些,但我们小朋友都很聪明,爱动脑筋,表现的特别棒!
开动脑筋想一想,会做哪个就做哪个!
出示三组:4 5 7 8 3 1 7 95 5 6
3三、全课总结
同学们,今天我们学习了什么?用什么玩的?
回家可以告诉你的爸爸妈妈,牌不仅可以作为娱乐休闲之用,还可以玩数学游戏呢!
你还可以和你的爸爸、妈妈一起玩一玩,跟他们比一比,好吗?
第二篇:点彩游戏公开课教学设计
一、案例主题:
在学生成长的过程中,各种各样的色彩是最能打动他们心扉的。可以说,色彩也是最能够引起他们兴趣的美术语言之一。本课以真实性、朴实性和学科性为指导思想进行教学设计。由于点彩画的知识特别丰富,在一节课里要面面俱到是不可能的。因此,我根据教学目标、教学的重点、难点以及学生的实际情况进行了本课的设计。力求做到课件少而精,不摆花架子,让学生学得扎实。
二、案例背景:
点彩是新印象主义以色彩分割原理为依据所采用的一种绘画表现形式,又被称为“点彩法”。其主要是利用不同的纯色点和块并列在一起形成的画面。课本中展示了法国新印象主义画家保罗·西涅克的作品《纳蒂布港》和修拉的《大碗岛星期天的下午》,目的是让学生了解点彩画的主要特征,提高研究点彩画的兴趣。而且通过学习了解简单的点彩画,让学生初步接触点彩,知道点彩的特点及简单技巧。教材中还列举了不同种类的色点的效果,提示学生可以根据表现内容的需要运用不同的色点来表现色调,丰富学生的表现力。三、三维目标:
1.知识与技能:学生初步接触点彩画,知道点彩的绘画特点及简单技巧,并用点彩法创作一幅画。
2.过程与方法:通过思考、比较、欣赏与讨论,使学生感知点彩画的画面效果,了解点彩画的原理。
3.情感态度与价值观:通过学习活动,引导学生富有创意地学习运用各种绘画手段,丰富学生的想象力,激发其对美好事物的表现以及创造的欲望。
四、教学重点难点:
教学重点:充分利用色彩和不同的点法创作一幅点彩画。
教学难点:能够使用点彩的方法创作相对完整的作品,丰富表现手段。
五、课前准备
教师:课件、水彩笔、油画棒、水粉颜料等。
学生:水彩笔、油画棒、水粉颜料、铅笔、棉签等工具。
六、教学过程:
(一)直接导入
出示课件,讲述今天这节课我们要进行一次点彩游戏,激发学生的学习兴趣。然后讲述这次游戏分成四关,要通过每一关才能算是取得胜利。
(二)进行游戏
通过游戏的方式将教学内容层层深入,每一关都设置一个小的教学目标:
第一关,比眼力。
通过观察发现点彩画跟我们以往的作品有什么不同?同时插入对点彩派的简介。(教学目标:发现点彩的与众不同之处)
第二关,比脑力。通过观察老师事先准备好的三幅不同工具点出来的作品,猜一猜他们是用什么工具点的?除了这些工具还有那些工具我们可以用来进行点彩?(教学目标:点彩使用的工具有很多种)
第三关,模仿力。出示几张用不同点点的苹果,让学生观察点与点的区别,同时选择一种工具学者用点的方式做一个苹果。(教师示范,学生第一次进行练习)第四关,创作力。了解点彩可以使用的工具,以及点彩的方法,学着用点彩的方式创作一幅点彩画。提出作业具体要求,进行第二次作业。
师:第四关,也是我们的最后一关,这一关要考察的是同学们的创造力。在这里老师要具体讲解一下这一关的游戏规则。游戏规则(作业要求):ppt7
1、选择任一种点彩工具进行点彩游戏(如:水彩笔、油画棒、水粉颜料等等)
2、先用深颜色点出图案的边缘或者是勾画出边缘,然后用点的方式给事先准备好的图案进行填色。
3、背景可以留白,时间充足的同学可以用点彩的方式对背景进行装饰。师:最后一关了,希望同学们加油,争取闯关成功。
(学生进行作业练习…….)
(作业点评)
闯关成功,胜利就在眼前… …
师:经过重重难关,我们终于来到了终点,让我一起来欣赏点彩给我们的生活带来的精彩。看一看,点彩在我们生活中的应用。Ppt8
师:这次游戏就到此结束了,希望同学们通过这次游戏,能将我们的点彩与电脑绘画结合在一起,利用电脑绘画中的喷枪工具、基本图形等等来创作一幅电脑绘画作品。
(结束)
第三篇:VB24点游戏设计
VB24点游戏设计(送论文查重报告)24点纸牌简介
任意给的四张扑克牌(不包括大小王),只能够用加、减、乘、除以及适当的括号连接着四张牌使得结果为24,或者宣布根本就是无解的。需要注意的是,每张牌必须且运算一次;J、Q、K可设置为11、12、13。
使用本程序其实很简单,按[Start]后,程序会任意给出四张牌,在左边的按钮中也能看到相应的数值,只要输入相应的表达式就可以了。如:6、5、4、1这四个数,输入表达式为:6/(5/4-1)即可;如果你认为本题无解,那么你不必输入任何数值直接按回车就可以,程序会验算答题是否准确。如果输入的数据有错,那么程序会自动定位到出错的地方,以方便用户修改。
本程序还有一个Test功能,用于自定义出牌值。即:可以自己任意给出四个(1-13)的整数,按[OK]键后由程序自动算出答案。
摘要:随着软件技术以及互联网技术的不断发展,游戏产业发展迅速,已经成为经济增民的一个亮点。实践是软件开发的核心,对代码要求精益求精,在开发的过程中,简单设计,用测试驱动,通过重构和迭代代码实现现设计。
本文简要的介绍了游戏的开发现状,以及游戏开发中存在的问题。另外还简单地介绍了众多游戏开发软件中的一种——即Visual Basic,其中主要地介绍了Visual Basic 6.0,以及Visual Basic的编程环境。同时通过两个小游戏简单介绍了利用Visual Basic 6.0开发游戏的处理过程。在本文中主要介绍了24点纸牌和拼拼图游戏的开发,包括界面的设计和相应的界面设计原则,还介绍了其开发环境。同时也也对游戏系统的公共功能模块做了阐述。
通过对该课题的研究设计,对如何运用Visual Basic来设计游戏有了一定程度的了解,并对如何设计游戏的构架有所掌握。
关键词:游戏设计;Visual Basic技术;界面设计;模块;算法 目 录
第一章 游戏开发的现状分析 1 1.1游戏开发现状 1
1.2 游戏开发中存在的问题 2 第二章 游戏开发的技术基础 3 2.1 Visual Basic技术 3
2.1.1游戏开发软件的介绍 3 2.1.2 Visual Basic概述 3
2.2 Visual Basic的编程环境 4
2.2.1 Windows下的Visual Basic编程环境 4 2.2.2 面向对象的编程 4 2.2.3 VB在系统中的应用 6 2.3 小结 9
第三章 系统总体规划 10 3.1 系统功能简介 10 3.1.1 24点纸牌简介 10 3.1.2 拼拼图简介 10 3.2 系统开发方法 11 3.2.1 24点纸牌的开发 12 3.2.2 拼拼图的开发 21 3.3 系统开发环境 25 3.3.1 开发平台 25 3.3.2 运行平台 25 3.3.3 输入输出设计 25 3.4 小结 26
第四章 系统功能模块设计 27 4.1 24点纸牌游戏公共模块 27 4.2 拼拼图公共模块 29 4.3 小结 30
第五章 总结与展望 30 5.1 全文总结 30 5.2 展望 31 参考文献 31 致 谢 33 以下是部分界面图,如图片不清,请直接点击图片,如需要看更详细的资料,请直接联系客服!
图1
图2 参考文献:
[1] 柴继贵.基于VB考勤管理系统[J].首都师范大学学报.2009(10), P40-40 [2] 尚俊杰.VB高校学生综合素质评价系统[J].东北师大学报.2009(4), P39-43 [3] 赵志升.基于VB人才信息管理系统[J].重庆大学出版社.2011(2), P37-42 [4] 王刚.基于VB网上作业批改系统[J].安徽大学出版社.2009(9), P29-30 [5] Fangzhen Lin,Li Yan Yuan,Mingyi Zhang.基于VB校园聊天室的设计与实现[J].贵州民族出版社.2011(7), P28-43 [6] 李国禄.基于VB医院病房管理系统[J].吉林大学社会科学学报.2009(4), P26-35 [7] 姜永玲.VB糖尿病专家系统[J].福州大学学报.2010(7), P27-37 [8] 刘宏兵.基于VBVF人事档案管理系统/VF企业员工管理系统[J].国防科技大学出版社.2009(9), P42-42 [9] 戴汉良.眼镜店销售管理系统[J].南京大学学报.2008(8), P40-41 [10] 张超.基于VB员工管理系统[J].中国农业大学学报.2009(8), P28-36 [11] 王承明.基于VB排课管理系统[J].北京工商大学学报.2011(7), P31-38 [12] 杨玚.基于VB机房作业管理系统[J].吉林大学.2010(1), P33-37 [13] 谭新良.基于VB网上购物系统[J].重庆出版社.2007(10), P23-30 [14] 方捷.基于VB客户关系管理系统[J].计算机工程与应用.2011(11), P40-42 [15] 何苏.基于VB贴吧的设计与实现[J].中国信息界.2007(11), P30-38 [16] 赵艳平.基于VB打砖块游戏[J].国防工业出版社.2007(2), P37-39 [17] 任昌荣.基于VB房产信息管理系统[J].人民邮电出版社.2011(2), P34-37 [18] 吕俊瑞.高校学生成绩管理系统的设计与实现[J].科技信息.2009(10), P35-40 [19] 徐生诚.基于VB学校工资管理系统[J].北京师范大学学报.2011(11), P34-40 [20] 王娴.基于VB多功能点歌系统/VOD视频点播系统[J].中国水利水电出版社.2011(9), P27-33 [21] 张晨光.基于VB自动报警系统的设计与实现[J].湖南师范大学社会科学学报.2007(8), P37-39 [22] 刘芳.基于VB基于web的教材管理系统[J].电子工业出版社.2011(7), P40-40 [23] 周东华.VB[J] LAN语音视频通信系统[J].高等工程教育研究.2011(9), P28-30 [24] 白兆庆.基于VB和SQL2005的学生考勤管理系统[J].广东教育出版社.2007(5), P24-25 [25] 廖仁全.基于VB人才管理系统[J].中国特殊教育.2011(9), P32-39 [26] 郝鹏.基于VB上机计时管理系统[J].南京师大学报.2008(4), P39-40 [27] 韩露.基于VB(C#)考证信息管理系统的设计与实现[J].福建科学技术出版社.2009(4), P37-39 [28] 栾晓春.基于VB客户管理系统[J].北京理工大学出版社.2011(11), P24-40 [29] 崔巍.智能排课系统[J].高等教育出版社.2010(10), P39-42 [30] 蒋华林.VB简单图片转化工具[J].中国大学教学.2011(4), P33-41 [31] 肖磊.人力资源管理系统[J].华南理工大学出版社.2010(8), P26-28 [32] 张志鑫.基于VB售楼管理系统[J].上海师范大学学报.2008(8), P28-37 [33] 周登杰.基于VB酒店预定系统[J].学位与研究生教育.2011(9), P29-38 [34] 林和.基于VB网上商城[J].华东师范大学学报.2007(9), P28-28 [35] 李晓亮.基于VB学校机房计费管理系统[J].中国法制出版社.2007(9), P25-37 [36] 谈静.基于VB学生交费管理系统[J].福建教育出版社.2009(4), P41-42 [37] 周新明.基于VB网址导航网站[J].清华大学出版社.2011(9), P30-37 [38] Krzysztof Dębicki.Towards an electronic independent learning enviro.Personal and Ubiquitous Computing.2009(4), P23-26 [39] Andreas Lommatzsch.Weight constraint programs with evaluable functio.Education and Information Technologies.2011(5), P23-33 [40] Sahin Albayrak.A comparison of discrete and continuous neural Net.Annals of Mathematics and Artificial Intelligence.2010(8), P32-43 [41] N.Gulzar, K.Ganeshan.Interval scripts: a programming paradigm for inte.Automated Software Engineering.2010(11), P37-41 [42] G.Zémor.Formal Specifications of User Requirements[J].Mathematische Zeitschrift.2009(8), P39-39 [43] Andrea Omicini.Environment as a first class abstraction in multi.Designs, Codes and Cryptography.2011(6), P24-35
第四篇:c++24点游戏
c++24点游戏
#include “iostream” #include “string” using namespace std;
//定义Stack类
const maxsize=20;
enum Error_code { success, overflow, underflow };
template
bool empty()const;bool full()const;int size()const;void clear();
Error_code top(T &item)const;Error_code pop();
Error_code push(const T &item);private: int count;T entry[maxsize];};
template
template
bool Stack
template
bool Stack
template
template
template
Error_code Stack
template
Error_code Stack
template
Error_code Stack
Stack
int set;
// 判断程序中的异常,以便适时退出?//
void process(char c)
//计算两个数的 +-* / 运算// { int k=0;double a,b;sign.pop();
if(num.top(b)==success){
num.pop();
if(num.top(a)==success){ num.pop();k=1;} } if(k){ switch(c){
case '+': num.push(a+b);break;case '-': num.push(a-b);break;case '*': num.push(a*b);break;case '/': if(b==0){ set=4;num.push(-1);} else
num.push(a/b);break;} }
else {set=1;num.push(-1);} }
void get_command(string &str){
cout<<“n请输入要进行运算的表达式,包括” +,-,*,/,=,(,)“和数字,”< <<“注意: 以数字开头,等号结尾,中间括号要匹配.”< double do_command(const string &str){ string s=“"; double outcome=-1;char c; for(int i=0;str[i]!=' ';i++){ if(set!=0)break;//例外 则停止运行 while(1){ //分离数据与运算符 if(str[i]<='9' && str[i]>='0' || str[i]=='.'){ s+=str[i];i++;} else { if(s!=”“){ if(num.push(atof(s.c_str()))==overflow)set=3;s=”“;} break;} } char ch= str[i]; switch(ch){ //处理运算的优先级,并注意例外抛出 case '*': case '/': if(sign.top(c)==success)if(c=='*'||c=='/')process(c);if(sign.push(ch)==overflow)set=3;break;case '+': case '-': while(sign.top(c)==success){ if(c!='(')process(c);else break;} if(sign.push(ch)==overflow)set=3;break;case '(': if(sign.push(ch)==overflow)set=3;break;case ')': while(sign.top(c)==success){ if(c!='(')process(c);else break;} sign.pop();break;case '=': while(sign.top(c)==success){ if(c!='(')process(c);else break;} break; default: set=2;break;} } if(num.size()==1 && sign.size()==0)num.top(outcome);else set=1; if(set==0)cout<<”运算结果是:n“< if(set==1)cout<<”n您输入的不匹配,有错误发生。Result lost!“< if(set==4)cout<<”n 分母为0,不能进行除法运算,出现溢出,Lost result!“< return outcome;} void main()int f(){ double out;do { string str,s;set=0; get_command(str);s=str; if(str[0]=='-')str='0'+str;//处理表达式中的负号 for(int i=1;str[i]!=' ';i++){ if(str[i]=='-' && str[i-1]=='('){ str.insert(i,”0“);i++;} } out= do_command(str); cout< 我gai过此行 cout<<”如果你算的结果不等于24,需要重新计算请输入你算出的结果,程序有漏洞,请合作。“< return out;} int main(void) { int ii,zz,jj; printf(”0-12的4个数字nn“); for(jj=0;jj<2;) { for(ii=0;ii<4;ii++) { zz=rand()()% 12; cout< } cout<<”请用这4个数字算出24“< f(); cout<<”是否继续;是1否2"< cin>>jj; cout< } 第3章 “速算24”扑克游戏--单元、异常、逻辑 3.1 “速算24”扑克游戏效果说明 “速算24”是一个考察心算能力、有助于开发智力的扑克游戏。在给出4张扑克牌之后,要求应用这些扑克牌数字做数学运算,迅速构造出一个数学表达式,得出结果24。这个游戏的关键在于迅速判断用户输入的表达式是否正确,并做出相应的反馈,告诉用户是算对了还是算错了。游戏的初始界面如图3.1所示。 图3.1 游戏的初始界面 当用户单击“开始”按钮时,系统开始发牌,随机发出4张牌,如图3.2所示为随机开始的一局游戏,给出的4张纸牌分别为“9”,“8”,“9”,“2”。在文本框中输入运算表达式,比如,输入“8*(2+(9-9))”,单击“计算”按钮,系统会出现提示框,显示“您输入的表达式的计算结果为16!”,告诉你该表达式的结果不是“24”,如图3.3所示。单击“确定”按钮,再次在文本框中输入表达式,比如“8*(2+(9/9))”,单击“计算”按钮,系统会出现提示框,显示“您真行,我服了您!”,表明运算正确,如图3.4所示。 图3.2 系统随机发4张纸牌 图3.3 运算式不正确 图3.4 运算式正确 这个游戏具体的规则如下: (1)单击“开始”按钮,游戏开始,系统将随机发牌。 (2)请迅速在文本框中输入运算表达式,然后单击“计算”按钮。 (3)这时系统会提示您的运算是对了还是错了,在弹出的对话框中单击“OK”按钮,再次输入新的运算表达式,重复上一步,直到您的运算表达式结果正确,这时系统会恭喜您! (4)如果结果错了还想继续或者中途想计算另一局扑克牌,就单击“重新开始”按钮,得到新一局扑克牌进行游戏。 下面,我们开始循序渐进地创建这个小游戏。在最开始,游戏的界面和效果都会非常简单,在后面我们会逐渐地完善它。 第3章 “速算24”扑克游戏--单元、异常、逻辑 3.2 生成和建立程序(1)在程序中用到了Image组件,用于放置图片。还用到了Timer组件,用于计算用户操作时间。下面我们来生成游戏的基本框架。 3.2.1 Image组件 Image组件在Additional页上,用来在窗口中显示一幅图片。它拥有如下几个主要属性: 1.Picture属性 可以在picture属性中调入图像文件。Delphi支持多种图像格式,如位图(.BMP)、图标(.ICO)、图元(.WFM)、动画光标(.ANI)、JPEG图片(.JPG、.JPEG)等。 2.AutoSize属性 当AutoSize为True时,Image组件将根据它所包含的图像的大小来调整自身的大小;当AutoSize为False时,不论图像有多大,组件将保持设计时的大小。如果组件比图像小,那么只有一部分图像是可见的。 3.Stretch属性 当Stretch为True时,位图图像将根据组件的大小调整自身的大小,当组件大小改变时,上述三种文件也做相应变化。Stretch属性对图标没有作用。 上述的AutoSize和Stretch属性决定了图像在窗口中的显示尺寸。 图3.5演示的3个Image分别为:AutoSize为True,AutoSize为False,Stretch为True的情形。可以看到,Image的原始尺寸比图片宽,矮,在上面的属性设置下,就会有不同的显示效果。 图3.5 AutoSize和Stretch的设置 3.2.2 Timer组件 在Delphi中,组件分可视组件和非可视组件。可视组件是指那些在运行期间仍然能显示的组件,例如Label,Button,Image组件等。非可视组件是指那些在程序界面设计期间可见,而在程序运行时不可见的组件,例如在System页上的Timer组件。 Timer组件能够有规律地触发OnTimer事件,发送信息给应用程序,它是编制应用程序时最为重要的组件之一。 1.Timer组件的属性 Enabled属性表示Timer是打开还是关闭。用Interval属性设置两个OnTimer事件间的间隔,单位是毫秒。将间隔设置为0相当于关闭计时器,Interval是Cardinal类型的,最大值可到4294967295,当然程序中一般不会把Interval设成很大的值。2.Timer组件的使用 Timer是独立的对象,在启动与Windows无关的逻辑和应用事件时极其有用。可以模拟时钟或计时器,可视地显示经过的时间;可以用作系统延时,Delphi提示信息出现只需在该区域停顿几秒,就是Timer组件应用的一个例子;可以检查系统环境、事件,根据结果进行响应;也可以在窗口中闪烁一段正文或图像,提示某种操作或处理正在进行等等。 尽管Delphi的计时器每秒可以产生1000次激发,在编程中还必须注意程序对Timer触发的响应。如果程序处理OnTimer事件的时间超过Interval的设定值,就可能错过事件,因为当下一次触发到来时,系统正忙于处理上一事件,则这次触发就会被忽略。同时要注意其他的Windows应用程序是否会影响Timer的触发。如果后台正运行着一个占用处理器的程序,就可能会导致Timer的触发不准确,从而使前台程序运行出现错误。 这里要强调的是Timer组件是一个非可视组件,可以把它放置到窗体或者其他容器组件上的任何位置。3.实现游戏计时功能 在本章的游戏中,我们加入一个Timer组件,实现游戏的计时功能。 在窗体中加入一个Label组件,将此组件的Caption属性设置为“使用时间”,然后从组件面板上选择System页中的Timer组件。 在Unit1中加入Form1的一个私有成员SpendTime,记录用户计算所用的时间。代码如下所示: private { Private declarations } SpendTime:Integer;在Form1的onCreate事件中加入如下代码。将SpendTime设置为0,并将Timer1的Enabled属性设置为False,使Timer1组件不能响应OnTimer事件;并将Timer1的Interval属性设置为1000,表示当Timer1有效时,每间隔1000ms(即1秒)发生一次OnTimer事件: procedure TForm1.FormCreate(Sender: TObject);var i:integer;begin //初始化,设置数组RandomData的长度为4 //并将每个数组元素初始化为零 setLength(RandomData,4);for i := 0 to 3 do RandomData[i]:=0;SpendTime:=0;Timer1.Enabled:=False;Timer1.Interval:=1000;end;然后在标题为“开始”的“开始”按钮的OnClick事件中,加入如下所示的代码,将Timer1的Enabled属性设置为True,使Timer1组件有效,即现在Timer1能响应OnTimer事件,计时开始。并将SpendTime重新设置为0: Timer1.Enabled:=True;Timer1.Interval:=1000;SpendTime:=0;//将SpendTime重新设为0 再在“计算”按钮的OnClick事件句柄中,增加下面的语句,使Timer1无效: Timer1.Enabled:=False;最后双击Timer1组件,创建Timer1的OnTimer事件句柄,在其中加入如下所示的代码,将SpendTime加1,并设置Label5的Caption属性: procedure TForm1.Timer1Timer(Sender: TObject);begin SpendTime:=SpendTime+1;Label5.Caption:='使用时间:'+IntToStr(SpendTime)+'秒';end;这样,每隔1秒钟,程序就刷新一次使用时间。 3.2.3 设计初始界面 按住Shift键,然后单击组件面板中Additional页中的Image组件,这时该组件边缘出现蓝色的边框,并且凹陷下去,表示可以在窗体上连续加入几个Image组件。选择好Image组件后,在窗体的左上角单击,加入1个Image组件,然后依次向右单击鼠标3次,再加入3个Image组件。最后再单击组件面板中最左边的箭头。 为了排列这4个Image组件,先利用Shift键将它们同时选上,然后右击,选择Align命令,在随后出现的Alignment对话框中的Horizontal选项组中选择Space equally,在Vertical选项组中选择Tops,表示这4个组件顶端对齐,水平方向上间距相等。 按照同样的方法加入4个Label组件、3个Button组件和1个Edit组件。按照表3.1所示设置各个组件的属性。 表3.1 各个组件的属性 组件名 Form1 Label1 属性名 Caption Caption AutoSize WordWrap Caption 属性值 速算24 1.单击“开始”按钮,游戏开始,系统将发出4张扑克牌 False False 2.要求用户利用扑克牌显示的数字,通过加减乘除运算,以最快的速度得出24(可以使用括号),JQKA和“王”算做1。然后在文本框中写好表达式,接 着单击“计算”按钮 Label2 Label3 AutoSize WordWrap Caption False True 3.这时系统会计算输入表达式的结果,告诉用户是对还是错了。在弹出的对话框中单击“OK”按钮,如果错了可以再次输入新的表达式,重复上一步。直 到您的表达式正确,这时系统会恭喜算对了! Label4 AutoSize WordWrap Caption AutoSize Caption Caption Caption Text False True 在下面输入数学表达式 False 开始 计算 退出游戏 空 Button1 Button2 Button3 Edit1 现在同时选择Label1,Label2和Label3,将它们左对齐,垂直方向等距离排列。将Button1,Button2和Button3左对齐,垂直方向等距离排列。 下面放置4个Image组件,用于放置4张纸牌的图片。 先选择Image1,然后切换到对象查看器中的属性编辑器,选择属性选项页中的Picture属性,然后在Picture属性值栏中双击,或单击此属性值旁边的带有省略号的按钮,打开Picture Editor对话框,如图3.6所示。然后单击Load按钮,弹出Load Picture对话框,在此对话框中选择background.bmp文件。最后单击OK按钮,退出Picture Editor对话框。 图3.6 指定图片 使用同样的方法,设定其他3个Image组件的Picture属性。 保存我们的新项目,运行之后界面如图3.7所示,与运行时的界面图3.1稍有不同。这里是设计时界面,只有界面没有事件响应。是程序创建过程中的一个步骤的检验。但是,这个程序还没有什么具体的功能,为了让游戏运行起来,必须添加代码,创建相应的事件处理程序。 第3章 “速算24”扑克游戏--单元、异常、逻辑 生成和建立程序 3.2.4 事件处理 需要添加个事件:第一个用于响应单击开始按钮,在此事件中完成发牌,即随机显示图片;第二个用于响应单击计算按钮,解析用户在文本框中输入的表达式,计算表达式的结果,并判断表达式的结果是否等于;第三个用于响应单击退出游戏按钮,退出游戏(程 序)。 1.数据初始化 创建窗体的事件处理程序,在这里进行必要的初始化。第一步先在Unit1中添加Form1的私有成员数组: private { Private declarations } RandomData:array of Integer;然后,在对象查看器中选中Form1,选中Event选项卡,在OnCreate一栏对应的右边的空白栏中双击,创建OnCreate函数。添加如下代码。 procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin //初始化,设置数组RandomData的长度为4 //并将每个数组元素初始化为零 setLength(RandomData,4); for i := 0 to 3 do RandomData[i]:=0; end;这里使用一个for循环语句,i是循环变量,格式是:for循环变量:=初值to末值do循环体。你也可以借助Delphi的自动完成功能,在输入for之后按下Ctrl+J键,生成如下代码: procedure TForm1.FormCreate(Sender: TObject); begin for := to do begin end; end;在上述代码中,程序首先利用setLength函数设定可变数组RandomData的数组长度为4,然后,将数组的每一个单元都设置为0。这样,就完成了数组的数据初始化工作。 2.“开始”按钮的Click事件处理 ()功能单击开始按钮时,系统就随机地发出张纸牌,显示在个组件中。 ()代码首先,我们需要一个循环变量,一个字符串变量存放随机选取的图片的文件名。创建“开始”按钮的OnClick事件处理程序,在begin前头添加需要的变量,然后在此事件 中加入如下所示的代码。 procedure TForm1.Button1Click(Sender: TObject); var i:integer; filename:String; begin Randomize;//初始化随机数 for i := 0 to 3 do begin RandomData[i]:=Random(13)+1;//产生一个1到13的随机数 filename:=IntToStr(RandomData[i])+'.bmp';//根据随机数,得到文件名 //根据i的不同为不同的Image组件载入图像文件 case i of 0 : Image1.Picture.LoadFromFile(filename);1 : Image2.Picture.LoadFromFile(filename);2 : Image3.Picture.LoadFromFile(filename);3 : Image4.Picture.LoadFromFile(filename); end; edit1.Text:=''; edit1.SetFocus; end; end;在Delphi内部,随机数的产生实际上也是在一套算法的控制之下,Randomize函数用于初始化产生随机数的种子,保证两次产生的随机数不同,而Random(i:integer)则利用初始化过后的随机数种子产生一个1~i之间的随机数。这里i设定为13,以配合扑克牌的张数13。 用来将一个整数转换成一个字符串,和上一章中的的功能恰好相反。我们已经预先准备了位图文件,它们都是形式,文件名则是利用数字命名。中特殊的字符串运算符将两个字符串串联起来,产生一个新的字符串,我们需要的位图文件后缀是,因此,在产生文件名的时候,在数字后面加上这个字符串。语句在上一章中已经讲过,单击开始按钮后,准备接受用户的输入,然后利用方法,把焦点设置到上。是提供的方法之一,用于设置输入 焦点到某个指定的组件。 3.“计算”按钮的OnClick事件 双击“计算”按钮,创建此组件的OnClick事件响应句柄,然后在代码编辑器中加入如下所 示的代码,用于计算用户输入的表达式。 procedure TForm1.Button2Click(Sender: TObject); var result:integer; answer:String; begin result:=TotalCompute(Edit1.Text); if(result=24)then Application.MessageBox('您真行,我服了您!','对了',MB_OK) else begin answer:='您输入的表达式的计算结果为'+IntToStr(Result)+'!';Application.MessageBox(PChar(answer),'错了',MB_OK); end; end;这段程序根据自定义函数的计算结果判断用户的输入正确与否,并且输出相应的结果以提示 用户。 在语句“result:=TotalCompute(Edit1.Text)”中用到了一个自定义的函数TotalComp-ute,我们用它来计算用户输入的表达式。现在我们还没编写这个函数的代码,所以,目前这段代码是无法运行的。没关系,可以先把它用“//”注释掉,然后随便给 result赋一个值,测试这个事件处理程序的其他部分是否运行正常,例如: //result:=TotalCompute(Edit1.Text); result:=24;这样,运行后,单击“计算”按钮后的显示如图3.8所示。 图3.8 成功的提示信息 我们用一个类型的变量存放出错信息,但是函数的第一个参数要求是(字符指针)类型,因此,我们用一个强制类型转换将转换 成。4.“退出游戏”按钮的OnClick事件 双击“退出游戏”按钮,创建此组件的OnClick事件处理程序,然后在代码编辑器中加入如 下所示的代码,用于退出程序。 procedure TForm1.Button3Click(Sender: TObject); begin Close; end;在上一章中我们提到可以用代替,但这里使用来结束程序的运行。这样,可以通过事件来指定在什么条件下窗体可以关闭。 第3章 “速算24”扑克游戏--单元、异常、逻辑 生成和建立程序5.OnCloseQuery事件 当调用方法来关闭窗体时,事件发生。利用事件来指定在什么条件下窗体可以关闭。事件包含一布尔型的参量,可以用它来决定窗体是否关闭。的默认值为。可以利用事件来询问用户是否真的希望马上关闭窗体。我们在这里弹出一个对话框,代码如下所示: procedure TForm1.FormCloseQuery(Sender: TObject;var CanClose: Boolean);begin if(MessageDlg('现在要退出游戏吗?', mtConfirmation, [mbOk, mbCancel], 0)= mrOk)then canClose:=True else canClose:=False;end;MessageDlg是一种提示对话框,第一个参数是对话框询问的讯息,是一个字符串;第二个参数则代表对话框的类型,mtConfirmation是一个TMsgDlgType的枚举类型,表示这个对话框是个确认对话框。TMsgDlgType类型如下所示: type TMsgDlgType =(mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);以上定义的对话框类型分别表示:警告、错误、提示、确认和自定义类型。 第三个参数是TMsgDlgBtn类型的集合,这个集合包含了类型为TMsgDlgBtn的按钮,TMsgDlgBtn的定义如下: type TMsgDlgBtn =(mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mnNoToAll, mbYesToAll, mbHelp);在我们的程序中,利用了一个集合[mbOK, mbCancle],表示在对话框中显示两个按钮:OK和Cancel的组合。 最后一个参数是用来描述帮助索引的长整型变量,用来获取提示用户的帮助信息,这里我们没有任何帮助信息,先不管它。函数和用户交互,返回一个类型的数字,预先定义了一套数字,用来直观地表示对话框返回信息。如果用户单击了按钮,这个对话框返回,效果如图所示。 图3.9 关闭窗口时询问用户 现在,我们已经完成了程序的主体部分。第3章 “速算24”扑克游戏--单元、异常、逻辑 单元间的互相引用3.3.1 单元引用的概念 在第章关于单元的知识里,我们已经知道可以定义不包含窗体的单元,它集中定义了程序中使用的函数,这一节里,我们就要实现这样的一个单元,用来实现上面提到的函数。我们可以在任何单元中编写自己的函数,当然包括与窗体相连的单元。可是我们常常需要用到一些常用的函数,这时最好是创建一个不与窗体相连的独立单元,用它来容纳自己的函数,这称为独立的单元文件。当创建了不与窗体相连的独立单元文件后,项目中的其他单元就能很容易地共享这些函数,其他项目也可以很容易地调用这些函数了。对于单元间的引用,要用到语句。3.3.2 uses语句 语句告诉程序在最终的执行代码中需要用到哪些函数和过程。会自动把一些必须的单元包括进来,例如,,等。对于我们自己编写的单元,如果程序中使用了该单元的函数或代码,也需要包括在部分中。语句具有两种类型:公有引用和私有引用。在部分包含的语句代表的是本单元的公有引用,就是说,这部分的引用可以被其他引用本单元的单元继承性地引用。在部分的语句应包含在部分中的代码所需要的单元,去掉那些可以自动加入到程序中的单元。在部分包含的语句代表的是本单元的私有引用,就是说,这部分的引用只能被本单元内部使用。在部分的语句应只包含在部分中的代码所需的单元的名字。对于单元间的引用,要避免交叉引用。假设有两个单元和,如果出现在的部分的语句中,那么单元便不能出现在单元的的语句中。因为这样会产生对单元的循环访问,编译时会出现错误信息。3.3.3 创建另一个单元 创建一个不与窗体相连的单元文件的方法是,首先选择主菜单的命令,然后选择命令,此时弹出一个对话框,如图所示。在此图中选择选项卡中的,然后单击按钮。此时自动为我们创建一个名为的独立单元文件,并显示在代码编辑器中,我们只需在此加入函数即可。 图3.10 New Items对话框 单元创建之后,就需要实现单元之间的互相引用。这里有两种方法:(1)直接在Unit1中写入uses Unit2,代码如下所示: var Form1: TForm1;implementation uses Unit2;(2)选择主菜单的File | Use Unit命令,此时Delphi弹出Use Unit对话框,如图3.11所示,在此窗口中列出当前文件没有连接的所有文件,只需选择需要连接的文件即可。当选择了某一文件并单击OK按钮后,当前文件就包含了对所选文件的引用。 图3.11 Use Unit对话框 如果当前文件已经连接了当前项目中所有其他文件,选择命令后,就会弹出如图所示的信息窗口,告诉程序员当前文件已经连接了当前项目中所有其他文件。 图3.12 Information对话框 此时再编译,程序就没有任何错误了。现在我们已经创建了,它将用作我们的数学函数定义单元。在开始定义这个单元之前,需要先了解一下关于的异常处理机制。第3章 “速算24”扑克游戏--单元、异常、逻辑 3.4 异 常 处 理 3.4.1 异常处理的概念 在应用程序开发中如何检测、处理程序的运行错误是一个很重要的问题。在 Delphi 的IDE(集成开发环境)中提供了一个完善的内置调试器,可以发现大部分程序错误。但并不是所有的错误都可以被发现,而且当程序涉及到与外设的数据交换或操作外设,如要求用户输入、读写磁盘等时,错误的发生是程序无法控制的,如输入非法字符、磁盘不能读写等。这些情况不仅会导致应用程序异常中止,而且可能引起系统的崩溃。针对这些问题,Delphi提供了一套强大的异常处理机制。巧妙地利用它,可以使程序更为强健,使用更为友好。 Delphi异常处理机制建立在Protected Blocks(保护块)的概念上。所谓保护块是指用保留字try和end封装的一段代码。保护块的作用是当应用程序发生错误时自动创建一个相应的Exception(“异常”类)。程序可以捕获并处理这个“异常”类,以确保程序的正常结束以及资源的释放和数据不受破坏。如果程序不进行处理,则系统会自动提供一个消息框。“异常”类是Delphi异常处理机制的核心,也是Delphi异常处理的主要特色。Delphi提供的所有“异常”类都是类Exception的子类。用户也可以从类Exception派生一个自定义的“异常”类。 3.4.2 资源保护方式 回收分配的资源是确保程序健壮性的一个关键。但默认情况下异常发生时程序会在出错点自动退出当前模块,因此需要一种特殊的机制来确保即使在异常发生的情况下,释放资源的语句仍能被执行,而Delphi的异常处理正提供了这种机制。 Delphi提供了一个保留字finally,用于实现资源的保护。 {分配资源} try {资源使用情况} finally {释放资源} end;try„finally„end就形成了一个资源保护块。finally后面的语句在任何情况下(不论程序是否发生异常)都会执行。 在异常保护的情况下,当异常发生时,系统会自动弹出一个消息框,在框中显示异常的消息。退出当前模块后异常类自动清除。 3.4.3 异常响应方式 异常响应为开发者提供了一个按需进行异常处理的机制。try„except„end形成了一个异常响应保护块。与finally不同的是:正常情况下except 后面的语句并不被执行,而当异常发生时程序自动跳到except处,进入异常响应处理模块。当异常被响应后异常类自动清除。 下面是异常响应方式的一般代码: try {程序正常功能} except on ESomething do {响应特定异常} else {提供默认响应} end;保留字on„do用于判断异常类型。必须注意的是:except后面的语句必须包含在某一个on„do模块中,而不能单独存在。这是又一个与finally不同的地方。 3.4.4 提供默认响应 在异常响应模块中,一般我们只对希望响应的特定异常进行处理。如果一个异常发生而响应模块并没有包含对它的处理代码,则退出当前响应模块,异常类仍被保留。 为了保证任何异常发生后都能在当前响应模块中被清除,可以定义默认响应: try {程序正常功能} except on ESomething do {响应特定异常} else {提供默认响应} end;由于else可以响应任何异常,包括我们一无所知的异常,因此在默认响应中最好只包括诸如显示一个消息框之类的处理,而不要改变程序的运行状态或数据。 第3章 “速算24”扑克游戏--单元、异常、逻辑 3.5 数学逻辑单元(1) 此游戏程序最关键的地方是如何将用户输入的字符串表达式解析成数学表达式。为了使程序结构清晰明了,我们将此解析代码和程序的主代码分开,单独编写成一个单元。 3.5.1 算法设计 游戏的难点是如何将一字符串形式的表达式解析成计算机能计算的算术表达式。例如对于字符串“3^(4*(9+4))”,如何让计算机解析、计算。 我们的想法是按照数学四则运算规则,先逐层进入最里层的括号,然后在括号内部计算乘方,接着进行乘(除)法运算,最后按顺序进行加(减)运算,当本层括号内部计算完成后,返回结果,去掉括号内部数据,退出到下一级括号(如果有)内进行计算。 这里面涉及的技术细节主要有下面几点: (1)层层剥离括号,然后从最里层的括号开始计算。(2)对于每一个运算符号,找到符号两侧的数字,形成一个计算式。 (3)每一个子计算式完成后,运算结果返回到原始数列中,作为子串的一部分,继续进行上述计算。 3.5.2 字符串的相关函数 在游戏中,用户输入的都是字符数据,我们需要从这些字符中分析得到数字和运算符号,因此要用到与字符串操作有关的函数。 function Pos(sub , all:string):integer;这个函数含有两个参数:sub表示要查找的字符,all表示原字符串。函数在字符串all中寻找指定的字符sub的位置,如果字符串中不存在sub字符,则函数结果为0。 function LastDelimiter(sub,all :string):integer 这个函数含有两个参数:sub表示要查找的字符,all表示原字符串。函数返回在字符串all中所有查找到的指定字符sub的最后一个的位置,如果字符串中不存在sub字符,则函数结果为0。 function Copy(allstring:string;first,length:integer):string 这个函数的3个参数的含义分别是:allstring代表原来的字符串,first表示拷贝开始的位置,length表示要拷贝的子串长度。函数返回拷贝成功的子串。 procedure Delete(str:string;ppos,length:integer)这个过程用于删除字符串中的一段字符。参数str代表将要操作的字符串,ppos代表开始删除的位置,length表示将要删除多少个字符。function Length(S): Integer;Length函数返回字符串S的长度。 function Trim(const S: string): string;overload;function Trim(const S: WideString): WideString;overload;Trim函数返回字符串S去掉前面和后面的空格后的字符串。 下面的例子给出一个综合利用字符串处理函数编写的一个处理特定字符串的函数,它的功能是:输入一个字符串后,可以返回字符串中两个单括号之间的子字符串,并去掉前面和后面带着的空格: function GetMyStr(const S: string): string;begin Result:=Trim(Copy(S,Pos('<',S)+1,Pos('>',S)-Pos('<',S)-1));end;比如我们在程序中写到GetMyStr(‘This is a test < Result to output > end of test’);,会得到字符串“Result to output”。 3.5.3 算法的代码编写 基于上述的考虑和知识基础,我们在声明部分定义下列几个主要函数: (1)AnyLastPos函数定位最后一个算术运算符的位置。 function AnyLastPos(Str:String):integer;(2)AnyFirstPos函数定位最先一个算术运算符的位置。 function AnyFirstPos(Str:String):integer;(3)AnyFirstF函数判断最先出现的符号是+号、-号、*号还是/号。 function AnyFirstF(Str:String):Char;(4)SubCompute函数用于计算不带()号的加、减、乘、除运算。 function SubCompute(Str:String):integer;(5)TotalCompute函数用于计算表达式的结果。 function TotalCompute(Str:String):integer;1.寻找最后一个算术运算符 定义4个整数变量SubPos,PluPos,MulPos,DivPos,在给定的字符串中寻找+,-,*,/的最后位置,将这些位置存储在上述的4个变量中,然后比较4个符号出现的位置,得到数值最大的运算符;在返回的结果中,返回这个运算符的位置。 程序代码如下所示: function AnyLastPos(Str:String):integer;var SubPos:integer;PluPos:integer;MulPos:integer;DivPos:integer;Pos:Integer;begin //定位字符串中最后一个运算符的位置 SubPos:=LastDelimiter('-',Str);PluPos:=LastDelimiter('+',Str);MulPos:=LastDelimiter('*',Str);DivPos:=LastDelimiter('/',Str);Pos:=SubPos;if(Pos 分别在给定的字符串中寻找+,-,*,/第一次出现的位置,然后比较4个符号出现的位置,得到数值最小的运算符。在返回的结果中,传递的是这个运算符的位置。 程序代码如下所示: function AnyFirstPos(Str:String):integer;var SubPos:integer;PluPos:integer;MulPos:integer;DivPos:integer;ForPos:integer;FirstPos:integer;begin //定位字符串中最先一个运算符的位置 SubPos:=Pos('-',Str);PluPos:=Pos('+',Str);MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);ForPos:=Pos('^',Str);FirstPos:=200;if(SubPos=0)then //如果没有-号 SubPos:=200;//将SubPos设置成一个不可能的值 if(PluPos=0)then //如果没有+号 PluPos:=200;//将PluPos设置成一个不可能的值 if(MulPos=0)then //如果没有*号 MulPos:=200;//将MulPos设置成一个不可能的值 if(DivPos=0)then //如果没有/号 DivPos:=200;//将DivPos设置成一个不可能的值 if(ForPos=0)then //如果没有^号 ForPos:=200;//将ForPos设置成一个不可能的值 if(FirstPos>SubPos)then FirstPos:=SubPos;if(FirstPos>PluPos)then FirstPos:=PluPos;if(FirstPos>MulPos)then FirstPos:=MulPos;if(FirstPos>DivPos)then FirstPos:=DivPos;if(FirstPos>ForPos)then FirstPos:=ForPos; AnyFirstPos:=FirstPos;//结束函数,返回位置 end;第3章 “速算24”扑克游戏--单元、异常、逻辑 3.5 数学逻辑单元(2) 3.得到最先出现的运算符类型 这个函数的返回结果是Char类型,代表这是一个字符变量。实际上,它返回的是+、-、*、/ 这4个符号中最早出现的一个。 程序分别寻找4个符号最早出现的位置,然后判断最先出现的是哪一种符号,再根据符号类型返回代表运算符的字符。 在具体的实现过程中,因为我们要得到最先出现的运算符,所以判断的是每次寻找后各个运算符的位置的最小值。如果不存在这个运算符,则将代表这个运算符位置的相应变量设置为200。对于本程序来说,这是一个搜索过程中不可能达到的值,这样就排除了这个位置的继续比较的可能。 程序代码如下所示: function AnyFirstF(Str:String):Char;var SubPos:integer;PluPos:integer;MulPos:integer;DivPos:integer;Operator:char;tempPos:integer;begin SubPos:=Pos('-',Str);PluPos:=Pos('+',Str);MulPos:=Pos('*',Str);DivPos:=Pos('/',Str); if(SubPos=0)then //如果没有-号 SubPos:=200;//将SubPos设置成一个不可能的值 if(PluPos=0)then //如果没有+号 PluPos:=200;//将PluPos设置成一个不可能的值 if(MulPos=0)then //如果没有*号 MulPos:=200;//将MulPos设置成一个不可能的值 if(DivPos=0)then //如果没有/号 DivPos:=200;//将DivPos设置成一个不可能的值 Operator:='-';tempPos:=SubPos;if(tempPos>PluPos)then begin tempPos:=PluPos;Operator:='+';end;if(tempPos>MulPos)then begin tempPos:=MulPos;Operator:='*';end;if(tempPos>DivPos)then begin tempPos:=DivPos;Operator:='/';end; AnyFirstF:=Operator;//结束函数,返回位置 end;4.计算不带括号的运算表达式 做完上述工作后,我们可以开始进行一些实际的运算了。 包括加、减、乘、除、乘方运算的表达式的程序算法如下所示: (1)寻找乘方符号“^”,如果存在,则计算一次乘方,去掉计算过的部分,接着循环查找和计算子串的乘方。 (2)寻找乘号“*”或者除号“/”,如果存在,则计算一次乘(除)法,去掉计算过的部分,接着循环计算子串的乘除法。 (3)寻找加号“+”或者减号“-”,如果存在,则计算一次加(减)法,去掉计算过的部分,接着循环计算子串的加减法。 上述算法是严格按照顺序进行的,它体现了数学运算中的优先关系,经过上述的计算,子字符串被分解,计算完毕。 无论是乘方、乘除法还是加减法,内部实现的逻辑是基本一致的。下面,我们设定有一个运算表达式:3+2^5/4。 程序代码如下所示: function SubCompute(Str:String):integer;var Middle:String;Mul2:String;Right:String;First:integer;tempStr:String;temp:integer;Left:String;Mul1:String;MulPos:Integer;DivPos:Integer;Fuhao:Char;begin Middle:='';Mul2:='';Right:=''; //定位第一个^号位置,计算乘方 First:=Pos('^',Str);While(First<>0)do //循环计算乘方 begin tempStr:=Copy(Str,1,First-1);temp:=AnyLastPos(tempStr);Left:=Copy(Str,1,temp);Mul1:=Copy(str,temp+1,First-temp-1);tempStr:=Copy(str,First+1,Length(str)-First);temp:=AnyFirstPos(tempStr);if(temp=200)then begin Mul2:=tempStr;Right:='';end else begin Mul2 :=Copy(tempStr,1,temp-1);Right:=Copy(tempStr,temp,Length(tempStr)-temp+1);end;Middle:=FloatToStr(IntPower(StrToInt(Mul1),StrToInt(Mul2)));Str:=Left+Middle+Right;First:=Pos('^',Str);end; //定位第一个*号或/号的位置 MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);First:=MulPos;if(MulPos>DivPos)then First:=DivPos;if((DivPos=0)and(MulPos<>0))then begin First:=MulPos;DivPos:=2000;// 将除号所在位置设置成一个大于MulPos但又不可能的值 end;if((DivPos<>0)and(MulPos=0))then begin First:=DivPos;MulPos:=2000;// 将乘号所在位置设置成一个大于DivPos但不可能的值 end;while(First<>0)do //循环计算乘、除 begin tempStr:=Copy(Str,1,First-1);temp:=AnyLastPos(tempStr);Left:=Copy(Str,1,temp);Mul1:=Copy(Str,temp+1,First-temp-1);tempStr:=Copy(Str,First+1,Length(Str)-First);temp:=AnyFirstPos(tempStr);if(temp=200)then begin Mul2:=tempStr;Right:='';end else begin Mul2 :=Copy(tempstr,1,temp-1);Right:=Copy(tempStr,temp,Length(tempStr)-temp+1);end;if(MulPos>DivPos)then Middle:=IntToStr(StrToInt(Mul1)div StrToInt(Mul2))else Middle:=IntToStr(StrToInt(Mul1)*StrToInt(Mul2));Str:=Left+Middle+Right; MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);First:=MulPos;if(MulPos>DivPos)then First:=DivPos; if((DivPos=0)and(MulPos<>0))then begin First:=MulPos;DivPos:=2000;// 将除号所在位置设置成一个大于MulPos但又不可能的值 end;if((DivPos<>0)and(MulPos=0))then begin First:=DivPos;MulPos:=2000;// 将乘号所在位置设置成一个大于DivPos但不可能的值 end;end;//定位+、-号首先出现的位置 First:=AnyFirstPos(Str);if(First=200)then //如果没有+、-号,则可以直接返回结果 begin SubCompute:=StrToInt(Str);exit;end;Fuhao:=AnyFirstF(Str);//确定首先出现的符号是+号还是-号 while(First<>0)do begin //如果找到+号或-号 tempStr:=Copy(Str,1,First-1);temp:=AnyLastPos(tempStr);Left:=Copy(Str,1,temp);Mul1:=Copy(Str,temp+1,First-temp-1);tempStr:=Copy(Str,First+1,Length(Str)-First);temp:=AnyFirstPos(tempStr);if(temp=200)then begin Mul2:=tempStr;Right:='';end else begin Mul2 :=Copy(tempStr,1,temp-1);Right :=Copy(tempStr,temp,Length(tempStr)-temp+1);end;if(Fuhao='+')then Middle:=IntToStr(StrToInt(Mul1)+StrToInt(Mul2))else Middle:=IntToStr(StrToInt(Mul1)-StrToInt(Mul2));Str:=Left+Middle+Right;First:=AnyFirstPos(Str);if(First=200)then break;Fuhao:=AnyFirstF(Str);end; SubCompute:=StrToInt(Middle);end;程序执行过程如下所示: (1)定位字符串中第一个乘方符号“^”的位置First。这个式子中的First为4。 (2)如果存在乘方符号,即First不等于0,则继续进行计算,否则退出循环。 (3)进入循环体内部,得到“^”前面的子串tempStr(“3+2”),寻找tempStr中的最后一个运算符temp(这里是“+”),则Temp和First之间的字符就是乘方符号的第一个参数(“2”)。 (4)同样的逻辑,得到“^”后面的子串tempStr(“5/4”),寻找tempStr中的第一个运算符位置temp(“/”),则Temp和First之间的字符就是乘方符号的第二个参数(“5”)。 (5)去掉乘方符号和两个参数,得到左侧子串left(“3+”)和右侧子串right(“/4”)。 (6)利用这两个参数和乘方符号,计算乘方,将结果返回,并插入在left和right之间,得到一次计算后的新字符串(“3+32/4”)。 (7)判断新串内部是否包含“^”,如果包含,则返回到步骤(3),不包含则进入下一种运算。 第3章 “速算24”扑克游戏--单元、异常、逻辑 3.5 数学逻辑单元(3)5.计算整个表达式的值 TotalCompute函数利用循环,找到最内层的一对括号,然后调用SubCompute函数处理这一对括号中的表达式。SubCompute函数处理的表达式中已经没有括号了,因此SubCompute只需处理乘方、加、减、乘、除,返回结果,形成新的字符串。 当整个字符串缩减至空值时,整个表达式计算完成。 程序代码如下所示: function TotalCompute(Str:String):integer;var First:integer;Last:integer;SubStr:String;LeftStr:String;Middle:String;Right:String;temp:integer;begin First:=LastDelimiter('(',Str);//定位最后一个(号位置 while(First<>0)do begin SubStr:=Copy(Str,First+1,Length(Str)-First);Last:= Pos(')',Str);//Last:=Last+First;//定位最后一个(号以后的最开始的)号位置 LeftStr:=Copy(Str,1,First-1);//(号左边的字符串 Middle:=Copy(Str,First+1,Last-First-1);//()号中间的字符串 Right:=Copy(Str,Last+1,Length(Str)-Last);//)号右边的字符串 temp:=SubCompute(Middle);//进入下面的计算 Middle:=IntToStr(temp); Str:=LeftStr+Middle+Right;First:=LastDelimiter('(',Str);end; Result:=SubCompute(Str);end;end.在程序中,“计算”按钮的OnClick事件处理程序中调用TotalCompute函数。函数中使用了一些数学函数和定位字符串的函数,这些函数Delphi已经在相应的系统单元中进行了定义,我们需要把这些系统单元包括到文件里面: uses Sysutils,Math;将前面调用TotalCompute的注释去掉,把代码改回: procedure TForm1.Button2Click(Sender: TObject);var result:integer;answer:String;begin result:=TotalCompute(Edit1.Text);if(result=24)then Application.MessageBox('您真行,我服了您!','对了',MB_OK)else begin第五篇:delphi24点游戏