C#备忘录人生存档的设计模式实例_第1页
C#备忘录人生存档的设计模式实例_第2页
C#备忘录人生存档的设计模式实例_第3页
C#备忘录人生存档的设计模式实例_第4页
C#备忘录人生存档的设计模式实例_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C#备忘录人生存档的设计模式实例目录C#备忘录设计模式游戏背景游戏实现角色类角色基类玩家类怪兽类游戏类游戏操作类客户端加上存档需要存档的数据存档定义备忘录模式出场空接口私有嵌套存档类创建存档和从存档恢复存档管理器类在游戏操作类添加玩家选项结语

C#备忘录设计模式

大家好,老胡又和大家见面了。首先承认今天的博客有点标题党了,人生是没有存档,也没有后悔药的。有存档和后悔药的,那是游戏,不知道这是不是游戏让人格外放松的原因之一。

今天恰逢端午放假,就让我们来试着做一个小游戏吧,顺带看看备忘录模式是如何在这种情况下面工作的。

游戏背景

这是一个简单的打怪游戏,有玩家,有怪兽,玩家作为主角光环,有如下三个特殊能力

攻击怪兽有暴击几率有几率回避怪兽攻击可以自己治疗一定生命值

游戏实现

角色类

角色基类

首先是角色类,角色类提供玩家和怪兽最基本的抽象,比如血量、攻击力、攻击和治疗。(对于怪兽来说,治疗是没有提供实现的,坏人肯定不能再治疗了)

classCharacter

publicintHealthPoint{get;set;}

publicintAttackPoint{get;set;}

publicvirtualvoidAttackChracter(Characteropponent)

opponent.HealthPoint-=this.AttackPoint;

if(opponent.HealthPoint0)

opponent.HealthPoint=0;

publicvirtualvoidCure()

//故意留空给子类实现

玩家类

玩家实现了治疗功能并且有暴击几率。

classPlayer:Character

privatefloatplayerCriticalPossible;

publicPlayer(floatcritical)

playerCriticalPossible=critical;

publicoverridevoidAttackChracter(Characteropponent)

base.AttackChracter(opponent);

Console.WriteLine("PlayerAttackedMonster");

Randomr=newRandom();

boolcritical=r.Next(0,100)playerCriticalPossible*100;

if(critical)

base.AttackChracter(opponent);

Console.WriteLine("PlayerAttackedMonsteragain");

publicoverridevoidCure()

Randomr=newRandom();

HealthPoint+=r.Next(5,10);

Console.WriteLine("Playercuredhimself");

怪兽类

怪兽没有治疗能力但是有一定的几率丢失攻击目标。

classMonster:Character

privatefloatmonsterMissingPossible;

publicMonster(floatmissing)

monsterMissingPossible=missing;

publicoverridevoidAttackChracter(Characteropponent)

Randomr=newRandom();

boolmissing=r.Next(0,100)monsterMissingPossible*100;

if(missing)

Console.WriteLine("Monstermissedit");

else

base.AttackChracter(opponent);

Console.WriteLine("MonsterAttackedplayer");

游戏类

游戏类负责实例化玩家和怪兽、记录回合数、判断游戏是否结束,暴露可调用的公共方法给游戏操作类。

classGame

privateCharacterm_player;

privateCharacterm_monster;

privateintm_round;

privatefloatplayerCriticalPossible=0.6f;

privatefloatmonsterMissingPossible=0.2f;

publicGame()

m_player=newPlayer(playerCriticalPossible)

HealthPoint=15,

AttackPoint=2

m_monster=newMonster(monsterMissingPossible)

HealthPoint=20,

AttackPoint=6

publicboolIsGameOver=m_monster.HealthPoint==0||m_player.HealthPoint==0;

publicvoidAttackMonster()

m_player.AttackChracter(m_monster);

publicvoidAttackPlayer()

m_monster.AttackChracter(m_player);

publicvoidCurePlayer()

m_player.Cure();

publicvoidBeginNewRound()

m_round++;

publicvoidShowGameState()

Console.WriteLine("".PadLeft(20,'-'));

Console.WriteLine("Round:{0}",m_round);

Console.WriteLine("playerhealth:{0}","".PadLeft(m_player.HealthPoint,'*'));

Console.WriteLine("monsterhealth:{0}","".PadLeft(m_monster.HealthPoint,'*'));

游戏操作类

在我们这个简易游戏中,没有UI代码,游戏操作类负责在用户输入和游戏中搭建一个桥梁,解释用户的输入。

classGameRunner

privateGamem_game;

publicGameRunner(Gamegame)

m_game=game;

publicvoidRun()

while(!m_game.IsGameOver)

m_game.BeginNewRound();

boolvalidSelection=false;

while(!validSelection)

m_game.ShowGameState();

Console.WriteLine("Makeyourchoice:1.attack2.Cure");

varstr=Console.ReadLine();

if(str.Length!=1)

continue;

switch(str[0])

case'1':

validSelection=true;

m_game.AttackMonster();

break;

case'2':

validSelection=true;

m_game.CurePlayer();

break;

default:

break;

if(!m_game.IsGameOver)

m_game.AttackPlayer();

客户端

客户端的代码就非常简单了,只需要实例化一个游戏操作类,然后让其运行就可以了。

classProgram

staticvoidMain(string[]args)

Gamegame=newGame();

GameRunnerrunner=newGameRunner(game);

runner.Run();

试着运行一下,

看起来一切都好。

加上存档

虽然游戏可以正常运行,但是总感觉还是少了点什么。嗯,存档功能,一个游戏没有存档是不健全的,毕竟,人生虽然没有存档,但是游戏可是有的!让我们加上存档功能吧,首先想想怎么设计。

需要存档的数据

首先我们要明确,有哪些数据是需要存档的,在这个游戏中,玩家的生命值、攻击力、暴击率;怪兽的生命值、攻击力和丢失率,游戏的回合数,都是需要存储的对象。

存档定义

这是一个需要仔细思考的地方,一般来说,需要考虑以下几个地方:

存档需要访问一些游戏中的私有字段,比如暴击率,需要在不破坏游戏封装的情况下实现这个功能存档自身需要实现信息隐藏,即除了游戏,其他类不应该访问存档的详细信息存档不应该和游戏存放在一起,以防不经意间游戏破坏了存档数据,应该有专门的类存放存档

备忘录模式出场

这个时候应该是主角出场的时候了。看看备忘录模式的定义

在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态

再看看UML,

看起来完全符合我们的需求啊,Originator就是游戏类,知道如何创造存档和从存档中恢复状态,Memento类就是存档类,Caretaker是一个新类,负责保存存档。

经过思考,我们决定采取备忘录模式,同时加入以下措施:

将存档定义为游戏中的私有嵌套类,这样存档可以毫无压力的访问游戏中的私有字段,同时外界永远没有办法去实例化或者尝试通过转型来获得这个类,完美的保护了存档类存档类是一个简单的数据集合,不包含任何其他逻辑添加一个存档管理器,可以放在游戏操作类中,可以通过它看到我们当前有没有存档存档放在存档管理器中存档实现一个空接口,在存档管理器中以空接口形式出现,这样外部类在访问存档的时候,仅能看到这个空接口。而在游戏类内部,我们在使用存档之前先通过向下转型实现类型转换(是的,向下转型不怎么好,但是偶尔可以用一下)

空接口

interfaceIGameSave

私有嵌套存档类

该类存放在game里面,无压力地在不破坏封装的情况下访问game私有字段

privateclassGameSave:IGameSave

publicintPlayerHealth{get;set;}

publicintPlayerAttack{get;set;}

publicfloatPlayerCritialAttackPossible{get;set;}

publicintMonsterHealth{get;set;}

publicintMonsterAttack{get;set;}

publicfloatMonsterMissingPossible{get;set;}

publicintGameRound{get;set;}

创建存档和从存档恢复

在game中添加创建存档和从存档恢复的代码,在从存档恢复的时候,使用了向下转型,因为从存档管理器读出来的只是空接口而已

publicIGameSaveCreateSave()

varsave=newGameSave()

PlayerHealth=m_player.HealthPoint,

PlayerAttack=m_player.AttackPoint,

PlayerCritialAttackPossible=playerCriticalPossible,

MonsterAttack=m_monster.AttackPoint,

MonsterHealth=m_monster.HealthPoint,

MonsterMissingPossible=monsterMissingPossible,

GameRound=m_round

Console.WriteLine("gamesaved");

returnsave;

publicvoidRestoreFromGameSave(IGameSavegamesave)

GameSavesave=gamesaveasGameSave;

if(save!=null)

m_player=newPlayer(save.PlayerCritialAttackPossible){HealthPoint=save.PlayerHealth,AttackPoint=save.PlayerAttack};

m_monster=newPlayer(save.MonsterMissingPossible){HealthPoint=save.MonsterHealth,AttackPoint=save.MonsterAttack};

m_round=save.GameRound;

Console.WriteLine("gamerestored");

存档管理器类

添加一个类专门管理存档,此类非常简单,只有一个存档,要支持多存档可以考虑使用List

classGameSaveStore

publicIGameSaveGameSave{get;set;}

在游戏操作类添加玩家选项

首先在游戏操作类中添加一个存档管理器

privateGameSaveStorem_gameSaveStore=newGameSaveStore();

接着修改Run方法添加用户操作

publicvoidRun()

while(!m_game.IsGameOver)

m_game.BeginNewRound();

boolvalidSelection=false;

while(!validSelection)

m_game.ShowGameState();

Console.WriteLine("Makeyourchoice:1.attack2.Cure3.Save4.Load");

varstr=Console.ReadLine();

if(str.Length!=1)

continue;

switch(str[0])

case'1'

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论