资源描述
课课 程程 设设 计计 任任 务务 书书学院学院信息科学与工程信息科学与工程专业专业电子信息科学与技术电子信息科学与技术学生姓名学生姓名学号学号设计题目设计题目1.1.分数类的设计与实现分数类的设计与实现 2.2.生命游戏生命游戏 1.分数类的设计与实现分数类的设计与实现 建立用于完成分数形式运算的类 RationalNumber。编写一个测试该类的程序。用整数变量表示类的私有数据(即分子和分母) 。给类提供一个能够对所声明的对象初始化的构造函数。为了能够在不提供初始化值的情况下也能对对象初始化,构造函数中应该包含默认的值。构造函数还应该以最简分数的形式存储数据,即 2/4 应该在对象中存储成分子为 1、分母为 2 的形式。公有成员函数应该有以下功能: 1.两个有理数相加,以最简形式保存结果; 2.两个有理数相减,以最简形式保存结果; 3.两个有理数相乘,以最简形式保存结果; 4.两个有理数相除,以最简形式保存结果; 5.以 a/b 的形式输出有理数(a 是分子,b 是分母) ; 6.以浮点形式输出有理数。2.2.生命游戏生命游戏 生命游戏其实是一个零玩家游戏。它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。1.如果一个细胞周围有 3 个细胞为生(一个细胞周围共有 8 个细胞) ,则该细胞为生(即该细胞若原先为死,则转为生,若原先为生,则保持不变) 。 2.如果一个细胞周围有 2 个细胞为生,则该细胞的生死状态保持不变; 3.其它情况下,该细胞为死(即该细胞若原先为生,则转为死,若原先为死,则保持不变)进度安排:第 17 周:分析题目,查阅课题相关资料,进行类设计、算法设计;第 18 周:上机调试程序,程序测试与分析,撰写课程设计报告,准备答辩。指导教师(签字):指导教师(签字):年年 月月 日日学院院长(签字)学院院长(签字)年年 月月 日日目目 录录PART I.11 需求分析.12 算法基本原理.12.1 加法.12.2 减法.22.3 乘法.22.4 除法.23 类设计.24 详细设计.34.1 类的接口设计.34.2 类的实现.44.3 主函数设计.95 运行结果与分析.105.1 程序运行结果.105.2 运行结果分析 .12PART II.126 基于 MFC 的图形界面程序开发.126.1 基于 MFC 的图形界面程序设计 .12(1)界面设计.12(2)代码设计.146.2 测试程序.226.3 MFC 程序编写总结.237 参考文献.24PART I1 需求分析需求分析(1) 有理数可分为整数和分数也可分为三种,一;正数,二;0,三;负数。除了无限不循环小数以外的实数统称有理数。在数学上有理数的运用相当广泛,所以一款简易的有理数计算器可以大大节约时间,而且不会因为人为误差导致计算结果出错。(2) 依照它们的序列,有理数具有一个序拓扑。有理数是实数的(稠密)子集,因此它同时具有一个子空间拓扑。采用度量,有理数构成一个度量空间,这是它的第三个拓扑。幸运的是,所有三个拓扑一致并将有理数转化到一个拓扑域。有理数是非局部紧致空间的一个重要的实例。这个空间也是完全不连通的。有理数不构成完备的度量空间;实数是它的完备集。(3)程序测试数据选择若干种有代表性的数据来进行测试,通过临界数据的测试来判断系统的正确性。2 算法基本原理算法基本原理2.1 加法加法有理数的加法与小学的加法大有不同,小学的加法不涉及到符号的问题,而有理数的加法运算总是涉及到两个问题:一是确定结果的符号;二是求结果的绝对值。 在进行有理数加法运算时,首先判断两个加数的符号:是同号还是异号,是否有 0。从而确定用那一条法则。在应用过程中,一定要牢记先符号,后绝对值,熟练以后就不会出错了。 多个有理数的加法,可以从左向右计算,也可以用加法的运算定律计算。法则1同号相加,取相同符号,并把绝对值相加。2绝对值不等的异号加减,取绝对值较大的加数符号,并用较大的绝对值减去较小的绝对值。互为相反数的两个数相加得 0。3一个数同 0 相加,仍得这个数。定律.同号相加,取相同符号,并把绝对值相加。.绝对值不相等的异号两数加减,取绝对值较大的符号,并用较大的绝对值减去较小的绝对值。互为相反数的两个数相加得 0。.一个数同 0 相加,仍得这个数。.相反数相加结果一定得 0。2.2 减法减法有理数减法法则:减去一个数,等于加上这个数的相反数。其中:两变:减法运算变加法运算,减数变成它的相反数。一不变:被减数不变。可以表示成: ab=a+(b) 。2.3 乘法乘法1.两数相乘,同号为正,异号为负,并把绝对值相乘。例;(-5)(-3)=15 (-6)4=-242.任何数字同 0 相乘,都得 0. 例;01=03.几个不等于 0 的数字相乘,积的符号由负因数的个数决定。当负因数有奇数个数时,积为负;当负因数有偶数个数时,积为正。并把其绝对值相乘。例;(-10)-5(-0.1)(-6)=积为正数,而(-4)(-7)(-25)=积为负数4.几个数相乘,有一个因数为 0 时,积为 0. 例;3(-2)0=0 5.乘积为 1 的两个有理数互为倒数(reciprocal) 。例如,3 与1/3,3/8 与8/3。2.4 除法除法1.除以一个数等于乘以这个数的倒数。 (注意:0 没有倒数)2.两数相除,同号为正,异号为负,并把绝对值相除。3.0 除以任何一个不等于 0 的数,都等于 0。4.0 在任何条件下都不能做除数。3 类设计类设计从上面的算法分析可以看到,本设计面临的计算问题的关键是设计一个有理数运算类。这个类必须能将用户给定的 2 个整数表达成有理数,同时必须进行合法性检测。同时需要为类设计 4 个方法,分别来运算加法,减法,乘法和除法,为了使有理数运算看起来更符合自然,所以必须利用 C+的重载技术,来对相应的 4 种运算符进行重载,并且还需要设计一个方法来满足有理数分数形式和小数形式的转换。要从用户输入创建一个有理数,为类设计了一个带有默认参数的构造函数来满足需求。根据以上的分析,设计出CRationalNumber 类。如图 3.1 所示。图 3.1 CRationalNumber 类UML 图形表示4 详细设计详细设计整个程序分为三个独立的文档,RationalNumber.h 文件中为有理数类 CRationalNumber的申明,RationalNumber.cpp 文件中包括有理数类的成员函数实现文件;main.cpp 文件包括程序的入口函数和测试数据。4.1 类的接口设计类的接口设计/RationalNumber.h 文件,实现类的声明class CRationalNumber public:CRationalNumber (int nt=0,int dt=1); /带有默认参数的构造函数声明virtual CRationalNumber();public:int numtor; /分子int dentor; /分母CRationalNumber operator+(CRationalNumber &rn); /加号运算符重载函数声明CRationalNumber operator-(CRationalNumber &rn); /减号运算符重载函数声明CRationalNumber operator*(CRationalNumber &rn); /乘号运算符重载函数声明CRationalNumber operator/(CRationalNumber &rn); /除号运算符重载函数声明float ConvertFloat(); /将有理数转换成浮点数;ostream& operator (ostream &,RationalNumber &); /重载流插入运算符,使分数以(a/b)形式输出函数声明类 CRationalNumber 设计了一个带有默认构造参数的构造函数,方便用户构造有理数。同时设计了 4 个重载函数,可以让使用者像使用普通整数那样对有理数运算进行操作,大大的提高了使用简洁性。4.2 类的实现类的实现/ RationalNumber.cpp 文件,类实现#include stdafx.h#include RationalCompute.h#include RationalNumber.h/ Construction/Destruction/CRationalNumber:CRationalNumber(int nt,int dt) /带有默参数构造函数的定义int temp,num,n,d;n=nt;d=dt;if(nnumtor*rn.dentor+rn.numtor*this-dentor;temp.dentor=this-dentor*rn.dentor;int temp1,num,n,d;n=temp.numtor;d=temp.dentor;if(nnumtor*rn.dentor-rn.numtor*this-dentor;temp.dentor=this-dentor*rn.dentor;int temp1,num,n,d;n=temp.numtor;d=temp.dentor;if(nnumtor*rn.numtor;temp.dentor=this-dentor*rn.dentor;int temp1,num,n,d;n=temp.numtor;d=temp.dentor;if(nnumtor*rn.dentor;temp.dentor=this-dentor*rn.numtor;int temp1,num,n,d;n=temp.numtor;d=temp.dentor;if(nnumtor)/float(this-dentor);return (temp);ostream& operator (ostream &output,RationalNumber &rn) /重载流插入运算符的定义,使分数以(a/b)形式输出if(rn.dentor=0) /分母是 0 输出 errorcouterror!0 & rn.dentor0)output-rn.numtor/-rn.dentor;elseoutputrn.numtor/rn.dentor;return output;在类的构造函数中,对用户输入的数据进行了求最大公约数处理,使输入数据看起来最简洁化。而且在所有的运算操作中都对错误的数据(如分母为 0)的情况进行了处理。由于运算符比较特殊,所以没有将重载符放入类的成员函数中,而是作为全局函数来处理,避免与 cout的冲突。4.3 主函数设计主函数设计/main.cpp 主函数#include RationalNumber. h int main()cout .oO 欢迎使用有理数计算器 Oo. 请根据提示输入运算数据! endl; int n1,n2,m1,m2; coutnn 请输入第一个分数的分子与分母:n1n2; cout请输入第二个分数的分子与分母:m1m2; RationalNumber rn1(n1,n2); /定义类的对象 rn1 并指定分子与分母值 RationalNumber rn2(m1,m2); /定义类的对象 rn2 并指定分子与分母值RationalNumber rn3,rn4,rn5,rn6; /定义类的对象 rn3,rn4,rn5,rn6 不指定分子与分母,用默认参数对其初始化 /调用以浮点形式输出分数函数rn3=rn1+rn2; /调用加号重载函数rn4=rn1-rn2; /调用减号重载函数rn5=rn1*rn2; /调用乘号重载函数rn6=rn1/rn2; /调用除号重载函数coutrn1 加 rn2 等于: rn3 或者 ; /调用流插入运算符,使分数以(a/b)形式输出rn3.showfloat(); /调用以浮点形式输出分数函数coutrn1 减 rn2 等于: rn4 或者 ; /调用流插入运算符,使分数以(a/b)形式输出rn4.showfloat(); /调用以浮点形式输出分数函数coutrn1 乘 rn2 等于: rn5 或者 ; /调用流插入运算符,使分数以(a/b)形式输出rn5.showfloat(); /调用以浮点形式输出分数函数coutrn1 除 rn2 等于: rn6 或者 ; /调用流插入运算符,使分数以(a/b)形式输出rn6.showfloat(); /调用以浮点形式输出分数函数cout-计算完成,请按任意键退出系统!endl;getchar();getchar(); return 0;在程序的主函数部分,选择了让用户输入操作数据的方式来互动,当用户根据提示来输入相应的数据后,程序会自动运算出每组数据的所有操作结果,如果用户输入数据有错误,则会显示出错误信息。 5 运行结果与分析运行结果与分析5.1 程序运行结果程序运行结果当输入正确无误的数据后,程序运行结果如图 5.1 所示。图图 5.1 程序运行结果程序运行结果从图 2 中可以看出,当输入正确的数据后,系统能正确无误的计算出有理数相加,相减,相乘,相除的结果,并能正确转换成小数形式。 当输入有误的数据,如分母为 0 的时候,程序运行结果如图 5.2 所示。图图 5.2 程序运行结果(错误数据源)程序运行结果(错误数据源)从图 5.2 中可以看出,当输入错误的数据后,程序会检测出错误数据源,证明了程序的健壮性。当输入的数据分子和分母最大公约数不为 1 的情况下,程序运行结果如图 5.3所示:图图 5.3 程序运行结果(有公约数)程序运行结果(有公约数)5.2 运行结果分析运行结果分析首先当向程序输入正确的数据源后,程序能准确快速的计算出 4 则运算的结果,当向程序输入分母为 0 的错误的数据后,程序也同样能够识别。当向程序中输入的分子分母有最大公约数,并且最大公约数不为 1 的情况下,说明分数可以化简,程序也能很好的识别并给出正确的结果。从运行结果来分析,设计的有理数类完全满足于需求PART II6 基于基于 MFC 的图形界面程序开发的图形界面程序开发6.1 基于基于 MFC 的图形界面程序设计的图形界面程序设计MFC 的图形界面程序设计可在上述类设计的基础上进行改造,MFC 的图形界面程序与 DOS 界面程序的主要不同点是:MFC 图形界面程序与 DOS 界面程序的输入输出方式不同,DOS 界面程序采用字符交互式实现数据输入输出,主要通过 cin,cout 等 I/O 流实现,而 MFC 的图形程序界面采用标准 Windows 窗口和控件实现输入输出,因此必须在 MFC 类的框架下加入上面所设计的矩阵和方程组类,并通过图形界面的输入输出改造来完成。(1)界面设计)界面设计首先在 VC 中建立 MFC AppWizard(exe)工程,名称为 RationalCompute,并在向导的Step1 中选择 Dialog based,即建立基于对话框的应用程序,如下图 6.1 所示图图 6.1 建立建立 MFC AppWizard(exe)工程工程在弹出的 MFC AppWizard 对话框中,选择单文档应用程序,其他使用默认值如图 6.2,点击完成。图图 6.2 选择文档类型选择文档类型建立应用程序工程骨架,点击确定。如图 6.3图图 6.3 建立工程骨架建立工程骨架此程序已经具备了常见的程序外观,如标题栏,菜单栏,工具栏,状态栏和视图区,程序的框架已经构建起来了。可以在 VC+环境中看到 App Wizard 已经生成 5 个类,如图 6.4 图图 6.4,应用程序类视图,应用程序类视图(2)代码设计)代码设计在 CMyView 类视图里添加画笔,画出生命游戏中的游戏界面,定义时间函数,定义更新速度以及生命游戏的游戏规则,代码如下:void CMyView:paint(CDC *p)int a,b,i,j;for(i=0;i20;i+)for(j=0;jEllipse(i*30,j*30,i*30+30,j*30+30);CBrush c;c.CreateSolidBrush(RGB(0,255,0); p-SelectObject(c);srand(int)time(NULL);for(int x=0;xEllipse(a*30,b*30,a*30+30,b*30+30); float time2; char str20; time2=(float)(time1)/1000.0; sprintf(str,更新速度:%.2f 秒,time2); p-TextOut(20,630,str,strlen(str);DeleteObject(c);void CMyView:paint1(CDC *p) int i,j;for(i=0;i20;i+)for(j=0;j20;j+)int num=0;for(int i1=0;i13;i1+)for(int j1=0;j1SelectObject(c);p-Ellipse(i*30,j*30,i*30+30,j*30+30);if(num1=1)m1i+1j+1=1;elsemi+1j+1=1;DeleteObject(c);else if(num=2)if(num1=1)m1i+1j+1=mi+1j+1;elsemi+1j+1=m1i+1j+1;/*HBRUSH c; if(mi+1j+1=1) c=CreateSolidBrush(RGB(0,255,0); :SelectObject(hdc,c);else c=CreateSolidBrush(RGB(255,255,255); :SelectObject(hdc,c); :Ellipse(hdc,i*30,j*30,i*30+30,j*30+30); :DeleteObject(c);*/elseCBrush c; c.CreateSolidBrush(RGB(255,255,255); p-SelectObject(c);p-Ellipse(i*30,j*30,i*30+30,j*30+30);if(num1=1)m1i+1j+1=0;elsemi+1j+1=0;DeleteObject(c);if(num1=1)num1=0;elsenum1=1;void CMyView:OnDraw(CDC* pDC)CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);paint(pDC);/ TODO: add draw code for native data here/ CMyView diagnostics#ifdef _DEBUGvoid CMyView:AssertValid() constCView:AssertValid();void CMyView:Dump(CDumpContext& dc) constCView:Dump(dc);CMyDoc* CMyView:GetDocument() / non-debug version is inlineASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CMyDoc);return (CMyDoc*)m_pDocument;#endif /_DEBUG/ CMyView message handlersvoid CMyView:OnTimer(UINT nIDEvent) CDC *p;p=GetDC(); paint1(p);CView:OnTimer(nIDEvent);void CMyView:OnFileNew() SetTimer(1,time1,NULL);void CMyView:OnFileOpen() KillTimer(1);void CMyView:OnM1() CDC *p; p=GetDC(); KillTimer(1); time1=time1/10; float time2; char str20; time2=(float)(time1)/1000.0; sprintf(str,更新速度:%.2f 秒,time2); p-TextOut(20,630,str,strlen(str); SetTimer(1,time1,NULL);void CMyView:OnM2() CDC *p; p=GetDC(); KillTimer(1); time1=time1*10; float time2; char str20; time2=(float)(time1)/1000.0; sprintf(str,更新速度:%.2f 秒,time2); p-TextOut(20,630,str,strlen(str); SetTimer(1,time1,NULL); 6.2 测试程序测试程序游戏界面如下图 6.5,此时游戏未开始,点击开始游戏,则游戏开始,玩家可通过暂停,加速,减速参与游戏,游戏界面上的细胞根据运动规律每秒更新一次,则形成了一幅时刻变化的图。变化中的生命游戏图如图 6.6,6.7.图图 6.5 游戏开始界面游戏开始界面 图图 6.6 图图 6.76.3 MFC 程序编写总结程序编写总结MFC 程序与控制台程序最大的区别就是界面,由于 MFC 是一个微软公司提供的类库(class libraries) ,以 C+类的形式封装了 Windows 的 API,并且包含一个应用程序框架。其中包含的类包含大量 Windows 句柄封装类和很多Windows 的内建控件和组件的封装类。所以传统的控制台程序只需要学习 C+就能编写,但 MFC 程序必须要先熟悉 windows 编程,这也是初学者最大的挑战。不熟悉 windows 编程可以说是对 MFC 程序无从下手,本系统采用的是MFC 的对话框架构,相比于文本文档模式来讲,要简单易懂些。MFC 提供的对话框模板大大提高了用户体验的满意度和友好度,所以 MFC 必将为 windows程序员必学的类库。通过本次课程设计的开发,使我初步掌握了 windows 程序设计的窍门,也了解了与传统控制台程序之前的差别,可以说 C+是基础,会 windows 编程才能写出更友好实用的应用软件来。通过面向对象的封装与设计实践,是我更进一步理解了什么是面向对象编程。由于本课程设计要求的主要功能比较简单,所以我相信这只是我学习中的一个小台阶,我将以此为基石,在今后的学习过程中不断总结和进步,写希望老师能给予批评指正。7 参考文献参考文献1徐士良. C 常用算法程序集. 北京:清华大学出版社,19952郑莉,董渊,张瑞丰. C+语言程序设计(第 3 版). 北京:清华大学出版社,20073钱能. C+程序设计教程(第二版). 北京:清华大学出版社,20074陈志泊,王春玲. 面向对象的程序设计语言C+. 北京:人民邮电出版社,20025李庆扬,王能超,易大义. 数值分析. 湖北:华中理工大学出版社,19866李爱华,程磊 面向对象程序设计 C+语言 清华大学出版社,20107马秀丽,刘志妩,李筠 C 语言程序设计 清华大学出版社,2008
展开阅读全文