C程序设计上机课程设计指导书.doc_第1页
C程序设计上机课程设计指导书.doc_第2页
C程序设计上机课程设计指导书.doc_第3页
C程序设计上机课程设计指导书.doc_第4页
C程序设计上机课程设计指导书.doc_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C程序设计上机课程设计最佳攻击目标选择的坦克游戏设计运用C语言来描述一种算法是非常方便的,因为C语言提供了非常丰富的运算符。此外,由于C语言的快速、高效这一特点,因此在许多研究领域,许多算法的实现和验证是采用C语言来进行的。本上机课程设计将实现最佳攻击目标选择的坦克游戏设计,来源于游戏设计项目。2.1准备工作这章的程序编写与前面几章的有所不同,它是根据某一个具体研究的算法来进行编程,因此具有一定的科研价值或实用价值。程序须达到该算法的某些特殊要求,如实时性、可扩展性等,在这些方面需要注意体现。另外,根据算法的当前应用领域,程序须设计一种与之相关的动画来进行演示。2.1.1实现规划一个算法思想一般都会以一种具体的描述形式来表达,并且都提供了算法的具体步骤或流程,而算法的验证则有待编程来实现。这一方面限制了编程者的发挥(因为必须按照算法的步骤来严格执行),而另一方面也相应地对编程者提出了更高的要求。因此,先要全面了解算法的思想以及它的作用。本程序主要实现一种多目标熵权决策分析算法。多目标决策分析是指在有多个不同目标时,如何根据各种条件来选出一个最优目标进行锁定。熵权决策分析算法就是针对这一问题提出来的,具体的算法内容将在下一节来详细介绍。程序实现的预期规划如下:1. 设计适当的数据结构2. 逐步实现算法的各个步骤,并进行验证3. 设计一种动画演示形式4. 在动画中调用算法来演示结果。另外,在程序中还计划加入辅助文档,以显示算法的各个中间步骤。现在,根据以上,可以将程序分为以下几个模块:l 算法模块:用于实现算法,包括算法各个步骤及相关函数。l 主模块:用于显示动画,在动画中调用算法并演示算法结果。l 辅助模块:用于显示算法中间过程的数据。2.1.2将程序代码分割为几类源文件先抛开程序的具体内容设计,而来解决一个程序文件分割的问题。这也可以说是本上机课程设计要讲到的第一个新的知识点。当一个程序代码过长时,往往很难进行维护和修改。而且过长的代码会弄得读程序的人头晕脑涨。于是,可以根据程序划分的模块来将代码分为几个子文件。一些有经验的程序员建议,尽量把一个大的程序按功能分成多个文件,一个文件尽量不要超作1000行,这样就可以比较清楚哪个文件的代码是健壮的,而哪个文件有可能有隐患,在进行程序调试和修改时便可以有针对性的检查相应文件代码。那么,如何进行文件代码的分割?又如何使之成为一个整体?分割其实很简单,就是把某一模块或某一类代码放到一个文件里,并保存为后缀名为 .c或 .h的文件。比如,将此程序的算法实现部分的代码放到一块,并保存为arithmetic.c,而动画演示部分的代码则保存为display.c。在此项目中,根据前面所划分的几个模块,可以将程序分割为以下几个模块,依次是l main.c:实时运行算法并用动画演示算法结果。l DMFunc.c:算法的各个步骤及与其相关的。l display.c:动画显示的各相关函数。l help.c:帮助文档l head.h:整个程序所用到的系统头文件、宏定义、全局变量以及主要函数申明。在分割完以后,将这些文件最好都放在一个文件夹内,比如d:tk。接下来进行各个文件的整合。在整个程序中,仍然只能有一个主函数main(),在该项目中这个主函数被放在文件main.c中。那么,假设要想在main.c中调用display.c这个文件中的函数和变量等,则只要在main.c的头文件包含部分象包含系统头文件一般将display.c包含进来便可,如下:/*-mian.c-*/#includedisplay.c这种包含方式可以嵌套,比如在step.c中包含了display.c,而在main.c中又包含了step.c,则在main.c中也可以调用display.c中的函数和变量。但是要特别注意的是,在一个程序中,一个文件只能被包含一次,比如在step.c中包含了display.c后,在其他文件中如main.c中就不能再来包含display.c了,而只能通过包含step.c来间接包含display.c。所以,最好不要出现嵌套包含的情况。这样就需要将每个文件所实现的功能都分得很明确,一个文件要能实现一个较大较完整的功能。实际上,一个文件只要在主程序中被包含了,在其他被主函数包含的文件中也可以调用该文件中。但是这里又有一个非常要注意的问题,那就是在主函数中各文件被包含的次序。假设在主函数中,各文件是依次如下被包含的:/*-main.c-*/#includehead.c#includedisplay.c#includeDMFunc.c#includehelp.c则在文件DMFunct.c和help.c中可以调用display.c,而反过来,文件display.c却不能调用此二个文件,这是因为文件display.c在此三个文件之前被主函数包含,而C语言在执行时会按照顺序依次来执行这几个包含语句,所以如果在display.c中调用位于它以下的那些被包含的文件,则由于程序还没执行那些包含语句,因此会出现错误。在此项目中,文件之间是这样来进行包含的:将整个程序所用到的系统头文件、宏定义、全局变量以及主要函数申明保存为一个头文件head.h,将其余各模块文件保存为后缀名为.c的文件,将它们都包含在main.c中。而其他文件中则不包含所用到的系统头文件,彼此间也不互相包含。由于在主文件main.c中最先包含了头文件head.c,因此其他文件便可调head.c中所申明的各宏定义和变量等,因此这些变量也就相当于全局变量。在整合了以后,如果各文件不是被放在TC的工作目录e:labturboc2include文件夹中,会发现程序仍然不能运行,会出现不能打开这些被包含的分割文件的错误。这是因为TC中默认的包含文件的存放目录为e:labturboc2include,如果使用包含语句例如#include help.c,则程序默认情况下会在e:labturboc2include目录中来寻找这些被包含的文件。解决的方法有两种。首先,假设这些文件都被放在d:盘的“tk”文件夹下,则可以在包含语句中添加该文件的绝对路径。比如要包含文件head.c,则形式如下:#included:tkhead.c此时要注意路径千万不能写错,否则如果在写错的这个路径下恰好也保存了该文件名,则程序便会调用这个写错的路径下的该文件了,而这个文件根本不是你原本想要调用的。另一种方法则是为TC添加各种文件的存放目录。在TC编程环境下,选择“Options”菜单下的“Directories”选项,可以看到TC默认的各存放目录,如图2.1所示。图2.1TC默认的文件存放目录其中各菜单项所代表的文件存放目录如下:l Include directories:包含文件(头文件)的存放目录l Library directories:库文件的存放目录l Output directories:输出文件(包括目标文件和可执行文件等)的存放目录,默认为当前目录l Turbo C directory:TC主目录则添加一个存放目录(比如Include directories)的方法就是:选中Include directories项,按回车键,然后在弹出的对话框中添加一个目录路径,该目录路径与前一目录路径之间用分号分隔。如图7.2所示。图7.2添加一个包含文件存放目录若有需要,还可以再添加另一个存放目录,只要在后面再加上一个目录名并用分号隔开。由于本程序中只要添加包含文件的存放目录,因此只要修改这一个选项。然后按回车键确定。回到”Options”菜单下来,选择”Save Options”选项,按回车键出现如下一个对话框,如图7.3。图7.3保存选项设置此时按回车键将出现一个确认对话框,如图7.4所示。图7.4确认保存提示框然后根据提示按”y”键,则覆盖了原来名为TCCONFIG.TC的配置文件,而将新的选项设置进行了保存。这样,在以后每次进入编程环境时,默认的存放包含文件的目录便有两个。现在再来编译执行main.c文件,便可运行了。7.2加熵权的决策分析算法7.2.1算法介绍首先来了解一下算法的用途和内容。前面已经介绍了什么是多目标决策。多目标决策可以广泛用于各个领域,比如机器人在多目标跟踪过程中选择一个最重要的目标进行跟踪,或军事上选择最优目标进行攻击,等。在多目标决策中,往往需要给各个目标赋一个权值来描述这些不同。这些权值既能反映主观的一面,又能反映客观的一面,从而能够区分各目标被锁定的先后程度。通常用表示第个指标的权重,且满足:和(2.1)本算法主要采用熵这一定义来确定权重。这里先来介绍一下关于此算法的一些相关定义和计算公式:定义1 熵的权重是指按照熵的思想,对多目标决策中各个评价指标赋权重,用来表示各指标在决策中相对重要程度的量。定义2 在有m个评价指标、n个被评价目标的问题中,有指标判断矩阵为,那么第个评价指标的熵定义为 (2.2)式中, (2.3)表示决策的不确定程度。因此,得到第个评价指标的熵权重计算公式:(2.4)下面给出算法的步骤。熵权决策算法是根据判断矩阵采用的模型,主要包括以下六个步骤。(1)构造指标判断矩阵。确定被评价的目标有n个,每个目标的评价方案有m个,那么每个方案的各指标值构成多指标评价矩阵。(2.5)如果各指标值采用不同物理量纲,需要将指标值标准化,以获得可比的尺度。本程序中假设各指标均已标准化。(2)构造加熵权的标准化指标矩阵。按上述公式计算熵和熵权值。(2.6)其中L和M分别代表矩阵的行和列中省略的数据。(3)找出理想点为(2.7)式中,。(4)计算被评方案到理想点的距离为: (2.8)(5)计算被评方案与理想点的贴近度: ;(2.9)(6)根据算出的贴近度对各个评价方案排序(低值为先),当值相等时,则以值加以区分(低值为先)。7.2.2熵权决策分析算法的实现先来实现程序的核心熵权决策分析算法。在实现这个算法过程中每实现一步便进行检验,看是否符合预期数据。这样便方便对算法的实现过程进行检验,使之能先着手建立起一个正确无误的算法,而不需要考虑其他如界面和动画等方面的事情。1.数据结构的设计标准指标判断的构成依赖于实际情况中的各种条件,在没有确定一种具体的实际应用环境之前,可以先假设程序已经获得了各个目标的标准化了的指标数据构成的标准指标矩阵,而具体如何获得指标矩阵将在以后的动画演示中来实现。因此实际上算法的实现只需从第三步开始。为了方便程序设计,需要设计以下的一些数据结构:/*-在文件head.c中定义-*/*-宏定义-*/#define mMax 10 /*-最大矩阵行值-*/#define nMax 10 /*-最大矩阵列值-*/*-全局变量-*/int m,n; /*-指标判断矩阵的行列值-*/int best,second; /*-最优和次优方案的数组下标索引-*/float fmMaxnMax,HnMax,OmiganMax;/*-fmMaxnMax存放公式(2.3)的因子,HnMax存放每个指标的熵,OmiganMax存放每个指标的熵权-*/float rmMaxnMax;/*-指标判断矩阵-*/float AmMaxnMax;/*-加熵权的标准化指标矩阵-*/float XnMax; /*-理想点-*/*-目标属性-*/struct Targetint ID; /*-目标标识符,用以识别该目标的唯一编号-*/int x,y; /*-目标坐标-*/float d; /*-方案距离-*/int dIndex; /*-方案距离在各方案的距离中排序后的索引号-*/float T; /*-方案贴近度-*/int TIndex; /*-方案贴近度在各方案的距离中排序后的索引号-*/int pIndex; /*-方案按贴近度和距离排序后的序号-*/;struct Target TanknMax; /*-定义存放目标结构的数组-*/2.算法函数的申明与实现现在可利用以上数据结构来实现与算法相关的各个函数了。下面是各相关函数的申明:/*-在文件head.c中申明-*/float Sigama(float a,int L);/*-求和-*/float findMax(float a,int L);/*-寻找最大值-*/float findMin(float a,int L);/*-寻找最小值-*/void Taxis(struct Target Tank,int pNum);/*-排序-*/*-算法步骤函数-*/void FormMatrix(); /*构造初始指标判断矩阵*/void FormEntropyMatrix(); /*构造加熵权的标准化指标矩阵A*/void FindPerfectPoint(); /*找出理想点Xm*/void CalDistance(); /*计算被评方案到理想点的距离Tankj.d*/void CalCloseDegree(); /*计算被评方案与理想点的贴近度Tankj.T*/void FindBestT(); /*根据贴近度和距离排序,找出最优目标*/void Arithmetic(); /*依次调用算法六个步骤*/ void ShowBest(); /*-显示最优目标-*/然后在文件DMFunc.c中来实现各函数,如下:/*-求和-*/float Sigama(float a,int L) /*-求得数组a中从下标0到L-1的元素之和。函数返回该和值-*/ int i; float temp=0; for(i=0;iL;i+) temp+=ai; return temp;/*-求最大值-*/float findMax(float a,int L) /*求得数组a中从下标0到L-1各元素的最大值。函数返回该最大值*/ int i; float temp; for(i=0;iai+1) temp=ai; ai=ai+1; ai+1=temp; return aL-1; /*-返回最大值-*/ /*-求最小值-*/float findMin(float a,int L) int i; float temp; for(i=0;iL-1;i+) /*-冒泡排序一轮将各元素的最大值交换到aL-1中-*/ if(aiai+1) temp=ai; ai=ai+1; ai+1=temp; return aL-1; /*-对各个方案的贴近度和距离进行排序-*/void Taxis(struct Target Tank,int pNum) /*-在定义的结构struct Target中定义了指示当前方案的贴近度和距离在各个方案中按大小排序所得到的序号TIndex和dIndex。此函数将各方案的TIndex和dIndex分别进行排序,得到其相应的排序号-*/ int i,j; for(i=0;ipNum;i+)/*从第一个开始,将第i个和第i+1个进行比较,若i的距离(或贴近度)大,*/ for(j=i+1;jTargetj.d) Targeti.dIndex+; else Targetj.dIndex+; if(Targeti.TTargetj.T) Targeti.TIndex+; else Targetj.TIndex+; /*-第一步:构造初始指标判断矩阵-*/void FormMatrix() /*暂不实现,而在实现了动画之后再来构造*/*-第二步:构造加熵权的标准化指标矩阵A-*/void FormEntropyMatrix() int i,j; float temp=0,k; k=1/log(n); for(i=0;im;i+) for(j=0;jn;j+) if(Sigama(&ri0,n)=0) fij=0; fij=rij/Sigama(&ri0,n); temp+=fij*log(fij); Hi=0-k*temp; temp=0; for(i=0;im;i+) Omigai=(1-Hi)/(m-Sigama(&H0,m); for(i=0;im;i+) for(j=0;jn;j+) Aij=Omigai*rij;/*-第三步:找出理想点Xm-*/void FindPerfectPoint() float amMaxnMax; int i,j; for(i=0;im;i+) for(j=0;jn;j+) aij=Aij; for(i=0;im;i+) Xi=findMax(&ai0,n);/*-第四步:计算被评方案到理想点的距离Tankj.d-*/void CalDistance() int i,j; float sigama=0; for(j=0;jn;j+) for(i=0;im;i+) sigama+=(Aij-Xi)*(Aij-Xi); Tankj.d=sqrt(sigama); sigama=0; /*-第五步:计算被评方案与理想点的贴近度Tankj.T-*/void CalCloseDegree() int i,j; float sigama1=0,sigama2=0; for(j=0;jn;j+) for(i=0;im;i+) sigama1+=Aij*Xi; sigama2+=Xi*Xi; Tankj.T=1-sigama1/sigama2; sigama1=0; sigama2=0; /*-第六步:根据贴近度和距离排序,找出最优目标-*/void FindBestT() int i,j,best_flag,second_flag; struct Target temp; best=0; for(i=0;in;i+) Tanki.dIndex=Tanki.TIndex=1; Tanki.pIndex=1; Taxis(&Tank0,n);/*-将贴近度和距离排序-*/ for(i=0;in;i+) /*-按贴近度将各方案进行排序-*/ for(j=i+1;jTankj.TIndex) Tanki.pIndex+; else if(Tanki.TIndex=Tankj.TIndex) /*若贴近度相同则比较距离*/ if(Tanki.dIndexTankj.dIndex) Tanki.pIndex+; else Tankj.pIndex+; else if(Tanki.TIndexTankj.TIndex) Tankj.pIndex+; for(i=0;in;i+) if(Tanki.pIndex=1) best=i; /*-找出最优方案,获得其方案序号-*/ best_flag=1; break; /*-调用算法各步骤找到最优目标-*/void Arithmetic() if(n=1) /*如果只剩最后一个目标,则直接规定最优目标为第一个*/ best=0; return; FormMatrix(); FormEntropyMatrix(); FindPerfectPoint(); CalDistance(); CalCloseDegree(); FindBestT();/*-显示最优方案和次优方案-*/void ShowBest() int i,j,x=14-2*n,y=5; clrscr(); gotoxy(12,2); printf(Find the 1st-selected and the 2nd-selected Project); for(i=0;i65;i+) gotoxy(x+i,y); putch(0xC4); gotoxy(x+i,y+2); putch(0xC4); gotoxy(x+i,y+10); putch(0xC4); gotoxy(x,y+1); printf(Project); gotoxy(x,y+3); printf(Distance); gotoxy(x,y+5); printf(Taxis by d); gotoxy(x,y+7); printf(Close_Extent); gotoxy(x,y+9); printf(Taxis by T); for(j=0;jn;j+) gotoxy(x+15+8*j,y+1); printf(Proj%d,j+1); gotoxy(x+15+8*j,y+3); printf(%.2f,Tankj.d); gotoxy(x+15+8*j,y+5); printf(%d,Tankj.dIndex); gotoxy(x+15+8*j,y+7); printf(%.4f,Tankj.T); gotoxy(x+15+8*j,y+9); printf(%d,Tankj.TIndex); for(i=1;i10;i+) gotoxy(x+14,y+i); putch(0xB3); gotoxy(x,y+11); putch(0x10); printf(The first-selected Project is Project %d.,best+1); gotoxy(x+1,y+12); printf(Target ID: %d,Tankbest.ID); gotoxy(x,y+13); putch(0x10); printf(The second-selected Project is Project %d.,second+1); gotoxy(x+1,y+14f); printf(Target ID: %d,Tanksecond.ID);3.编写简单的测试程序实现算法为了能尽快验证算法实现,在此先编写一个简单的测试程序。【例7-1】 算法测试程序首先,在文件head.c中包含如下头文件:#includestdio.h#includestdlib.h#includemath.h#includeconio.h然后,在文件main.c中包含文件head.c,以及DMFunc.c如下:#includehead.c#includeDMFunc.c为了测试的方便,在此测试程序中采用对二维数组r直接赋值的方法来获得标准指标判断矩阵。为此另设一个临时的函数GetR(),假设赋值如下:void GetR() int i,j; float tempmMaxnMax=0.3,0.9,0.5,0.9, 0.1,0.8,0.4,0.7, 0.5,0.9,0.6,0.3; for(i=0;im;i+) for(j=0;jn;j+) rij=tempij; for(i=0;im;i+) /*显示初始指标判断矩阵*/ for(j=0;jn;j+) cprintf(%8.4f,rij); cprintf(n); 最后,在主函数main()中调用各函数:main() clrscr(); GetR(); /*显示标准指标判断矩阵*/ getch(); clrscr();FormEntropyMatrix(); FindPerfectPoint(); CalDistance(); CalCloseDegree(); FindBestT(); Arithmetic(); ShowBest(); /*显示最后结果*/ getch();程序测试运行如图7.5和图7.6所示:图7.5算法测试程序显示标准指标判断矩阵图7.6算法测试程序显示最后结果将该结果与用MATLAB编写的相同算法的程序运行结果或用其他方法得到的结果来进行比较,可以发现,该结果的数据基本与其他各方法得到的结果数据相符,只有精度在0.001级别上的细微差别。而算法最后选出的最优和次优方案结果正确。还可以测试其他的多组数据,只要在函数GetR()中修改数组temp即可。此测试程序没有逐步显示各中间结果。但在编写每个函数模块时,都应该单独对其进行测试,这样才能保证最后结果的正确。7.3动画设计根据算法的实际用途,本章将利用多目标熵权决策算法实现一个有趣的动画效果:锁定多移动目标中的最优目标,然后进行击毁。首先,目标是多个的。其次,各目标是移动的。在这一部分,有几个有趣的创新点:多目标在固定区域内向各个方向的同时移动;攻击效果;星空闪烁背景等。7.3.1设计内容动画设计主要体现在动画内容的设计上。另外在此程序中,还要设计一种能体现多目标熵权决策算法的机制来进行演示。而动画的各种效果则要依靠编程来具体实现。下面分别规划这两个方面的基本内容。1.动画内容设计在屏幕上显示一个矩形区域,作为各个目标活动的区域。而在该区域的下方则显示一个炮台。各个目标在矩形区域内无规则地活动。一旦用户发出了锁定目标的命令后,则调用算法对当前的各个目标状态进行分析,并得出最优攻击目标。当用户下达攻击命令后,则从炮台飞出导弹将最优目标击毁。反复此过程,依次将各个目标击毁。最后显示“清除”字样。2.体现算法的机制设计在前面的算法实现部分,曾经省略了对各个攻击目标的指标进行获取从而构造初始指标矩阵这一环节。因而机制的设计实际上就是设计如何构造这个初始指标判断矩阵。为了体现算法的实用性,本程序决定模拟以前一个经典的中型电子游戏:坦克大战。在这个游戏中,玩家的主要目的便是在自己有限的生命值里保护己方的大本营,并将敌方坦克全部消灭,这样便算过一关。而在本程序中,将炮台看作大本营,玩家只需发出攻击命令,然后由算法自行选出一个最优目标将其击毁。在这里,最优目标定义为:当前状态下对己方大本营威胁最大的一个目标。可以用“危险性”来描述这种威胁。某个目标“危险性”越大,则越有可能被击毁。从第二节的算法描述中可以看到,指标判断矩阵是由每个目标的m个指标值构成的。也就是说,要确定几个共有的指标,并且根据不同情况给每个目标赋以不同的指标值,这样在某一时刻或某一状态下,这n个目标的m个指标值即构成了当前的初始指标判断矩阵。而根据上述提到的“危险性”,可以在程序中设计几个能体现这种“危险性”的指标。在游戏中,一旦敌方坦克直面己方大本营开过来时,或靠近大本营时,则很有可能对大本营构成威胁。另外,往往攻击力越强的坦克,这种威胁越大。因此,可以定义每个目标以下三个指标值:l 目标与大本营的距离distance。l 目标对大本营的侵略性invasiveness。l 目标本身攻击力power。这三个指标值在分别在struct Target结构中定义。其中“距离”可以通过实时坐标计算来获得。那么如何来获得另外两个值?对于“攻击力”,可以用目标本身的颜色来表示:给每个目标设置不同的颜色值,每种颜色值代表一个“攻击力”值。而“侵略性”指标获取则相对复杂些。根据游戏,可以得出以下三个规律:l 当目标直面大本营(也就是与大本营在同一水平线或同一垂直线上时)时,“危险性”较大。l 当目标运动方向为靠近大本营时,“危险性”较大;反之较小。l 当目标在大本营附近活动时,不管处于哪个运动方向,其“危险性”都较大。这三个规律互相辅助和克制,目标的“侵略性”便是根据这三个规律来指定。具体的制定方法在后面讲述。现在,对于“最优目标”定义又明确了一层,那就是:最靠近大本营的、最具侵略性的、火力最强的目标。当然,算法的思想是要综合考虑这三个方面因素,并权衡得出一个最理想的平衡点。7.3.2多目标的显示来利用一下第三章中的资源:坦克的绘制。也就是在这里将目标都画成一辆辆的坦克。但是,在坦克的头顶,还需附加上该坦克的编号,这点不难。先来看看演示平台及多目标的绘制。先定义相关数据结构和变量。这里只介绍背景平台的相关结构以及修改的坦克目标属性结构。其余参看随后的head.c文件的代码清单: 根据本章前面所设计的动画机制,在“坦克”的结构中首先需加上三个指标值:距离、侵略性、攻击力,这三个指标值的类型都设为符点型,因为它们是直接构成初始指标判断矩阵的数据。而由于攻击力由坦克的颜色值来决定,并且也为了方便图形的绘制,因此还需加上一个代表该坦克颜色的成员,以及坦克的半径。另外,设一个代表当前坦克运动方向的成员变量,以决定坦克的当前运动,并且方向与“侵略性”这一指标值密切相关。/*-坦克目标属性-*/struct Target int ID; /*-坦克标识符,用以识别该目标的唯一编号-*/ int x,y; /*-坦克坐标-*/ int r,color; /*-坦克半径和颜色-*/ float d; /*-距离-*/ int dIndex; /*-距离索引-*/ float T; /*-贴近度-*/ int TIndex; /*-贴近度索引-*/ int pIndex; /*-坦克排序索引-*/ int direction; /*-坦克当前运动方向-*/ float inva,distance,power;/*-分别为坦克的三个指标:“侵略性”、“距炮台距离”、“攻击力”-*/TanknMax; /*-定义坦克目标数组-*/另外,定义三种坦克的颜色值,各辆坦克的颜色从其中产生。int color3=WHITE,YELLOW,RED; /*-定义坦克的三种颜色值-*/而为了方便演示矩形框的绘制,在头文件中定义了一个struct RECT结构和一个struct Emplacement结构,分别用来描述演示矩形框和炮台。/*-演示窗口结构-*/struct RECT int left,top,right,bottom; int width,height;rect;/*-炮台结构-*/struct Emplacement int x,y;int width,lenth; /*为方便设计,width和lenth都只代表炮台宽度和长度的1/2*/int color;emp;其次是单个坦克的绘制。只要在第三章的代码基础上加上显示坦克编号的代码。用ShowInt()函数来实现坦克编号的显示。第三步是显示各辆坦克。在显示之前,首先要将各辆坦克初始化,初始化的内容包括坦克的编号、颜色值、半径以及随机坐标的产生。其中随机坐标的产生范围为矩形演示框内位于炮台上方的区域。这里要注意的一个地方是,要使一辆坦克完全位于矩形框内,则必须考虑到坦克的半径,因为坦克的坐标值是以其中心点的坐标来代表的。而在初始化时,由于将y坐标值都设在位于炮台之上,因此还要考虑炮台的位置和大小。因此实际上第i辆坦克的初始坐标值的变动范围为:x坐标:(rect.left+Tanki.r,rect.right-Tanki.r)y坐标:(rect.top+Tanki.r, rect.bottom-Tanki.r-2*emp.lenth)以上范围暂不考虑炮台所占的区域。下面两句话用来产生第i辆坦克的随机坐标:Tanki.x=rect.left+Tanki.r+random(rect.width-2*Tanki.r);Tanki.y=rect.top+Tanki.r+random(rect.height-2*emp.lenth-2*Tanki.r); 小经验:由于程序被分割成了几个文件,而如果要调试一个文件中的函数代码,则需要先保存当前文件的改动,然后回到包含主函数的文件中去,在主函数中调用该函数,然后保存主文件,再运行,才会显示改动后的效果。特别注意被改动的文件和主文件都要保存一次,否则程序运行的结果仍然会是改动前的效果。为此,可以在调试当前文件的单个函数时,在该文件的代码里加上一个主函数main(),然后在这个main()函数中调用要测试的函数,并且直接运行该文件的程序,以查看当前文件或函数是否有错误,这样就不用再回到包含主函数的文件中去进行调试。本程序中,由于整个程序要用到的头文件、宏定义以及全局变量都放到了一个文件head.h中,因此在要调试的文件中将该头文件head.h包含进来便可利用要用到的头文件、宏定义以及全局变量了。而在整体测试时,再将这个文件中的main()函数以及include”head.h”语句注释掉。下面是添加了main()函数以便测试关于演示矩形框及多辆坦克的绘制的程序代码(由于这部分功能未涉及到算法,因此不用将文件DMFunc.c包括进来):【例7-2】 演示背景框及多目标的显示“head.h”文件/*-head.h-*/*-头文件,宏定义,函数申明-*/#includestdio.h#includestdlib.h#includemath.h#includeconio.h#includetime.h#includegraphics.h#define upkey 72 /*-上方向键-*/#define downkey 80 /*-下方向键-*/#define leftkey 75 /*-左方向键-*/#define rightkey 77 /*-右方向键-*/#define Enter 13 /*-回车键-*/#define ESC

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论