博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++程序设计作业--坦克大战[分享]
阅读量:3973 次
发布时间:2019-05-24

本文共 7330 字,大约阅读时间需要 24 分钟。

C++程序设计作业--坦克大战[分享]

在使用C#做的面向对象程序设计,做的虽然是坦克大战小游戏,结合上课内容,理解类图以及对应的语句,完成作业,也是一种收获,现在记录一下,也分享一下,共勉!有错误的话欢迎大家指出~

1.设计目的

通过该实验,掌握windows下C++程序设计的基本方法。掌握类图、代码图的分析方法。通过处理过程对计算机软件系统工作原理的进一步理解,促进对面向对象概念的系统理解以及面向对象方法的应用。

2.设计目标

1、基本目标

(1)完成代码编写设计;

(2)编译通过整个程序,并运行相应小游戏;
(3)界面成功显示,可以对坦克进行相应操作;
(4)能够正常更新己方坦克和敌方坦克的HP值;
(5)可以实现两个己方坦克的同时操作;
(6)在双人模式下,保证界面的正确运行;
(7)对最后的积分结果有着正确的显示。

2、额外目标

(1)可以任意改变墙的形状;

(2)长按空格键可以无限发射子弹;
(3)可以任意改变坦克的颜色大小;
(4)可以显示在线帮助和设置;
(5)其它自行设计的功能。

3 程序设计思路

3.1 类的设计

本设计在于用C++实现一个小游戏—坦克大战,经考虑可以用六个类来实现:

Class1:class Ctank:virtual public Draw

Class2:class Control : virtual public CTank, virtual public CBullet

Class3:class CBullet : virtual public Draw

Class4:class Draw : public CData

Class5:class CUnion

Class6:class CData

先给出整个程序的类图,类图(Class diagram)由许多(静态)说明性的模型元素(例如类、包和它们之间的关系,这些元素和它们的内容互相连接)组成。类图可以组织在(并且属于)包中,仅显示特定包中的相关内容。类图(Class diagram)是最常用的UML图,显示出类、接口以及它们之间的静态结构和关系;它用于描述系统的结构化设计。类图(Class diagram)最基本的元素是类或者接口。 类图主要用在面向对象软件开发的分析和设计阶段,描述系统的静态结构。类图图示了所构建系统的所有实体、实体的内部结构以及实体之间的关系。即类图中包含从用户的客观世界模型中抽象出来的类、类的内部结构和类与类之间的关系。它是构建其他设计模型的基础,没有类图,就没有对象图、状态图、协作图等其他UMI动态模型图,也就无法表示系统的动态行为。类图也是面向对象编程的起点和依据。

类图用于描述系统中所包含的类以及它们之间的相互关系,帮助我们简化对系统的理解,是系统分析和设计阶段的重要产物,也是系统编码和测试的重要模型依据。
类图如下:
在这里插入图片描述

3.1.1 CData

CData这个类的类图如下图所示:

在这里插入图片描述

这个类的作用是获得和重置坦克大战地图的高和宽,下面给出一个40*45的地图程序实现,由于这个程序过长,故截图显示:“

在这里插入图片描述

3.1.2 class Draw

class Draw派生于class Cdata,Draw的类图是:

在这里插入图片描述

这个类旨在实现设置控制台窗口,如打印地图、打印字符、在一个界面显示主菜单(清屏、处理按上下键之后的显示)、设置界面、显示选项、显示选项后的参数、接受按键(如果退出、将设置更新、清除箭头、防止选项超、检测左右键、防止参数超出范围、处理指定行的内容)、清除指定行的内容、打印帮助……

下面给出显示主菜单的源码:

int Draw::showOption(){
//清屏 Draw::clearConsole(8); Draw::writeChar(15, 11, "坦克大战 v1.0", FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); char ch; int option = 0; writeChar(13, 13 , "→", FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); char * options[] = {
"单人游戏", "双人游戏", "编辑地图", "设 置", "游戏帮助", "退 出" }; for (int i = 0; i < 6; i++) {
writeChar(15, 13 + i, options[i], FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); } while (true) {
if (_kbhit()) {
ch = _getch(); if (ch == 27) //esc {
return -1; } if (ch == 72 || ch == 80||ch == '\r') //只检测上下键 {
if (ch == 72) //UP {
writeChar(12, 13 + option, " ", 0); option--; } else if (ch == 80) //DOWN {
writeChar(12, 13 + option, " ",0); option++; } if (option < 0) {
option = 0; } else if (option >= 6) {
option--; } //处理按上下键之后的显示 writeChar(13, 13 + option, " ",0); Sleep(100); writeChar(13, 13 + option, "→", FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); writeChar(15, 13 + option, options[option], FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); if (ch == '\r') {
return option; } } } }}

