面向对象的模拟器设计
SimC主要是使用C++程序设计语言所编写的。
C++是一门非常适合编写模拟器的语言。作为现在最常用的程序设计语言之一,C++最早被发明时的初衷便是用来编写模拟程序,C++之父Bjarne Stroustrup博士在其著作《The C++ Programming Language》里坦诚到:“初始发明这个语言(指C with Classes,C++的前身),是因为我想去写某些事件驱动的模拟程序”。当时语法上最适合编写模拟程序的语言是Simula67,从这种语言的名字上就可见一斑,它是上世纪60年代专门设计用来编写模拟器的语言,也是世界上第一个面向对象程序设计(Object-Oriented Programming, OOP)语言,同属于ALGOL家族。Bjarne Stroustrup博士将Simula67中的一些思想融合到C语言中,形成了最初的C with Classes。
风靡一时的OOP,其最早的概念“类”、“继承”,如今这些所有程序员都耳熟能详的术语,就是由制作模拟器的需求所催生出来的。
所以,很显然,模拟器的核心,就是对象。
什么是对象?
这里简单地对OOP中的一些概念进行阐述,方便没有编程基础的人往下阅读。
阅读这样几个句子,体会它们的含义:
这里,“动物”“鸟类”“猫头鹰”都叫做类。
而“Minerva”叫做对象。Minerva是一只猫头鹰,我们说Minerva是猫头鹰类的一个实例。
我们管“飞”“呼吸”这些动作称为方法。Minerva支持“飞”这个方法,所以我们可以让Minerva飞。
Minerva不支持“打酱油”这个方法,所以我们没办法让Minerva去打酱油。
而“让鸟类飞”显然是非常滑稽的一种说法,不需要我多解释你们都能明白为什么。
“体重”“身长”这些称为属性。
“动物”“鸟类”“猫头鹰”三个类之间的关系称为继承。猫头鹰继承自鸟类,鸟类继承自动物。
鸟类具有动物的所有属性和方法。猫头鹰具有鸟类的所有属性和方法。
我们管鸟类叫做猫头鹰的基类,管猫头鹰叫做鸟类的派生类。
以上是一些简单的概念介绍。
思考题
"鸟类会飞"这里究竟隐含了什么错误?如何改正?
(提示:企鹅是鸟类。)
为什么要用对象?
回到魔兽世界里来。
如果我们没有面向对象的这些概念,进行模拟会是很痛苦的一件事情。
例如我们现在要描述一些待模拟的职业:
职业 | 盗贼 | 战士 | 小德 | |
属性 | 急速 | 有 | 有 | 有 |
精通 | 有 | 有 | 有 | |
方法 | 攻击 | 有 | 有 | 有 |
爆菊 | 有 | |||
冲锋 | 有 | |||
卖萌 | 有 |
如果我们使用不带有OOP性质的程序设计语言,描述上述问题,就需要这么写:
盗贼的急速。
盗贼的精通。
盗贼的攻击。
盗贼的爆菊。
战士的急速。
战士的精通。
战士的攻击。
战士的冲锋。
小德的急速。
小德的精通。
小德的攻击。
小德的卖萌。
这样写的问题,不仅是代码量很大,写着麻烦。重复的代码也太多了,好像一直在做无用功一样,三个职业的急速有什么区别?
突然有一天,暴雪宣布,急速这个属性的计算方法改变啦!那么我们需要修改三处蓝色的代码,维护起来很吃力。
如果我们使用了OOP,程序会变成这样:
这样代码量明显减少了,“急速”“精通”“攻击”这些三职业共性都只有一份代码。没有重复代码。
暴雪说修改急速计算方法,我们对应需要修改的蓝色代码也只有一处。维护方便。
假设现在我们要定义战士的三个输出技能:致死打击、压制、猛击。
如果不使用OOP,我们要这么写:
你妹啊,这只不过刚写了三个技能,而且还只描述了技能的主要效果,这代码就已经长到令人兴致索然。
一个职业需要模拟的技能恐怕要达到20个吧!
所以我们需要将它们的共性抽取出来,使用继承来解决代码冗长的问题。
战士技能类{
}
致死打击类:继承自“战士技能类”{
}
压制类:继承自“战士技能类”{
}
猛击类:继承自“战士技能类”{
}
这样每添加一个技能所需的代码量就只有区区几行!添加一个技能变得轻松加愉快!
它们从基类“战士技能类”继承来了一整段完善的技能攻击过程,只需覆写其中的某个或某几个部分来表现每个技能的个性,例如压制永不会被躲闪,“压制类”覆写了计算躲闪几率的方法,使其返回结果永远都为零。
我们现在只有三个技能,代码长度看起来区别不是很明显。当你写满20多个技能的时候,差距就显现出来了。
思考题
请你尝试模仿我的写法,在上面的代码中添加第四个技能“英勇打击”。
英勇打击消耗30怒气,不获取怒气,冷却1.5秒,没有公共冷却,要求近战武器,不限天赋。
如果目前战士身上有“最后通牒”效果,英勇打击吞噬这个效果,变得必暴且不消耗怒气。
如果战士双持单手武器,英勇打击造成1.4倍的伤害。
(提示:写完后请自行检查,如果战士身上有“最后通牒”效果而现有怒气不足30,应该可以顺利施放英勇打击,而且这个英勇打击暴击率为100%。)
答案: