已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
软件工程与开发实践1软件设计报告题 目 俄罗斯方块学 院计算机学院专 业 计算机科学与技术班 级 学 号 10109345学生姓名其他成员组 长指导教师孙志海完成日期2012年6月1、 软件设计概述(目的、任务、开发环境、参考资料) 俄罗斯方块游戏属于经典小游戏,游戏规则简单,但又不乏趣味。而计算的一大领域也是游戏,所以,成为游戏开发者,几乎是每个编程者的梦想。经过大一和大二的学习,我们已经掌握了编程基础。为了提高我们的编程能力,我们就要不断积累编程经验。1、 目的:复习和巩固C/C+编程的基本思想;掌握数据结构的核心思想;掌握C/C+中多文件的编写;初步对了解界面的设计。2、 任务:完成一个可以运行的游戏。3、 开发环境:C/C+控制台。4、 参考资料:1 谭浩强.C语言程序设计M.北京:清华大学出版社.2004.62 孙鑫余安萍.VC+深入详解M.北京:电子工业出版社.2006.6二、可行性研究、需求分析及分工 这是一个游戏软件,程序与用户的交流只在游戏界面上,方块的产生是随机的。3、 软件设计的基本原理和采用的主要方法与技术1、方块类型以下7大类 每一种方块都能够变形,所以在游戏中如何正确打印出方块的类型是重点,也是难点。我采用的是“相对坐标法”,具体实现参照“实现的过程与步骤”部分。 2、此游戏是简单的二维游戏,而且区域恒定不变,所以在存储游戏的信息时,二维数组是首选。用数组元素值模拟当前位置有无方块。3、 流程图如下 到达底部到达底部,游戏结束到达底部部结束销行操作生成下一个下坠物将新生的下坠物代替旧的“下一个下坠物“将旧的“下一个下坠物”用作当前 下坠物销行操作游戏结束处理下降一个单位开始 4、采用的方法在控制台下,光标是左到右,自上而下的,所以要要调用系统函数来控制光标。同理,为了界面的美观,也要调用系统函数进行颜色控制。5界面设置游戏的最大特点就是界面的美观,由此才能吸引玩家的兴趣,因此如何让界面尽最大限度美观,是每个游戏程序员努力的目标。这个程序是在VC环境下基于 C/C+控制台的,由于VC下没有像TC下那样丰富的图形库,画图就要调用windows API函数。但由于我对windowsAPI理解不深,所以画起图来还是比较困难。游戏不仅要求界面美观,而且还要音乐来衬托,所以在整个程序中,尽量让方块的每一个动作与特殊的音乐像对应,此外,最好加上背景音乐。4、 实现的过程与步骤数据结构:1、 方块的存储如下图所示,每一种方块都由四个小方块组成,可以按顺序编号、,在方块旋转、输出、擦出时,可以由第一个方块位置加上(减去)第二个与第一个的偏移量,从而找到第二个方块,如此可以方便遍历四个方块。 由于方块属于宽字符,故在占两个字节,输出的时候占两位。设号块的坐标为(x,y),那么第二块与它的偏移量的x=2,y=0,相对坐标即为(2,0)。同理,号方块的相对坐标为(2,1),号方块的坐标为(4,1),特别的, 号方块的相对坐标为(0,0),这样一来,只要知道每一种(7大类,19种)方块的号方块的坐标,就可以通过、方块与号方块的偏移量而逐个输出整个方块。明白了方块的输出,就要用一个数据结构存储方块了。19种方块都由4个小方块组成,在打印的时候最好能用一个4次的循环,这样代码也显得简单。综上以上两点,可以定义结构体typedef struct _VARY int vary_x4; int vary_y4;VARY;存储4个小块之间x,y坐标之间的相对偏移量。在定义变量的时候初始化成VARY vary = 0, 2, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, 0, 2, 2, 0, 0, 0, -1, -1, 0, -2, -2, -4,0 , 0, -1, -1, 0, 0, 2, 2, 0, -1, -1, -2, 0, 2, 2, 4, 0, 0, -1, -1, 0, 0, -2, -2, 0, -1, -1, -2, 0, 0, 2, 4, 0, -1, 0, 0, 0, 0, 0, 2, 0, -1, -2, -2, 0, 0, -2, -4, 0, -1, -1, -1, 0, 2, 2, 2, 0, 0, -1, -2, 0, 2, 4, 4, 0, 0, 0, -1, 0, -2, -2, -2,0, 0, -1, -2, 0, 0, 2, 4, 0, -1, -1, -1, 0, 0, 0, -2, 0, -1, -2, -2, 0 , 2, 4, 2 0, 0, 0, -1, 0, 0, 2, 0, 0, -1, -1, -2, 0, -2, 0, 2, 0, -1, -1, -1, 0, 0, -2, 0, 0, -1, -1, -2,;这样,7大类,共19中方块就全部存储了,在输出时只要用一个4次循环就可以了。 2、控制变形 变形 如图所示, 种方块经变形得到到种方块。那么如何才能根据种方块快速地找到种方块,这是关键。有方块的存储可以联想到,在这儿能不能也用相对坐标来存储呢?可以的! 如图所以,设种块的号小块坐标为(x,y),则种块的号小块坐标为(x+2,y-1),其相对偏移量为(2,-1)。这样一来在当方块变为方块时,只需把光标移动到点(x+2,y-1)处即可,然后可以通过一个4次循环,完整打印出方块。 明白了控制变形,就要设计数据结构。但是每一类方块通过变形产生的子类方块的目是不定的,如上类方块变形可生成两类,但是“山”字形方块变形,最多可产生4类,而“田”形的只有一类。所以在存储变形的相对位置时,还要将7大类方块变形产生方块的数目记下来。综上,可以定义如下结构体typedef struct _CONNECTION int sum; int connection_x5; int connection_y5;CONNECTION;其中,sum用来存储该类变形产生的方块数,connection_x5和connection_y5用来每一个子类与大类直接的相对位置。由于每一大类变形产生的子类数目不定,故用一个能容下最大量是数组。有了结构体的定义,可以具体定义变量CONNECTION connection = 2, -2, 2, 0, 1, 1, 0, 0, 2, 2, -2, 0, 0, 2, -2, 2, 0, 0, 4, -2, 0, 4, -2, 0, 0, -1, 1, 4, -4, 2, -2, 4, 0, 0, -1, 1, 4, -2, 2, 0, 0, 0, 0, 0, 0,;这样,在连续变形中,可以通过不断对sum去余而得到当钱方块形状。3、 用户界面的存储正如前面所说,俄罗斯方块是个二维游戏,所以很容易想到用二维数组存储界面信息。用数组元素和界面建立一一对应的关系,在游戏过程中会出现销行,所以,这就要存储当前位置有无方块,如果,为了界面美观,还要存储当前位置方块的颜色。综上,可以定义一下结构体:typedef struct _BOARD int x; int y; int color; bool having;BOARD;游戏的界面大小根据开发者自己定义,这儿用满格为15*25的区域,即定义界面面板BOARD board1525;主要函数1、 void choice_direction(int *prev_count)作用:实现上、下、左、右的选择。参数:旋转次数指针,用来记录当前方块旋转次数。 实现:根据_kbhit()函数判断当前有无按键,若无,则方块下降;若有,则用switch()判断是哪个键,根据键值修改跟踪方块的参数。2、void get_depth(int *pdepth)作用:计算当前方块可以下降的高度。参数:高度值。实现:由于每个方块有4个小方块,而且每个小方块的上下位置不一,而方块能够下降的高度,应该是最小高度,所以应该在4个值里面去最小值。3、 void check_boundary()作用:判断当前方块是否已处于左右边界。实现:同上,方块有4个小块,在判断是否到达边界时,四个小块都要判断。若没有触界,则处理左右按键引起的水平移动;若已处于边界,则对左右按键引起的参数值的改变进行复原。4、 void invilate()作用:方块到达底部后数据记录实现:根据方块的类型、坐标,对应对数组里面的个元素赋值,包括坐标点和颜色值已经状态量。5、 遇到的困难与获得的主要成果1、方块的存储和变形这个问题我想了好久。开始的时候我想着把19种方块分开了,但那样出现的问题就是:竖直下落的时候很简单,但是如果变形,新方块的位置怎么确定,鉴于这个问题,最初的方法还是放弃了。我用“相对偏移法”的灵感来自于指针和寻址。在存储的时候,第一方块的位置就相当于是基“地址”,而后面的3个小块都可以通过加上一个相对值来找到,这与指针和相对寻址不是很相似吗?2、 判断有误按键开始的时候给按键开了一个进程,用来判断有误按键。但是那样也有个不足的地方,每一种进程执行的时间长度是随机的,如果不对每个进程进行控制,就会出现“在输出四个小块的时候,值输出了前两个小块,CPU就转向判断有误按键了,而如果这时恰好有按键,而且是水平位移键,出现的结果就是部分小块在左端,部分小块在右端”的情况,很显然,这是绝对不可以的。之前我不知道有_kbhit()这个函数,我也是在阅读别人的代码时发现这个函数的。有了这个函数,就不用开线程了,也不用去控制线程了,程序简洁多了。3、 获取方块可以下落的高度如前面函数声明里所说,方块下落的高度要去最小值。但是随着水平按键,导致方块的左右移动,方块能够下降的高度随时都在变。也可以用另一个线程获取下降高度,但不好的情况和用线程判断按键类似,所以我的处理就是在每一次方块的位置改变时,都调用获取高度的函数。4、 方块的下落 方块下落的高度有获取高度函数确定。但是会有一种极端情况出现,如下所示: 方块道道第3列上方时,它能下降的高度已经是0,但是如果在它到到第3列上方,随后立即按了水平右移键,那么,它能下降的高度至少是4,而不是0。因此一味得说能下降的高度是0时,它就停止下降,显然是不对的。下降高度是0时,下降函数就马上执行完了,至少是跳出了下降循环,所以就要想办法,在在下降函数执行马上结束时,再一次判定它的能够下降的高度,如果高度不是0,那就再次调用下降函数(它自己),也就是递归,如果下降高度还是0,那么这个方块就落到底部了。采用这种方法可以很好的解决在水平移动时的类似问题。但是这种方法也有个不足就是,如果当方块已经到底了,这时仍然按了水平移动键,而此时,它又满足水平移动的要求,那么他就反复递归了,递归栈越来越深,只有累计时间溢出时,下一个方块才能落下。5、 多文件编写以前写程序都是一main到底,多文件的。初次试着用多文件编写,遇到的主要问题是全局变量的存放。 在多文件编写中,变量,尤其的全局变量的定义和引用显得不那么精简。很多人可能会想,把全局变量放在一个*.h文件中,然后在以后的调用中只要include一下不就可以了?想想也有道理,include不就是把*.h原封不动的复制过来吗?但是,这样存在一个问题。加入定义了10个全局变量,而在具体一个*.c文件中我只用其中一个。如果用include把全局变量全都包含进来。那利用率不就才是10%吗。而且C语言常用于嵌入式,如果每个文件都include一个全局变量头文件,那么这些变量就被分配 一次内存,这对嵌入式来说肯定是致命的;另外,如果有很多个文件都include了全局变量的头文件,编译器要跟踪每一个文件对其中一个变量的更改,这对编译器来说也是吃不消的。 所以便有了*.c和*.h的区别。 很多人都知道声明和定义的区别一个分配内存,一个不分配内存,而且函数的声明和定义更是显而易见,但是对于变量的声明和定义,就显得有些模糊不清。由于如上所述的种种原因,C语言中全局变量放在*.c文件,而不放在*.h文件。这样一来,*.h文件好像无用武之地了,非也。我们经常见到#include *.h,但有谁见过#include *.c吗?所以*.h文件用来声明,*.c文件用来实现,在调用处用extern声明。 1、普通变量定义成全局变量 如果是普通类型,完全可以不用*.h文件,直接在*.c文件中定义,在调用文件处用extern 声明,因为对于普通类型,编译器是可以识别的。比如在一个 my.c文件中,我定义了char name10;那么在别的文件中只要用extern char name(由于是声明,一位数组可以省略大小,但不建议用指针,比较指针和数组是两回事)外部声明就可以了,告诉编译器这个变量我已经定义过了,具体怎样,你慢慢找吧。这符合常理,因为char是编译器能自主识别的类型。 2、自定义结构体类型定义成全局变量 不同于普通类型,如果不预先通知编译器,编译器是不会识别你自定义的类型的。这个时候,*.h文件便出现了。不是定义结构类型不占内存吗?那好,我大结构体的定义放在*.h文件中,这样一来,无论你incude无数次,内存都不会被占用的。而且这样还有个好处,在别的文件中可以include这个*.h文件,这样,在这个文件中,编译器就可以识别你的自定义类型了,目的不就达到了? 假如我在global.h中定义了typedef struct _POSITION int x; int y;POSITION;那么我可以在一个global.c文件中实现全局变量的定义,不过要include那个*.h文件,比如/* *global.c * */ include “global.h”POSITION current; 这样就定义了cunrrent这个变量,在别的文件中引用这个变量时,只要extern POSITION current;进行声明,然后就可以用了,不过这个文件也还得include global.h 因为如果不包含,在这个文件中是不识别POSITION类型的。 所得:首先,在整个程序中,我决定最大的两点在于那两个结构体的定义,我想,这才是我们学习数据结构的意义。学习数据结构,不是让我们写一个堆栈或者是链表,而是要学会分析,将问题抽象提炼出来,根据问题自己定义一个结构。然后,在这个程序中,好几个系统函数都是我在阅读别人代码时看到的,由此可见交流的重要性。最后,分析问题一定要严谨,在这个调试这个程序的时候,就在水平移动、落地的时候,出现过很多bug,我也是费了好久才调试过来,所以,分析问题一定要严谨。6、 测试与运行记录 程序测试结果良好,但不能排除bug的可能。程序第一次执行时会出现 用于选择保存成绩的路径,界面,因为此后程序在运行时,都要打印当前的最高分,所以就要把每一次的最好分存储起来,程序下次运行时,直接从这个文件中读取最高分。存储分数路径选择好后,接着会出现界面,一个简单的启动画面,只需按任意键即可进入游戏。游戏界面如下,左面为游戏主界面,右面有三行,第一行 用于显示下一个方块;第二行用于显示当前用户的得分,已经在这台PC机上的最高分;第三行是游戏说明以及作者信息。 7、 结果分析与小结 在统计分数时,一次销的行越多,得到分数越多。一次1行的1分;一次两行的3分;一次3行的6分;一次4行得10分。在级数统计时, 1,20)为一级;20,50)为二级;50,90)为三级;9
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 水电工程安全协议样本
- 长期汽车销售购销合同
- 建设银行个人贷款合同
- 墙体涂料工程分包合同
- 新版购销合同的条款列举
- 茶叶物联网应用合同
- 废料买卖合同协议
- 临时兼职合同书
- 债权债务转让协议法律分析
- 程序员保密协议的案例解析
- 模具开发FMEA失效模式分析
- 年产40万吨灰底涂布白板纸造纸车间备料及涂布工段初步设计
- 1-3-二氯丙烯安全技术说明书MSDS
- 学生思想政治工作工作证明材料
- 一方出资一方出力合作协议
- 污水处理药剂采购投标方案(技术方案)
- 环保设施安全风险评估报告
- 数字逻辑与计算机组成 习题答案 袁春风 第3章作业批改总结
- 要求降低物业费的申请书范本
- 焊接机器人行业分析研究报告
- PI形式发票范文模板
评论
0/150
提交评论