首页 案例分析-开发综合程序

案例分析-开发综合程序

举报
开通vip

案例分析-开发综合程序 案例分析-开发综合程序 经过基本的编程训练后,我们已经能编写解决小问题的程序,对程序的开发也有了初步 的认识,还掌握了 C语言的基本语法,这一过程确确实实令我们感到欣喜,有点计算机可以 完成自我任务的成就感。但是,对于程序设计而言,学习 C的步伐不应该停留于此。我们最 终的目的应该是掌握开发大型综合程序的方法,即遵循软件工程的开发步骤和结构化程序设 计思想,用 C语言开发出解决复杂问题的大型综合程序。 首先介绍软件工程的概念,然后通过一个具体的案例讲述如何在综合程序的开发中应用 软件工程的思想和方法。 ...

案例分析-开发综合程序
案例 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 -开发综合程序 经过基本的编程训练后,我们已经能编写解决小问题的程序,对程序的开发也有了初步 的认识,还掌握了 C语言的基本语法,这一过程确确实实令我们感到欣喜,有点计算机可以 完成自我任务的成就感。但是,对于程序 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 而言,学习 C的步伐不应该停留于此。我们最 终的目的应该是掌握开发大型综合程序的方法,即遵循软件 工程 路基工程安全技术交底工程项目施工成本控制工程量增项单年度零星工程技术标正投影法基本原理 的开发步骤和结构化程序设 计思想,用 C语言开发出解决复杂问题的大型综合程序。 首先介绍软件工程的概念,然后通过一个具体的案例讲述如何在综合程序的开发中应用 软件工程的思想和方法。 1 软件工程........................................................................................................................ 1 1.1 软件工程的定义....................................................................................................................1 1.2 传统的生命周期方法学........................................................................................................1 2 综合程序的开发流程...................................................................................................................2 2.1 问题定义................................................................................................................................3 2.2 程序分析................................................................................................................................3 2.3 程序设计................................................................................................................................4 2.3.1 结构化程序设计方法.....................................................................................................4 2.3.2 设计工具.........................................................................................................................6 2.2.3 扫雷游戏的设计.............................................................................................................8 2.4 编码......................................................................................................................................16 2.4.1全局变量........................................................................................................................17 2.4.2 函数...............................................................................................................................17 2.4.3 风格...............................................................................................................................17 2.4.4 扫雷游戏的源程序.......................................................................................................21 2.5 测试和调试..........................................................................................................................29 2.5.1 调试...............................................................................................................................29 2.5.2 测试...............................................................................................................................30 2.6 运行与维护..........................................................................................................................34 2.7 分工协作..............................................................................................................................34 小结 ................................................................................................................................................35 1 1 软件工程 软件工程是随着软件的发展而诞生的一门学科。我们现在都知道软件由程序、数据和 文档组成,其中程序是主体,数据是使程序能正常操纵信息的数据结构,文档是与软件的开 发、维护和使用有关的材料。然而这一概念的形成却经历了三个阶段:第一阶段是在计算机 系统发展的早期时代,即 60年代中期以前,由于硬件非常昂贵、运算速度低、内存容量少, 造成这时的软件就是规模较小的程序,需求者和编写者往往是同一个人,他们强调“程序设 计技巧”以节省存储单元和 CPU 时间,写出的程序只要能在计算机上的除正确的结果,程 序的写法可以不受任何约束,这些程序很难被别人看懂。这种个体化的软件环境,使得软件 设计通常是在人们头脑中进行的一个隐含的过程,除了程序清单之外,没有其它文档资料保 存下来;第二阶段是从 60年代中期到 70年代中期,随着计算机硬件的发展和应用的日益普 及,这个时期的一个重要特征是出现了“软件作坊”,但是基本上仍然沿用早期形成的个体 化软件开发方法,此时的软件包含程序及简单的说明书。可是当软件数量急剧膨胀时,“软 件危机”爆发了,所谓软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重 问题,如对软件开发成本和进度的不准确估计造成的超预算、拖延、甚至半途而废;软件产 品的质量往往靠不住;软件常常是不可维护的,包括程序中的错误难以改正、难以适应新的 软硬件环境的变化和无法扩展等;软件成本在计算机系统总成本中所占比例逐年上升;软件 开发生产率远远落后于计算机应用迅速普及深入的趋势,造成软件产品“供不应求”。为了 探讨如何解决软件危机问题,1968 年北大西洋公约组织的计算机科学家在德国召开了国际 会议,在该会议上正式提出并使用了“软件工程”这个名词,一门新兴的工程学科就此诞生 了;第三阶段也称为软件工程阶段,约从 70年代至今,软件工作的范围从只考虑程序编写 扩展到涉及整个软件生存期,软件包括程序、数据和文档,软件开发的成果具有社会属性, 它要在市场中流通以满足广大用户的需要,软件开发者和用户的分工和责任是十分清楚的。 开发者应该尽可能地实践软件工程,以生产出高质量的软件。 1.1 软件工程的定义 虽然有很多软件工程的定义,但 Fritz Bauer在 1968年北大西洋公约组织的该主题的奠 基性会议上给出的定义仍是进一步展开讨论的基础: 软件工程是建立和使用一套合理的工程原则,以便获得经济的软件,这种软件是可靠的, 可以在实际机器上高效地运行。 IEEE给出了一个更全面的定义: 软件工程是:(1) 将系统化的、严格约束的、可量化的方法应用于软件的开发、运行和 维护,即将工程化应用于软件。(2) 在(1)中所述方法的研究。 更进一步地说,软件工程视软件的开发是一项工程,它借鉴传统工程的原则、方法,使 经过时间考验而证明是正确的管理方法和当前能够得到的最好的开发技术结合了起来,以提 高质量、降低成本为目的。 1.2 传统的生命周期方法学 一个软件从定义、开发、使用和维护,直到最终被废弃,要经历一个漫长的时期,这就 如同一个人要经历胎儿、儿童、青年、中年、老年,直到最终死亡的漫长时期一样。通常把 软件经历的这个漫长的时期称为生命周期。软件工程强调使用生命周期方法学和各种结构分 析及结构设计技术。它们是在 70 年代为了对付应用软件日益增长的复杂程度、漫长的开发 2 周期以及用户对软件产品经常不满意的状况而发展起来的。人类解决复杂问题时普遍采用的 一个策略就是“各个击破”,也就是对问题进行分解然后再分别解决各个子问题的策略。 软件工程采用的生命周期方法学就是从时间角度对软件开发和维护的复杂问题进行分 解,把软件生命的漫长周期依次划分为若干个阶段,每个阶段有相对独立的任务,然后逐步 完成每个阶段的任务。前一个阶段任务的完成是开始进行后一个阶段工作的前提和基础,而 后一阶段认为内务的完成通常是使前一阶段提出的解法更进一步具体化,加进了更多的实现 细节。在每一个阶段结束之前都必须进行正式严格的技术审查和管理复审,若检查通不过, 则必须进行必要的返工,返工后还要再经过审查。审查的一个主要 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 就是每个阶段都应该 提交和所开发的软件完全一致的高质量的文档资料,从而保证再软件开发工程结束时有一个 完整准确的软件配置交付使用。文档不仅是前后阶段的通信工具,而且是软件交付使用后进 行维护的依据。所以,采用生命周期方法学或称传统的软件工程方法,就使软件开发工程的 全过程以一种有条不紊的方式进行,保证了软件的质量,特别是提高了软件的可维护性。 一般来说,软件生命周期由软件定义、软件开发和软件维护三个时期组成,每个时期又 进一步划分成若干个阶段。软件定义时期的任务是确定软件开发工程必须完成的总目标;确 定工程的可行性;导出实现工程目标应该采用的策略及系统必须完成的功能;估计完成该项 工程需要的资源和成本,并且制定工程进度表。这个时期的工作通常又称为系统分析。这一 时期通常进一步划分成三个阶段,即问题定义、可行性研究和需求分析。 时 期 阶 段 关键问题 问题定义 问题是什么? 可行性研究 有可行的解吗? 问题定义 需求分析 系统必须做什么? 总体设计 概括地说,应该如何解决这个问题? 系 统 设计 详细设计 怎样具体地实现这个系统? 编码和单元测试 正确的程序模块 开发 系 统 实现 综合测试 符合要求的软件 维护 维护 持久地满足用户需要的软件 表 2-1 软件生命周期每个阶段及其解决的关键问题 开发时期具体设计和实现在前一个时期定义的软件,它通常由下述四个阶段组成:总体 设计,详细设计,编码和单元测试,综合测试。其中前两个阶段又称为系统设计,后两个阶 段又称为系统实现。 维护时期的主要任务是使软件持久地满足用户的需要。具体地说,当软件在使用过程中 发现错误时应该加以改正;当环境改变时应该修改软件以适应新的环境;当用户有新要求时 应该及时改进软件以满足用户的新需要。每一次维护活动本质上都是一次压缩和简化了的定 义和开发过程。表 2-1 列出了软件生命周期每个阶段及其解决的关键问题。 下一节,针对如何用 C 开发出一个大型综合程序这个主题,我们将从“软件工程”的 角度详细介绍开发综合程序的方法和流程。 2 综合程序的开发流程 从上一节中,我们已了解到编码只是软件开发的一个阶段,而且是处在实现阶段。对 于 C 语言的初学者,由于没有正式接受系统化开发方法的指导,往往会形成一个错误的认 识:程序的开发就是编码。也就是说,拿到问题后,马上就开始写程序。这种做法的不良后 3 果初学者无法体会到,是因为他们所面临的需要解决的问题,无论从规模而言,还是从难易 程度而言,实在是太小了。所以在直接编写程序的过程中,大脑已经让初学者无意识地完成 了问题的定以和设计过程。但是,这种侥幸的“个体化”做法对于复杂的现实问题的解决是 绝对行不通的。虽然目前我们还谈不到软件项目的开发,但是相对初学阶段,我们已经可以 解决较为复杂的问题了,即进入综合程序的阶段,因此,必须从现在开始,树立正确的开发 观,为今后专业化开发打好基础。 遵循软件的开发流程,大型综合程序的开发经历问题定义、分析、设计、编码、测试 和维护几个阶段。 2.1 问题定义 问题定义阶段是整个过程中占用时间最少的阶段,在这个步骤中我们的任务是明确要 解决的问题是什么。如果不知道问题是什么就试图解决这个问题,显然是盲目的,只会浪费 时间和金钱,结果是毫无意义的。 在综合程序训练时期,欲解决的问题可由教师提供,或者由学生自行选题。假若是后 者,那么学生必须动动脑筋,寻找身边有哪些事情可用计算机解决,然后确定一个可行的。 例如,某位同学非常熟悉 Windows 系统中自带的扫雷游戏,于是他以此为题,即自己实现 一个类似功能的扫雷游戏。 2.2 程序分析 这个阶段的任务仍然不是具体地解决问题,而是理解问题和分析问题,确定“为了解 决这个问题,目标系统必须做什么”,主要是确定目标系统必须具备哪些功能。除此之外, 还要确定可能的输入或输出数据是什么。 我们在问题定义步骤中得到的问题,有时仅仅是一个抽象的题目,有时除题目外还附 一段简要说明。无论问题以何种形式出现,都需要做进一步的分析,以获得解决问题的计算 机系统必须实现哪些功能。下面我们以扫雷游戏为例,看看如何分析问题。这通过两步来完 成:首先必须对 Windows 系统中的扫雷游戏进行了解,然后确定我们将实现的扫雷系统要 做什么。 通过亲身体验或其它交流手段,可获知这个游戏是在屏幕显示的一个雷区范围内(如 图 2-1(a)所示),系统预先埋设了一定数目的地雷(图 2-1(a)中笑脸左侧小窗显示的数字), 游戏者在游戏过程中通过判断,若能正确标记出雷区中的所有地雷,则游戏胜利(如图 2-1(b) 所示);否则踩雷,游戏失败(如图 2-1(c)所示)。具体的游戏规则如下: 1) 在“游戏”菜单上,单击“开局”,出现图 2-1(a),其中包括地雷计数器窗口、计 时器窗口和雷区。开局后,单击雷区中的任何一个方块,便启动计时器。每标记 一个地雷,地雷计数器减 1; 2) 用鼠标左键单击某个方块,可挖开它。若所揭方块下有雷,则踩雷,即所有含地 雷的块都标记Å,这局游戏失败;如果方块上出现数字,它代表在它周围的八个 方块中共有多少颗地雷; 3) 用鼠标右键单击某个方块,则标记此块下埋着地雷(实际上可能是误标),显示为 。每标记一个地雷,地雷计数器减 1; 4) 用鼠标右键击打某个方块两次,则在某块上面标一个问号(?),意味着没有把握判 定它是否有雷。标记为?的块可在恰当的时候再击打鼠标右键两次或单击左键, 将其标记为地雷或挖开; 5) 如果某个数字方块周围的地雷全都标记完,可以同时单击鼠标左右键,将其剩下 的方块挖开。如果挨着这个方块的地雷没有全部标记完,则未挖开的方块将闪烁。 4 通过分析上述游戏规则,抛开 Windows 扫雷游戏中界面显示、鼠标操作等非本质的东 西,我们从Windows扫雷游戏中提取的主要功能包括:规则 1)隐含初始化新游戏的开局功 能,规则 2)隐含的挖雷功能,规则 3)对应的标记地雷功能,规则 4)对应的标记疑问功 能,规则 5)的自动挖开功能。另外,我们还可以看到游戏的输入是启动这些功能的指示信 息,通过鼠标左右键的操作来表达;游戏的输出是游戏是否成功。 我们所要实现的扫雷游戏正是Windows扫雷游戏的模仿版,也就是说能够实现Windows 扫雷游戏的主要功能,因此,我们的目标系统必须具备:开局功能、挖雷功能、标记雷功 能、标记疑问功能、自动挖开功能。到这里,程序分析的工作就结束了。接下来,将进入 下一阶段——程序设计——的工作。 2.3 程序设计 著名计算机科学家 Nikiklaus Wirth 提出了公式:程序=算法+数据结构,这一公式反映 了程序的两个要素:算法和数据结构,实际上,程序还应当有另外两个要素:程序设计方法 和语言工具。这四个方面是一个程序设计人员所应具备的知识。算法是灵魂,数据结构是加 工对象,语言是工具,程序设计需要好的设计方法。 经过程序分析阶段的工作,综合程序必须“做什么”已经清楚了,现在是决定“怎样 做”的时候了,也就是到了设计算法和重要数据的数据结构的时候了。程序这个阶段的设计 工作,应该对要解决的问题设计出具体的解决方案,得出对目标系统的精确描述,从而在编 码阶段可以把这个描述直接翻译成用 C语言书写的程序。 当然,程序设计将采用结构化程序设计方法,自顶向下逐步求精地设计出综合程序的 实现“蓝图”。为此,我们首先介绍结构化程序设计方法,然后列举描述算法的常用工具, 接着仍以扫雷游戏为例,详细说明设计阶段的工作和结构化程序设计方法的应用,最后谈谈 合作情况下如何分工协作的问题。 2.3.1 结构化程序设计方法 结构化程序设计的概念最早由 E.W.Dijkstra提出。在软件发展的早期,程序员追求效率 第一,在程序中滥用 GOTO 语句,程序的控制流程时而 GOYO 过来,时而 GOTO 过去, 把程序的逻辑拧成一团乱麻,造成程序难于阅读和理解,有人称这种的可读性非常差的程序 为“一碗意大利细面条”(bowl of spaghetti,简称 BS程序),“剪不断,理还乱”。在这种局 面下,1965年 Dijkstra在一次会议上指出:“可以从高级语言中取消 GOTO语句”,“程序的 质量与程序中所包含的 GOTO语句的数量成反比”。1966年 Böhm和 Jacopini证明了:“任 何程序的逻辑均可用顺序、选择和循环这三种控制结构或它们的组合实现”,这一证明奠定 图 2-1 Windows扫雷游戏 (a)开局 (b)胜利 (c)失败 5 了结构化程序设计的理论基础。1968 年 Dijkstra 再次建议从一切高级语言种取消 GOTO 语 句,只使用三种基本控制结构写程序。他的建议引起了了一番激烈的争论,最后终于得出了 “GOTO语句必须限制使用”的一致结论。这场讨论改变了许多人单纯强调程序效率的旧观 念,除少数使用特频繁或对执行时间有严格要求的实时程序,大多数情况下,应该优先考虑 程序的清晰度。这场讨论使人们认识到,不是简单地去掉 GOTO 语句的问题,而是要创立 一种新的程序设计思想、方法和风格,以显著提高软件生产率和降低软件维护代价。1972 年 IBM公司的Mills进一步提出,“程序应该只有一个入口和一个出口”,从而补充了结构化 程序设计的规则。 那么,什么是结构化程序设计呢?结构化程序设计是一种设计程序的技术,它采用自 顶向下逐步求精的设计方法和单入口单出口的控制结构。 自顶向下逐步求精的设计方法符合人类解决复杂问题的普遍规律,这种设计方法的过 程是将问题求解由抽象逐步具体化的过程。例如,设计房屋就采用了这种方法,先进行整体 规划 污水管网监理规划下载职业规划大学生职业规划个人职业规划职业规划论文 ,然后确定建筑物方案,再进行各部分的设计,最后进行门窗、楼道等的细节设计。在 制定问题的算法时同样也能采用这种方法,例如,考虑如下的问题描述: 某学院为准备参加省举办的财产经纪人资格考试的学生开办了一门课程。去年,几个学 完该门课程的学生参加了这门课程的考试。学院自然想知道这些学生考的得怎样。现在要你 编写一个统计考试结果的程序,能够显示出通过和没有通过的人数,并且如果通过人数超过 8人,显示提高学费的决定。已知参加考试的学生有 10 名,并且已经在通过考试的学生名 字旁边注上了 1,在没有通过考试的学生名字旁注上了 2。程序必须要处理 10 个学生的考试 结果,所以要使用循环 2) 每个考试结果都是一个数,即 1 或 2。程序每次读取一个测试结果后,必须确定 该数是 1还是 2。 3) 使用两个计数器。一个用于计算通过考试的学生人数,另一个用于计算没有通过 考试的人数。 4) 程序处理完所有结果后,必须判断是否有 8个以上的学生通过了考试。 自顶向下逐步求精的方法解决这个问题。问题的顶层表示为: Analyze exam result and decide if tution should be raised顶层是程序功能的完整的表述。 第一次求精结果为: Initialize variables Input the ten quiz grades and count passes and failures Print a summary of the exam results and decide if tuition should be raisedfailures记录通过和没有通过 考试的人数,还要用一个计数器 student控制循环过程,还需要用一个变量来存储用户的输 入。这样,对语句 Initialize variables可做如下的求精: Initialize passes to zero Initialize failures to zero Initialize student to one failures和 student。语句 Input the ten quiz grades and count passes and failures需要一个循环结 构来实现,并在每次循环时输入一个学生的考试成绩。在循环体内要用双路选择结构确定学 生是否通过了考试,然后再递增相应计数器的值。该求精结果为: While student counter is less than or equal to 10 Input the next exam result If the student passed Add 1 to passes else Add 1 to failures 6 Add one to student counter第一次求精的最后一条语句 Print a summary of the exam results and decide if tuition should be raised可做如下求精:Print the number of passes Print the number of failures If more than 8 students passed Print “Raise tuition”经过二级求精后得到的算法描述(完整的二级求精过程见图 2-2),已详细到可将它转换为 C 程序(如图 2-3 所示),这时,我们的自顶向下逐步求精过 程结束。 上述的问题非常简单,而对于大型综合程序的复杂问题来说,需要更多步的求精过程来 进行设计。程序设计阶段又可细分为两个子阶段,第一个子阶段称为总体设计阶段,采用自 顶向下逐步求精方法,可以把一个复杂问题的解法分解和细化成一个由许多模块组成的层次 结构,即问题模块化,得到整个程序的总体结构。在这个阶段必须确定全局数据的数据结构 和模块间的借口;第二个子阶段称为详细设计阶段,采用自顶向下逐步求精方法,可以将每 个模块的功能逐步分解细化为一系列具体的处理步骤,即该子阶段制定出模块结构化算法的 详细描述和模块内的局部数据结构。 我们应当掌握自顶向下逐步求精的设计方法。采用结构化程序设计方法进行程序设计, 可以使设计思路清晰,便于验证算法的正确性,在向下一层展开之前应仔细检查本层设计是 否正确,只有上一层是正确的才能向下细化。如果每一层设计都没有问题,则整个算法就是 正确的。由于每一层向下细化时都不太复杂,因此容易保证整个算法的正确性。检查时也是 由上而下逐层检查,这样做,思路清楚,有条不紊一步一步进行,既严谨又方便。 2.3.2 设计工具 在理想情况下,设计的描述应该采用自然语言来表达,不熟悉软件的人不需要重新学 习就可以理解。但是,自然语言在语法和语义上往往具有多义性,常常要依赖上下文才能把 问题交代清楚,而且即使可以描述,也需要大量的篇幅,非常烦琐。所以必须使用简洁的方 式表达整体结构,用约束性强的方式来表达算法。设计工具可以对设计进行无歧义的描述, Initialize passes to zero Initialize failures to zero Initialize student to oneWhile student counter is less than or equal to 10 Input the next exam result If the student passed Add 1 to passes else Add 1 to failures Add one to student counter Print the number of passes Print the number of failures If more than 8 students passed Print “Raise tuition” 图 2-2 #include main() { int passes = 0; int failures = 0; int student = 1; int result; while ( student <= 10) { printf (“Enter result (1=pass, 2=fail): ”); scanf (“%d”, &result); if ( result == 1) ++passes; else ++failures; student += 1; } printf(“Passeds %d \n”, passes); printf(“Failed %d \n”, failures); if ( passes > 8 ) printf(“Raise tuition \n”); return 0; } 图 2-3 7 能指明控制流程、处理功能以及其它方面的实现细节。俗话说“千言万语抵不过一幅画”, 下面的三种常用工具是图形方式的工具。 层次图用来描述软件的层次结构,图中的一个矩形框代表一个模块,方框间的连线表示 调用关系。图 2-4中最顶层的方框代表正文加工系统的主控模块,它调用下层模块完成正文 加工的全部功能;第二层的每个模块控制完成正文加工的一个主要功能,例如“编辑”模块 通过调用它的下属模块可完成六种编辑功能中的任何一种。层次图很适合于在自顶向下设计 软件的过程中使用。 程序流程图是历史最悠久使用最广泛的描述软件设计的方法。它的主要优点是对控制流 程的描述很直观,便于初学者掌握,但这种用箭头代表控制流的方法,容易使程序员不受任 何约束,可以完全不顾结构化程序设计的精神,随意转移控制。另外,程序流程图不易表示 数据结构。所以这一本质上不是逐步求精的工具,许多人建议停止使用它,而且总趋势亦是 如此。图 2-5显示了用程序流程图表示的结构化三种结构。 盒图(如图 2-6所示)是一种很好的支持结构化程序设计思想的图形工具,也称为 N-S 图。盒图上能明确表达功能域,不可能任意转移控制,很容易确定局部和全局数据的作用域, 很容易表现嵌套关系,而且也可以表示模块的层次结构。所以坚持使用盒图作为设计的工具, 可以使程序员逐步养成用结构化的方式思考问题和解决问题的习惯。 输入 正文加工系统 输出 编辑 加标题 存储 检索 编目录 格式化 添加 删除 插入 修改 合并 列表 图 2-4 正文加工系统的层次图 图 2-5 结构化控制结构的程序流程图表示 8 图形工具表示设计确实比较直观,但画起来比较费劲,所以描述设计还可以使用伪码这 个常用的语言工具。伪码是一种“混合”语言,它使用一种语言——通常是某种自然语言— —的词汇,同时却使用某种结构化程序设计语言的语法。这样,它具有严格的关键字外部语 法,而表示实际操作和条件的内部语法又是灵活自由的,书写方便,也比较好懂。图 2-2正 是考试统计问题算法的伪码表示。 除了图形工具、语言工具外,还有如判定表的表格工具,关于设计工具的进一步介绍感 兴趣的同学可参考其它文献。 2.2.3 扫雷游戏的设计 扫雷游戏的输赢规则为挖开一个含有雷的方块,游戏失败;正确的标记出所有含有雷的 方块,游戏胜利。在 2.2.2我们已经分析出扫雷游戏的目标和主要的功能,即根据输入的信息, 执行相应的诸如挖雷、标记雷、标记疑问、自动挖开等功能,以期在尽快的时间内标识出开 局时所埋设的所有地雷。但是,这仅仅是程序层次结构中最上层的部分(如图 2-7 所示): 划分的功能比较抽象,需要进一步的精化;与系统实现的其它相关细节还是空白,需要进一 步完善,从而逐渐逼近最后的实现。 现阶段的设计任务是自顶向下逐步求精,具体要完成以下几点: ♦ 继续分析已有功能,直到精化出所有子功能,确定出模块间接口; ♦ 描述精化后每个模块的处理过程; 图 2-6(b) 盒图的应用实例 图 2-6(a) 盒图的基本符号 开局 扫雷游戏系统 输入 挖雷 标记雷 标记疑问 自动挖开 输出 图 2-7 扫雷系统的顶层层次图 9 ♦ 确定主要的数据及其数据结构; ♦ 确定输入输出数据的内外部形式; ♦ 界面的设计 以下将展示我们是如何进行扫雷游戏的设计的。 1) 确定游戏的界面。在此我们的设计非常简单,没有 Windows 应用系统的风格。只 在中部显示由小方块组成的雷区,小方块的背景显示为浅灰,表示该方块没有被挖开或标记; 小方块的背景显示为深灰,表示它已经被挖开或标记为“F”、“?”或“*”;当选中一个方块 要操作时,它的边框线为红色。在屏幕的左上方显示游戏是否成功等信息,这也是游戏结果 的表现形式。如图 2-8所示。 2) 决定游戏的输入方式。Windows系统中的扫雷游戏是采用鼠标作为操作手段的,我 们对自己实现的系统决定采用键盘,即通过光标的移动来选择操作的小方块,根据所敲击的 键值来选择游戏的功能,这样需要定义功能键。下面是我们对键盘功能键的定义: 上,下,左,右键用来移动光标的位置; 回车或者空格键用来挖开光标当前指向的一个方块; F, f 标记当前光标指向的方块有地雷; Q, q 在光标指向方块打一个问号,表示可能有地雷; A , a 自动挖开光标周围的方块; ESC 退出游戏。 3) 确定主要的数据,这里主要是有关雷区的数据。 ♦ 雷区界面数据 # define ROW 16 /* 表示整个雷区的行数*/ # define COL 16 /* 表示整个雷区的列数*/ /*这样可通过光标位置(i,j),i∈[0,ROW-1],j∈[0,COL-1]来代表雷区中相应的小方块*/ # define STARTX 50 /* 表示雷区在屏幕上的起始 x坐标*/ # define STARTY 50 /* 表示雷区在屏幕上的起始 y坐标*/ # define SIZEX 20 /* 表示一个方块的长度*/ # define SIZEY 20 /* 表示一个方块的宽度*/ 图 2-8 扫雷游戏的界面 10 ♦ 雷区内部数据 int totalMine; /* 整个雷区所含的地雷总数*/ int table[ROW][COL]; /* 数组 table 的每个元素值记录了雷区对应方块是否有雷:1表示有雷,0 表示没有雷*/ int num[ROW][COL]; /* 数组 num 的每个元素值记录了雷区对应方块周围有多少个地雷*/ int flag[ROW][COL]; /* 数组 flag 的每个元素值记录了雷区对应方块当前的状态*/ 在整个系统中 table[ROW][COL]、num[ROW][COL]、flag[ROW][COL]是最核心的数据, 是雷区的内部表示,游戏的挖雷、标记雷、标记疑问、自动挖开等界面操作,在内部实际上 是对这些数据的操作。 ♦ 方块(i,j)的状态取值: #define UNFLAG 0 /* 表示该方块还没有被打开或者标记*/ #define FLAGED 1 /* 标记该方块有地雷*/ #define QUESTION 20 /* 表示该方块可能有地雷*/ #define EXPLOD 30 /* 踩到地雷爆炸了*/ #define OPEN 40 /* 一个没有地雷的方块被打开*/ ♦ 光标当前位置数据 int pi,pj; /* 记录光标的当前位置,初始时光标在(0,0)上*/ int di[8]={-1,-1,0,1,1,1,0,-1}; int dj[8]={0,1,1,1,0,-1,-1,-1}; /*相对于当前方块而言,di[8]和 dj[8]分别表示了它周围八个方块的行和列坐标偏移量。它们 与当前光标坐标配合使用,可表示周围的方块,如(-1+pi,0+pj)表示当前方块的正上方方 块的坐标。*/ ♦ 游戏状态数据 int gameRes; /*记录游戏结束的结果状态,值为 0表示按 esc键退出游戏;-1 表示游戏失败;gameRes = 1 表示游戏胜利。实际为输出数据的内部形式*/ ♦ 功能键的键值 /*上,下,左,右键*/ #define UP 0x4800 #define DOWN 0x5000 #define LEFT 0x4b00 #define RIGHT 0x4d00 /*回车、空格键*/ #define ENTER 0x1c0d #define SPACE 0x3920 /*F, f */ #define UPPERF 0x2146 #define LOWERF 0x2166 11 /*Q, q*/ #define UPPERQ 0x1051 #define LOWERQ 0x1071 /*A , a*/ #define UPPERA 0x1e41 #define LOWERA 0x1e61 /*ESC*/ #define ESC 0x011b /*为了避免书写错误和明确含义,对系统的按键值用符号常量来定义*/ 4) 功能求精 实际上,除了图 2-7的主要功能外,我们已经得出我们以图形方式显示游戏界面,而在 C系统中屏幕的输出默认的方式是文本方式,所以需要首先将显示方式设置为图形方式。所 以到目前为止,可以非常容易地确定出程序主控模块的流程如图 2-9所示,下面我们从主控 模块入手,继续利用逐步求精的方法来设计系统。 第一步,写出主程序的基本框架,确定各个内部模块的函数名和参数。 int main() { initGraph(); /*图形显示方式初始化*/ do { newGame(); /*初始化新游戏,即开局*/ int gameRes=0; do { int key = getKey(); /*读入操作信息*/ if (key == ESC) {gameRes = 0;break;} switch(key){ 对其他 key值进行判断处理; } if (checkWin()) /*判断游戏是否胜利*/ gameRes = 1; }while(!gameRes); }while (!confirm(gameRes)); return 0; } 12 可以看出,主控模块为两层循环结构,外层循环是用于控制游戏是否再次进行。内层是对某 次游戏操作进行处理,用 gameRes作循环判断。gameRes初始值为 0。当游戏获胜时值设为 1,游戏失败时值设为-1,当 gameRes值不为 0时,意味着游戏已有胜负结果,所以可以退 出本次游戏。另外,当按下 ESC键时,用 break直接跳出了内部循环,这是受限制的 GOTO 的使用。主控模块的下属模块有: ¾ void initGraph()函数:用于将显示器显示方式设置为图形方式。 ¾ void newGame()函数:开始新的游戏,初始化新的游戏界面及数据。 ¾ int getKey()函数:得到从键盘读入的操作信息。 ¾ int checkWin()函数:用于判断游戏是否获胜。若返回值为 1表示胜利,返回值为 0 表示游戏还没结束。 ¾ int confirm(int) 函数:用于判断游戏是否重新开始。参数的值来自 gameRes, gameRes=0,表示按 esc键退出游戏;gameRes = -1,表示踩到地雷,游戏失败; gameRes = 1,表示游戏胜利。Confirm的返回值为 0表示重新开始游戏;为 1表示 关闭游戏,退出程序。 第二步,对“图形初始化”进一步求精,实现图形显示方式的初始化。 void initGraph( ) { int gdriver = DETECT, gmode, errorcode; /* request auto detection*/ initgraph(&gdriver, &gmode, "f:\\borlandc\\bgi\\"); /*nitialize graphics mode*/ errorcode = graphresult(); /* read result of initialization*/ if (errorcode != grOk) /* an error occurred */ { 图 2-9 扫雷游戏的主控模块流程 图形方式初始化 初始化新游戏 从键盘读入操作信息 开始 各类消息判断并作相应的处理 判断当前游戏状态 重新游戏? 是 胜利 /失败 / 退出命令 其他 关闭游戏,结束 13 printf("Graphics error: %s\n", grapherrormsg(errorcode)); printf("Press any key to halt:"); getch(); exit(1); /*return with error code */ } } 这里的 initgraph(),graphresult(),grapherrormsg()函数是在 graphics.h中声明的库函 数,其中 initgraph()初始化图形硬件,用于设置计算机图形方式;graphresult()用来判断是否 完成了图形的初始化;grapherrormsg()返回出错信息。 第三步,对“初始化新游戏”进一步求精。 void newGame() { cleardevice(); generateMine(); /*随机生成雷区地雷分布*/ pi = pj = 0; drawTable(); /*实现在屏幕上画出雷区*/ } 新的一轮游戏开始时,必须清理掉上次的结果,通过 graphics.h 中的 cleardevice()清除屏幕 上已有的显示,通过 generateMine()函数随机生成新的雷区地雷分布,即重新设置 totalMine、 num、table和 flag。最后通过 drawTable()在屏幕上显示新的游戏界面。 generateMine()的继续细化: void generateMine() 功能:随机生成地雷的分布。 参数: 无 返回值:无 算法描述: 1. 计算将要生成的地雷的总数,存放在变量 totalMine中。 2. 将 table数组和 num数组清零,table和 num都是全局的二维数组,table记录 坐标(x,y)中是否有地雷,0表示没有地雷,1表示有。 num数组表示和(x,y)相邻的所有小方块中有多少颗地雷。 3. 随机生成 totalMine个地雷的坐标,动态更新 table和 num数组的状态, drawTable()的继续细化: void drawTable() { int i,j; for(i=0;i
本文档为【案例分析-开发综合程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_326117
暂无简介~
格式:pdf
大小:157KB
软件:PDF阅读器
页数:37
分类:互联网
上传时间:2010-03-27
浏览量:7