3.1.3 class CBullet

class CBullet虛继承于class Draw,CBullet的类图如下:

在这里插入图片描述

class CBullet实现的功能是:清除子弹、子弹向着指定的方向移动一步、打印子弹如果是空道才打印返回true,否则返回false,然后调用attackSomeThing()等功能。

下面给出子弹移动的代码:

void CBullet::move(int direction){
this->clearBullet(); if (this->printBullet()) {
this->oldBulletY = BulletY; this->oldBulletX = BulletX; switch (direction) {
case UP: --BulletY; break; case DOWN: ++BulletY; break; case LEFT: --BulletX; break; case RIGHT: ++BulletX; break; } }}

3.1.4 class Ctank:virtual public Draw

class Ctank虛继承于class Draw,Ctank实现的功能是:打印坦克、将玩家1(2)写入地图、将坦克坐标写到地图上、对坦克进行碰壁检测、清除坦克、移动坦克等。

它的类图是:
在这里插入图片描述

下面给出移动坦克的源码:

void CTank::move(int direction){
round(time(NULL)); //判断坦克是否可以通过 if (tankIsThrough(this->TankX,this->TankY, direction)) {
switch (direction) {
case UP: this->clearTank(); this->TankY--; this->Direction = UP; this->printTank(); break; case DOWN: this->clearTank(); this->TankY++; this->Direction = DOWN; this->printTank(); break; case LEFT: this->clearTank(); this->TankX--; this->Direction = LEFT; this->printTank(); break; case RIGHT: this->clearTank(); this->TankX++; this->Direction = RIGHT; this->printTank(); break; } } else //不能通过就只打印 {
if (TankID >= 2) //用于敌方坦克在碰到障碍物时改变方向 {
switch (this->Direction) {
case UP: this->Direction = (int)rand() % 4; break; case DOWN: this->Direction = (int)rand() % 4; break; case LEFT: this->Direction = (int)rand() % 4; break; case RIGHT: this->Direction = (int)rand() % 4; break; } } else {
this->Direction = direction; } this->printTank(); }}

3.1.5 class Control : virtual public CTank, virtual public CBullet

class Control虛继承于CTank和CBullet,Control的类图如下:

在这里插入图片描述

class Control实现的功能是逻辑算法,控制坦克和子弹,检测坦克是否可以通过、循环输出子弹夹里面的子弹、开始游戏(游戏人数)、画记分板、更新我方和敌方记分板、打印初始化坦克等功能。下面给出生成第一个子弹的源码:

void Control::sendBullet(CTank& tank){
//生成一个子弹 clock_t firstTime = clock(); switch (tank.Direction) {
case UP: bullet.InitBullet( tank.TankID, tank.TankX + 1, tank.TankY - 1, tank.Direction, true, firstTime, tank.TankX + 1, tank.TankY - 1 ); break; case DOWN: bullet.InitBullet(tank.TankID, tank.TankX + 1, tank.TankY + 3, tank.Direction, true, firstTime, tank.TankX + 1, tank.TankY + 3); break; case LEFT: bullet.InitBullet(tank.TankID, tank.TankX - 1, tank.TankY + 1, tank.Direction, true, firstTime, tank.TankX - 1, tank.TankY + 1); break; case RIGHT: bullet.InitBullet(tank.TankID, tank.TankX + 3, tank.TankY + 1, tank.Direction, true, firstTime, tank.TankX + 3, tank.TankY + 1 ); break; } //将子弹存入VBullet容器 CUnion::ListBullet.push_back(bullet); //移动第一步 bullet.move(tank.Direction);}

3.1.6 class CUnion

class CUnion的类图如图所示:

在这里插入图片描述

这个类所要实现的功能是敌军被子弹击中 更新HP、更新计分板、处理子弹碰到障碍物等问题,下面给出击中后更新HP和记分板的源码:

void CUnion::enemyBeAttack(int posX, int posY){
int tank = CData::GetTypeOfMap(posX, posY); VTank[tank + 2].clearTank(); VTank[tank + 2].setnMaxHP(VTank[tank + 2].getMaxHP() - 1); Control::updateTableau();}

3.2主程序

