2011-2012(2)《软件工程导论》实验报告学院:计算机学院班级:软件工程114姓名:***学号:*********目录实验1:项目计划、分析和设计实验2;编码实验3:代码复查、编译实验4:项目测试总结软件工程导论实验一:项目计划、分析和设计[ 实验日期 ] 2012 年 4 月 20 日[ 实验目的 ]初步了解结构化分析、设计方法的原理、步骤以及各阶段的文档,练习撰写简要的需求文档、设计文档。
[ 实验内容 ]贪吃蛇程序:贪吃蛇游戏是一个深受人们喜爱的游戏,一条蛇在密闭的围墙内,在围墙内随机出现一个食物,通过按键盘上的四个光标键控制蛇向上下左右四个方向移动,蛇头撞到食物则表示食物被蛇吃掉,这时蛇的身体长一节,同时计1分,接着又出现食物,等待被蛇吃掉,如果蛇在移动过程中,撞到墙壁或身体交叉蛇头撞到自己的身体,游戏结束。
根据编写贪吃蛇的游戏规则,我们利用c语言来进行编辑具体步骤,从而使游戏能够运行,根据编写贪吃蛇程序,掌握软件工程思想及要领,进一步巩固编程思想和掌握画图函数底层,依据项目可行性研究的结果,进行需求分析和设计,编写简要的需求规格说明书,绘制程序流程图。
[ 实验原理和步骤]当前的建模方法主要有传统的结构化分析、设计方法(SA/D)和面向对象分析、设计方法(OOA/D)两种。
分析阶段:结构化分析(SA)是一种建模技术,它通过一定方法帮助开发人员定义系统需要什么功能,系统需要存储和使用哪些数据,以及为完成这些功能,系统需要什么样的输入和输出以及如何把这些功能结合在一起来完成任务。
设计阶段:分总体设计和详细设计两阶段。
总体设计阶段的任务主要是确定系统由哪些模块组成,以及这些模块之间的相互关系;详细设计阶段的任务主要是设计每个模块的处理过程。
常用的结构化设计(SD)方法有面向数据流分析(DFA)的设计方法和面向数据的设计方法。
DFA设计技术实施的通用步骤:(1)复查并精化DFD;(2)确定DFD类型;(3)把DFD映射到系统模块结构,设计出模块结构的上层;(4)基于DFD逐步分解高层模块,设计出下层模块〈初步结构〉;(5)根据模块独立性原理,精化模块结构,得到更为合理的软件结构;(6)模块接口描述;(7)修改和补充数据词典;(8)制定测试计划。
详细设计阶段的任务主要是确定每个模块的处理过程,包括(1)确定每个模块的算法。
(2)确定每一个模块的数据组织。
(3)为每个模块设计一组测试用例。
(4)编写详细设计说明书。
详细设计阶段采用的方法是结构化程序设计(SP),与SA,SD方法衔接。
目标是给出可以直接用以编码的程序逻辑结构,强调清晰第一。
设计思路:这个程序的关键点是表示蛇的图形以及蛇的移动。
用一个小矩形块表示蛇的一节身体,身体每长一节,增加一个矩形块,蛇头用两节表示。
移动时必须从蛇头开始,所以蛇不能向相反方向移动,也就是蛇尾不能改作蛇头。
如果不按任何键,蛇自行在当前方向上前移,当游戏者按了有效的方向键后,蛇头朝着指定的方向移动,一步移动一节身体,所以当按了有效的方向键后,先确定蛇头的位置,然后蛇身体随着蛇头移动,图形的实现是从蛇头的新位置开始画出蛇,这时,由于没有清屏的原因,原来蛇的位置和新蛇的位置差一个单位,所以看起来蛇会多一节身体,所以将蛇的最后一节用背景色覆盖。
食物的出现和消失也是画矩形块和覆盖矩形块。
为了便于理解,定义了两个结构体:食物和蛇。
[ 需求规格说明书]主要功能陈述:这是一款适合各年龄阶层小游戏,它可以使人们休息时的一种放松方式也可以是孩子们的娱乐游戏;另外对于一些对于有一定的C语言基础的,可以一边在玩的时候,感受在其中的编程思想并且自己进行尝试。
IPO图:数据字典:先进行蛇与食物的定义,再制定游戏中蛇的光标处理方法,初始化蛇的位置坐标,接着创建整个游戏的活动界面从而确定游戏的整体的框架。
初始化游戏的计分系统,设置初始化分数,再增加分数统计系统确立分数处理的方法。
接着编写游戏的规则,蛇的走动方法与吃到食物增长的处理以及游戏中碰壁或碰到自身的处理,最后进行对游戏失败的处理以及游戏的清屏处理。
[ 详细设计说明书]模块的文字描述:main()主函数:这是程序的大体流程,首先定义使用到的常数、全局变量及函数原型说明,然后初始化图形系统,调用函数画出开始画面,调用函数,即玩游戏的具体过程与分数的增加,游戏结束后调用关闭图形系统清理屏幕,结束程序画界面函数:设计游戏的活动界面,就是一个密封的围墙加上一个数据处理界面,利用printf 来构建游戏的大体框架与各个部分的具体内容游戏具体过程函数:这一部分是游戏的重要组成,调用这个函数是游戏的主要部分,重点是一次次反复表示蛇与食物的新位置并进行对前一次的反复清屏。
采用的方法是每次移动的时候从最后一节开始到倒数第二节,将前一节的坐标赋值给后一节的坐标,移动后只要把最后一节用背景色去除即可。
蛇的方向通过w a s d键进行控制数组的加减。
如果没有食物,随机出现食物;如果有食物,则显示食物,蛇移动身体,根据蛇的方向改变坐标值,并判断蛇是否撞到了墙或自己吃了自己,如果出现这两种情况之一,则蛇死,调用游戏结束函数结束本次游戏或重新开始。
如果蛇吃到了食物,蛇身体长一节,数组元素增加一个,身体节数、分数都进行相应的改变。
如果有按键,则识别键值。
如果按键为Esc键则结束游戏,程序运行结束;如果所按键为方向键,则根据该键改变代表蛇方向的变量的值,要考虑相反方向键无效。
游戏结束函数:游戏结束,显示游戏结束信息。
HIPO图:[[注意事项]1.程序流程图应符合结构化思想:单入口、单出口。
[实验总结 ]通过本次试验让我加深了对程序设计的理解,对程序结构化设计有了进一步的认识,同时也是对自己编程思想的优化和编程能力的提高,认识到了如何将程序设计工程化,同时也发现了自己诸多问题,对软件工程思想没有很好的理解,以及IPO图和HIPO图的绘制与编写出现了问题,我觉得在画图之前首先要确定具体框架,然后根据框架进行补充。
此次试验让我发现了很多问题,我认识到编写任何程序无论难或易都要进行实验前的准备,对实验的步骤有个具体了解并且能够理清实验思路才能够进行实验。
这些发现让我能够及时的进行自我反思从而对自己进行相应的改进。
总体说,这次实验让我学到了很多宝贵的经验与思想,为以后打好基础。
软件工程导论实验二:编码[ 实验日期 ] 2012 年 4 月 20 日[ 实验目的 ]通过对本次贪吃蛇程序的编写,了解各种不同的编程方法和不同的编程风格,从而在这次实验以及以后学习过程中养成属于自己的良好的编程风格与编程方法技巧。
[ 实验内容 ]通过实验一的基础,先制定基本框架,然后在这个基础上详细的进行编注,整体按照相应的结构化思想编写代码,在相应的地方做出对自身的注释,从而能够使自己和他人能够更好的理解。
[ 实验原理和步骤]编码的原理包括几方面,首先编码风格要强调“清晰易读”,不能过分个性化或过多的插入个人技巧,要做到自己编的程序对于那些会编程的人都能够轻易理解并能够在不足的地方进行修改。
编码过程中要注意变量或函数的名字要赋予相应的意义,做到每个代码都有自己存在的意义与作用。
编码中的表达式和语句要一目了然,排版风格、循环语句风格要保持一致,使人在阅读你的程序是能够很快理解你要表达的意思与目的。
在函数宏的定义,常数的定义,注释方面要全面。
注释包括序言性注释、函数模块注释和程序语句注释。
[具体步骤]首先制定相应的程序框架,然后根据实验一种相应的模块进行相应的填充。
当整体程序基本成型后,再通过反复测试,找出其中的不足,进行不断地完善。
然后对程序中相应的模块与需要理解的地方进行合理的简洁的注释,使他人能够跟快的理解。
对每个函数前写模块注释,重要语句写功能性注释,变量或函数的名字要有意义,排版,从而使程序变得美观易懂。
[ 程序源代码]#include <stdio.h>#include <windows.h>#include <time.h>#include <conio.h>#include <stdlib.h>#include <string.h>int snake_len=1;//蛇的长度int snake_loc[50][2]={31,12};//整条蛇的位置,最长为50int snake_head[2]={31,12};//蛇头位置,初始值为11,12;int food[2];//食物位置char snake_direction='s';int delay=200; //蛇每delay个时间走一步int eat_flag=0;//1表示吃了食物,0表示未吃int liv_stat=0;//1表示死了,游戏该结束了;0表示还活着void gotoxy(int x, int y)//定位光标,x为行坐标,y为列坐标{COORD pos = {x,y};HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(hOut, pos);}void hidden()//隐藏光标{HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO cci;GetConsoleCursorInfo(hOut,&cci);cci.bVisible=0;//赋1为显示,赋0为隐藏SetConsoleCursorInfo(hOut,&cci);}void init()//初始化{int i;snake_len=1;//蛇的长度snake_loc[0][0]=31;//整条蛇的位置snake_loc[0][1]=12;snake_head[0]=31;//蛇头位置,初始值为11,12;snake_head[1]=12;snake_direction='s';delay=200;eat_flag=0;liv_stat=0;for(i=1;i<50;i++){snake_loc[i][0]=0;//整条蛇的位置snake_loc[i][1]=0;}}void create_window()//创建窗口{gotoxy(0,0);printf("********************************************************************* ***********");printf("* * *");printf("* * *");printf("* * 分数:1 *");printf("* * 按键说明:*");printf("* * 上:w *");printf("* * 下:s *");printf("* * 左:a *");printf("* * 右:d *");printf("* * 暂停:空格*");printf("* * 退出:Esc键*");printf("* * *");printf("* * *");printf("* * *");printf("* * *");printf("* * *");printf("* * *");printf("* * *");printf("* * *");printf("* **");printf("* * *");printf("* * *");printf("* * *");printf("********************************************************************* ***********");}void update_score()//更新分数{gotoxy(73,3);printf("%2d",snake_len);}void create_food()//产生食物的位置{time_t t;srand(time(&t));while(1){food[0]=rand()%62+1;//生成1~62之间的随机数,其中random函数生成0~77之间的随机数food[1]=rand()%22+1;//生成1~22之间的随机数,其中random函数生成0~17之间的随机数if(food[0]!=snake_head[0]&&food[1]!=snake_head[1])break;}gotoxy(food[0],food[1]);printf("*");}void direction(){char keyhit=0,i;while(kbhit()!=0)keyhit=getch();if( ((keyhit=='a') || (keyhit=='d') || (keyhit=='w') || (keyhit=='s')) && (abs(snake_direction/16-keyhit/16)==1) )snake_direction=keyhit;else if(keyhit==' '){gotoxy(30,24);system("pause");gotoxy(30,24);for(i=0;i<19;i++)printf(" ");}else if(keyhit==27)exit(0);}void state()//判定蛇死没死{if(snake_head[0]<1||snake_head[0]>62||snake_head[1]<1||snake_head[1]>22)liv_stat=1; }void eat()//判定蛇吃没吃上,并对根据方向对蛇头位置进行更新{switch(snake_direction){case 'w': snake_head[1]--;break;case 's': snake_head[1]++;break;case 'a': snake_head[0]--;break;case 'd': snake_head[0]++;break;}if((food[0]==snake_head[0]) && (food[1]==snake_head[1]) ){eat_flag=1;switch(snake_direction){case 'w': snake_head[1]--;break;case 's': snake_head[1]++;break;case 'a': snake_head[0]--;break;case 'd': snake_head[0]++;break;}}}void show_snake()//更新蛇在屏幕中的位置{gotoxy(snake_head[0],snake_head[1]);printf("*");gotoxy(snake_loc[snake_len-1][0],snake_loc[snake_len-1][1]);printf(" ");}void update_maxtrix()//更新存储蛇位置的数组{int i;if(eat_flag!=1){for(i=snake_len-1;i>0;i--){snake_loc[i][0]=snake_loc[i-1][0];snake_loc[i][1]=snake_loc[i-1][1];}}else{snake_len++;if(snake_len>3 && delay>100)delay-=30;for(i=snake_len-1;i>1;i--){snake_loc[i][0]=snake_loc[i-2][0];snake_loc[i][1]=snake_loc[i-2][1];}snake_loc[1][0]=food[0];snake_loc[1][1]=food[1];eat_flag=0;create_food();update_score();}snake_loc[0][0]=snake_head[0];snake_loc[0][1]=snake_head[1];}void main(){int flag;long password=123456;int i=1;long pw;printf("请输入密码\n");scanf("%ld",&pw);if(password!=pw)while(1){i++;printf("密码错误\n请重新输入:");scanf("%ld",&pw);if(password==pw){printf("密码正确,欢迎使用\n");flag=1;break;}i f(i==3){printf("请稍后再试\n");flag=0;break;}}else{printf("密码正确,欢迎使用");f lag=1;LOOP:system("cls");init();create_window();hidden();create_food();while(1){int i;Sleep(delay);direction();eat();show_snake();update_maxtrix();state();if(liv_stat==1){for(i=1;i<snake_len;i++){gotoxy(snake_loc[i][0],snake_loc[i][1]);printf(" ");}gotoxy(food[0],food[1]);printf(" ");gotoxy(30,12);printf("Game over!\n");gotoxy(25,13);printf("继续请按y,退出请按n");while(1){i=getch();if(i=='y')goto LOOP;else if(i=='n')break;}break;}}}}[注意事项]1.模块的逻辑描述应该清晰第一、使用标准的、规范的控制结构、正确可靠[实验总结 ]通过对实验二的学习让我对程序的编写有了更深的理解也对编程的谨慎性有了更深层次的体会,即使在小的疏忽或错误都会影响整个实验的进行。