软件工程实践报告Word文件下载.doc
《软件工程实践报告Word文件下载.doc》由会员分享,可在线阅读,更多相关《软件工程实践报告Word文件下载.doc(29页珍藏版)》请在冰点文库上搜索。
它还可以直接访问内存的物理地址,进行位(bit)一级的操作。
由于C语言实现了对硬件的编程操作,因此C语言集高级语言和低级语言的功能于一体。
既可用于系统软件的开发,也适合于应用软件的开发。
此外,C语言还具有效率高,可移植性强等特点。
因此广泛地移植到了各类各型计算机上,从而形成了多种版本的C语言。
因而越来越多的高等院校已经将C语言作为非计算机专业甚至计算机专业的必修课和选修课,C语言也成为了软件设计的首选语言之一。
本学期我们进行了软件工程实习活动,主要的任务就是运用所学的C语言知识,在turboc集成环境下制作一个小型贪食蛇应用程序,以达到熟悉和熟练运用C语言的目的,为将来的学习和工作打下良好的实践基础。
虽然贪食蛇游戏在我们日常生活中是很平常见,但作为很普通的一款小游戏,他却有着极强的生命力。
它的简单易行使之广泛的存在于电脑,手机,游戏机等载体上,加上变化无穷、引人入胜让它成为了一款受人喜欢的小游戏
第二章需求分析
项目背景和内容概要:
现在我们所要介绍的这一款游戏---贪吃蛇。
是个简单的小游戏,但却能给人以放松,让我们从繁重的日常生活中解脱出来。
而只有我们的身心得到了娱乐才能更好的投入到新的工作。
现在的人,不管是已经工作的,还是还未进入社会的学生,都面临着很大的压力,而这样一款能让我们随时随地都能享受的游戏,其魅力还是不可估量的。
·
系统分析
1可行性分析
1。
1技术可行性
完全可以利用C语言来编程,在TC下也能顺利运行,可以说在技术这方面不会有大的问题。
2经济可行性
可以说其经济利益将相当可观,随着手机和电脑的普及,这样的小游戏也将随着普及,到时候我们也可以静观其成。
3操作可行性
对于这样一个简单易行的游戏,其操作不会有问题的,不论是怎样的平台都能很好的运行。
而用户也可以在其受益不浅。
2需求分析
游戏是人们生活中不可或缺的,一个人从小到大,真正伴随他成长的东西,游戏占有着很重要的地位。
不论是一个玩具,还是一个能和伙伴一起开心的小游戏,都是能给我们留下很多美好的回忆。
所以不论是什么样的游戏,只要它能迎合人们内心的某种需求,它的市场总会是好的。
第三章设计要求
具体的设计要求包括基本要求和提高要求
贪食蛇游戏的基本要求是在turboc集成环境下用C语言进行编译。
游戏规则:
1、蛇头不能咬蛇身--蛇头不能和蛇身发生碰撞,撞上就gameover,包括不能反方向运动
2、蛇头不能碰障碍--撞上就gameover,包括不能走出游戏区域
3、蛇吃了食物会增加长度,食物吃掉一个才会产生新的
4、蛇只有上下左右四个行走方向
提高要求是为了让界面看起来更大方和美观,并对吃下的豆子进行积分,当游戏结束时,界面出现“GAMEOVER”的提示
第四章系统的组成
系统的组成部分即程序模块结构:
1、初始化:
场景、外边框和蛇(初始化蛇的长度,初始化蛇的行走方向)
2、在场景中放置食物,吃完一个再出现下一个,吃一个食物蛇身增加一节,食物不能和障碍重合
3、蛇的运动,一节跟一节
4、行走中检测蛇头不能和障碍、蛇身碰撞,也不能超出游戏区域
5、键盘的监听,控制蛇的运动,及改变游戏状态
第五章概要设计
一、程序初始化:
1、全局变量的定义(初始化游戏的速度以及得分)
2、蛇结构体的定义,食物结构体的定义
3、图形界面的初始化(Init()函数)
游戏围墙的绘制(Draw()函数)
食物的出现(Gameplay()函数)
此次编译方法采用的是结构体定义编程,除了此方法还可以运用双向链表的方法制作贪食蛇游戏,但是因为编程复杂且不容易理解,所以未采用。
二、设计流程图
在游戏程序中,主任务0主要完成一些初始化的工作,开机画面的显示。
在任务2种一开始将屏幕清屏,然后绘制贪食蛇游戏的边界和计分状态,最后进入一个无限循环,在循环体中根据游戏者的按键进行相应的处理,详细流程图如下图所示:
绘制游蛇的边界图案
显示游戏界面右边的静态图片和计分清零
初始化蛇的位置以及蛇的游动方向
等待键盘扫描任务发来的消息
判断按键
的值
Reset键暂停键
方向键
重新创建任务2,重新开始游戏
改变蛇游动的方向
把任务2挂起,使游戏暂停
延时
图1:
贪食蛇吃豆的任务流程图
蛇的动态显示建立在任务2,主要是不停的更新蛇的位置,另外每更新一次还需要判断蛇是否碰到边界,是否碰到自己身子,是否吃到豆子等。
其流程图如下图所示:
游戏
结束否?
否
更新蛇的位置,将蛇头原来坐标赋给蛇身,蛇身原来坐标赋给蛇尾。
是否碰到边界或自己身体
是
游戏结束
是否吃到豆子
增加蛇身的长度
更新豆子
蛇身各坐标赋值
第六章详细设计
一、对象模型设计
1、寻找规律,建立对象模型:
首先从物理的角度来分析蛇得运动规律。
它是蠕动的,像水一样流动。
他有个特性就是身体的每一个点都经过他头部所在的点,他每一个时刻骨节所要运动的目的地是他前一个骨节所在的位置。
不难看出,其中的对象模型为
蛇,骨骼,骨节,头
抽象的接口为
蛇,骨骼,骨节,头,图中豆子
2、结构图:
接口结构图
骨骼骨骼
骨骼
骨节
蛇
豆子
头
对象结构图
3、给接口添加行为:
图元(GraphicObject)
绘画:
进行图元自身的绘画操作
当前矩形:
得到图元当前所在的矩形,也可考虑使用region,这样使得对图元范围得描述更加具体。
骨节(Condyle)
前一个骨节:
提供前序访问
后一个骨节:
提供后序访问
流动:
进行骨节运动诡计得计算。
骨骼(Cadre)(管理骨节链)
得到头:
得到蛇头
得到尾:
得到蛇尾
新增骨节:
在骨节链中新增骨骼
删除骨节:
在骨节链中删掉指定骨节
头(head)
方向:
能够设定和访问当前运动方向。
蛇(Snake)
增长:
蛇进行自身得增长
4、完善模型,引入访问者模式
存在的问题:
当前是由具体的骨骼对象来负责图元的绘画以及处理流动的,而骨骼只是管理骨节,没有提供任何访问骨节的方法,我们应该怎样访问骨节呢?
比如我们要每个骨节画出自己的形态,我们可能会这样做。
在骨骼上提供一个绘画方法,然后通过遍历骨节链,调用每个骨节的绘画方法。
这样似乎可以解决问题。
那么,我们要进行骨节流动计算呢?
我们再在骨骼上提供流动方法,然后同样的遍历骨节,调用每个的流动方法。
我们要是加入统计骨节个数功能呢?
我们要是加入其他的需要遍历骨骼的方法呢?
……
这样做的缺点是什么?
相似的代码有多份
如果骨节的访问结构发生变化,后果会怎样?
有新功能需要遍历骨节链该怎么办?
这样会迫使我们拷贝代码。
解决办法,引入访问者模式:
新增加接口如下:
加入行为:
访问者:
(空,无方法,属性)
被访问者:
接受访问者
骨节访问者:
继承自访问者
访问骨节
访问者
被访问者
骨节访问者
5、完整的结构图:
图元
二、食物及蛇状态的初始化及食物的出现
(一)、程序初始化
——————全局变量
全局变量:
是指在函数之外定义的变量,其作用范围是从定义位置开始到源文件结束为止,其间的函数
都可以使用
int
a,b
;
f1(intc)
{
intd,e;
…
}
inti;
main()
intm,n;
}
全局变量a、b的作用范围,c的作用范围,d、e的作用范围
(二)、程序初始化
—————结构体的定义
蛇的结构体的定义:
每一节蛇坐标的表示蛇移动方向的表示蛇生命的表示蛇节数的表示
食物结构体的定义:
食物的坐标的表示食物有无的表示
(三)、程序初始化
—————图形界面的初始化
intgd=DETECT,gm;
initgraph(&
gd,&
gm,”c:
\\Win-TC”);
(四)、游戏边框的绘制(Draw函数)
开始画面,左上角坐标为(50,40)
右下角坐标为(610,460)的围墙
库函数rectangle(left,top,right,bottom);
(50,40)
(610,460)
(60,50)
(600,450)
9
(五)、Gameplay()函数:
———结构体变量的使用
需要出现新食物:
food。
yes=1;
/*1表示需要出现、0表示已存在*/
蛇的状态:
snake。
life=0;
/*0表示活着、1表示死亡*/
蛇默认(初始)运动方向:
direction=?
;
蛇的默认(初始)节数:
snake。
node=2;
蛇的默认(初始)坐标:
x[0]=?
y[0]=?
/*蛇头*/
x[1]=90;
y[1]=100;
/*蛇身*/
注意结构体变量成员的引用格式:
<
结构体变量>
。
成员>
(六)、Gameplay()函数:
—————食物的出现
判断是否需要出现食物——判断food。
yes的值
1:
/*需要出现新食物*/
随机产生食物坐标,并使坐标能被十整除
/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/
改变food。
yes的状态:
0:
/*显示食物*/
画出食物
蛇的运动:
先自由移动,用方向键控制蛇的方向。
三、游戏运行中的设计思想:
1、蛇自由移动:
在没有任何按键的时候,蛇按照初始方向向前移动;
2、方向键控制蛇的移动方向:
用方向键控制蛇结构体里面的方向成员。
同时如果不出现蛇死亡或者按ESC键,我们可以永远玩游戏。
永远玩游戏这里将用到一个什么语句?
永循环
while
(1)
while(bioskey
(1)==0)表示无键盘输入
Gameplay()程序结构
while
(1)
{
while(bioskey
(1)==0)
{
蛇身、蛇头坐标的改变
画出蛇,并使蛇运动
}
/*endwhile(!
bioskey
(1))*/
监听方向键及ESC键
/*endwhile*/
判断是否需要出现食物,并进行相应的操作
食物及蛇状态的初始化
3、蛇的移动
移动的思想:
(1)蛇身、蛇头坐标的改变
蛇身:
将蛇的第二节在屏幕中的坐标移动到第一
节,第三节中的坐标节移动到第二节……
蛇头:
随着方向键走。
(2)蛇向前运动:
画出蛇,延时(gamespeed),并用用背景色去除
蛇的最后一节
4、蛇的坐标改变
for(i=snake。
node-1;
i>
0;
i--)
{
snake。
x[i]=snake。
x[i-1];
y[i]=snake。
y[i-1];
5、方向键的表示
上
下
左
右
UP
DOWN
LEFT
RIGHT
1
2
3
4
6、如果蛇结构体的方向成员为
y[0]-=10;
2:
……………
3:
4:
7、蛇向前运动
画蛇(for)
delay(gamespeed);
用背景色去除蛇的最后一结:
(1)接受按键:
key=bioskey(0);
(2)按ESC键退出游戏
(3)方向键改变蛇的结构体方向成员
如果key==UP&
&
direction!
=2:
direction=1;
………依此………。
。
类推…………………………
(二)、方向键控制蛇的移动
四、设置游戏规则
1、判断蛇是否撞击自己,如果撞击自己游戏就结束(调用gameover()函数,在程序外面定义gameover()函数,同时蛇的生命成员为1;
2、判断蛇是否撞击墙壁,如果撞击墙边游戏就结束(调用gameover()函数),同时蛇的生命成员为1;
3、判断蛇是否吃到食物,如果吃到食物,先把食物擦除,蛇长度加1,食物的判断变量food。
yes=1,分数加10,输出分数(调用显示分数函数printscore(),在程序外面定义printscore()函数);
判断蛇是否撞击自己
for(i=3;
i<
node;
i++)
if(snake。
x[i]==snake。
x[0]&
y[i]==snake。
y[0])
{
GameOver();
life=1;
break;
}
判断蛇是否撞击墙壁
判断蛇头坐标是否撞击墙壁
若撞击,调用GameOver();
并将蛇的状态设置为1
判断蛇是否吃到食物
判断蛇头与食物坐标是否相同
相同:
擦除食物
蛇的身体长一节
yes的状态
score增加10
输出新得分:
PrScore();
Gameover()函数
使用到的库函数:
cleardevice()
/*图形模式下清除屏幕上的内容*/
settextstyle();
/*设置图形模式下字符显示的字体、方向和大小*/
outtextxy();
/*图形模式下在x,y坐标位置显示一行字符串*/
Printscore()函数
用到的库函数:
setfillstyle(pattern,color);
/*设置填充模式和填充颜色*/
bar(left,top,right,bottom);
/*画矩形,并填充矩形内部区域*/用于分数的底色*/
setcolor(6);
/*用于分数的底色*/
settextstyle(0,0,2);
sprintf(str,“score:
%d”,score);
/*把要输出的字符转移给字符数组str(str要先定义)*/
outtextxy(55,20,str);
/*输出分数*/
Gameplay()
食物及蛇状态的初始化
Printscore()
while
(1)
判断是否需要出现食物
判断蛇是否撞击自己
判断蛇是否撞击墙壁
life==1)break;
判断蛇是否吃到食物
画出蛇,并使蛇运动
}/*endwhile(!
/*endwhile
(1)*/
第七章调试及测试结果与分析
调试(debugging)是指去掉程序中的错误(通常被称为bugs)的过程。
一个错误可能非常简单,例如拼错一个单词或者漏掉一个分号;
也可能比较复杂,例如使用一个指向并不存在的地址的指针。
无论错误的复杂程度如何,掌握正确的调试方法都能使程序员受益匪浅。
运行贪食蛇程序时会有多种原因使它不能运行,这些原因可以分为以下4种基本类型:
(1)程序中有死循环;
(2)程序运行的时间比所期望的长;
(3)程序在等待某些输入信息,并且直到输入正确后才会继续运行;
(4)程序设计的目的就是为了延迟一段时间,或者暂停执行。
在讨论了因未知原因而挂起的程序的调试技巧后,将逐个分析上述的每种情况。
调试那些因未知原因而不能运行的程序是非常困难的。
可能花费了很长的时间编写一个程序,并努力