#include "stdafx.h"#include "Control.h"int _tmain(int argc, _TCHAR* argv[]){
Control con; con.init(); while (true) {
int option = Draw::showOption(); switch (option) {
case 0:con.gameStart(1); break; //单人游戏 case 1:con.gameStart(2); break; //双人游戏 case 2:Draw::editMap(); break; //编辑地图 case 3:Draw::showConfig(); break; //设置 case 4:Draw::help(); break; //游戏帮助 case 5:return 0; break; //退出游戏 } } return 0;}}

可见,主程序先对Control类里面的成员变量进行初始化,然后进入循环,进入玩家选择界面,确定参与人数,是否需要编辑地图,是否需要进行设置以及游戏帮助和是否退出游戏。

3.3 Codemap:

在这里插入图片描述

Codemap可以更加清楚的看清程序之间的关系,可以通过创建代码图来可视化代码中的依赖项。 代码图可帮助查看代码如何相互配合,而无需读取文件和代码行。

可见,六个类之间的聚合链路都很广,它们之间的依赖关系都很强。

4 测试过程

4.1 进入游戏开始界面

在这里插入图片描述

4.2 选择单人模式,进入游戏

在这里插入图片描述

4.3 单人操作

在这里插入图片描述

可见,发射子弹,移动、HP、记分板等功能正常

4.4 双人模式

在这里插入图片描述

在运行过程中,功能也都按照最初想法实现了

4.5 运行设置和帮助

在这里插入图片描述

点击设置之后,可以调整敌方坦克数量、敌方坦克攻击力、敌方坦克血量、敌方坦克移动速度、敌方坦克自动寻路等

在这里插入图片描述
点击帮助之后,可以查看玩家1和玩家2的玩法操作。

综上,经过测试,最初的设想均已实现,坦克大战V1.0设计成功。

5.设计感想与总结

1)做大程序前,要学会做程序框架图。

以前,编写的都是小程序,可能不需要做框架图就可以在脑子中构思好,但是一旦程序量大了之后,脑子是运转不过来的,很容易混乱,这时候,做一个总的程序框架图是很有必要的,不用非常细腻,具体到每一个函数,只需要将程序的大体结构画出来,这样,你才知道具体的路该怎么走,从哪起步,接下来该干什么,对自己的行动有一个规划,这样做,可以使程序的结构很清晰,又能节省很多时间去思考接下来该干什么,这是一种很好的思想。
2)学会借鉴别人的程序
小程序看别人的,可能会被称为抄袭,但是如果大程序的每个语句都由自己来编写,在我看来是一种很愚蠢的方法,有个名人曾说过,天下文章一大抄,牛顿也说过,只有站在巨人的肩膀上,才能看的更远,所以对于大程序而言,有些可以借鉴别人的,没有必要全部自己来编写,可以在别人的基础上进一步来改进,这样既节省时间,又可以使自己的程序到达一个更高的水平。
3)学会用调试去发现和解决问题
程序量较小的时候,可能用脑子去模拟程序的运作就可以想出来错误在哪里,但是如果程序量大,不可能再去用脑子模拟,这时候就要用调试去解决,首先,需要找到错误的大概位置,设置断点,运行调试,一步一步,查看关键变量的数值,或者在关键位置设一个标志位,看标志位的值,同时看窗口的运行结果。这样,就能发现问题,解决问题。
4)写程序日志
每天对这天遇到的问题和解决方法,以及做的工作都记录下来,对编写程序能力的提升会有很大的帮助,这样做,解决问题的方法越来越多,遇到的问题也不会慌张,这样做,积累的是解决办法,而不是积累错误。

转载地址:http://ghtki.baihongyu.com/

你可能感兴趣的文章
Win7下Eclipse中文字体太小
查看>>
java中使用net.sf.json对json进行解析
查看>>
JSONObject和JSONArray遍历数组与对象
查看>>
MySQL事务autocommit自动提交
查看>>
git中.gitignore设置
查看>>
ajax请求成功后打开新窗口地址
查看>>
python中的copy模块(浅复制和深复制)
查看>>
Linux SWAP分区占用率高,刷新SWAP分区方法
查看>>
Redis在新浪微博中的应用
查看>>
微博CacheService架构浅析
查看>>
Google字体库引起的首页加载缓慢的解决方法
查看>>
apache调优
查看>>
linux中rpm常用命令
查看>>
tcp连接的11种状态
查看>>
url转码和解码
查看>>
编译安装ruby1.9.3(No rvm)
查看>>
详解如何在ubuntu上安装node.js
查看>>
tmpfs用法
查看>>
你真的会python嘛?
查看>>
Python的魔法(一): 基本知识
查看>>