




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第C#備忘錄人生存檔的設(shè)計(jì)模式實(shí)例目錄C#備忘錄設(shè)計(jì)模式游戲背景游戲?qū)崿F(xiàn)角色類角色基類玩家類怪獸類游戲類游戲操作類客戶端加上存檔需要存檔的數(shù)據(jù)存檔定義備忘錄模式出場空接口私有嵌套存檔類創(chuàng)建存檔和從存檔恢復(fù)存檔管理器類在游戲操作類添加玩家選項(xiàng)結(jié)語
C#備忘錄設(shè)計(jì)模式
大家好,老胡又和大家見面了。首先承認(rèn)今天的博客有點(diǎn)標(biāo)題黨了,人生是沒有存檔,也沒有后悔藥的。有存檔和后悔藥的,那是游戲,不知道這是不是游戲讓人格外放松的原因之一。
今天恰逢端午放假,就讓我們來試著做一個(gè)小游戲吧,順帶看看備忘錄模式是如何在這種情況下面工作的。
游戲背景
這是一個(gè)簡單的打怪游戲,有玩家,有怪獸,玩家作為主角光環(huán),有如下三個(gè)特殊能力
攻擊怪獸有暴擊幾率有幾率回避怪獸攻擊可以自己治療一定生命值
游戲?qū)崿F(xiàn)
角色類
角色基類
首先是角色類,角色類提供玩家和怪獸最基本的抽象,比如血量、攻擊力、攻擊和治療。(對于怪獸來說,治療是沒有提供實(shí)現(xiàn)的,壞人肯定不能再治療了)
classCharacter
publicintHealthPoint{get;set;}
publicintAttackPoint{get;set;}
publicvirtualvoidAttackChracter(Characteropponent)
opponent.HealthPoint-=this.AttackPoint;
if(opponent.HealthPoint0)
opponent.HealthPoint=0;
publicvirtualvoidCure()
//故意留空給子類實(shí)現(xiàn)
玩家類
玩家實(shí)現(xiàn)了治療功能并且有暴擊幾率。
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");
怪獸類
怪獸沒有治療能力但是有一定的幾率丟失攻擊目標(biāo)。
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");
游戲類
游戲類負(fù)責(zé)實(shí)例化玩家和怪獸、記錄回合數(shù)、判斷游戲是否結(jié)束,暴露可調(diào)用的公共方法給游戲操作類。
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,'*'));
游戲操作類
在我們這個(gè)簡易游戲中,沒有UI代碼,游戲操作類負(fù)責(zé)在用戶輸入和游戲中搭建一個(gè)橋梁,解釋用戶的輸入。
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();
客戶端
客戶端的代碼就非常簡單了,只需要實(shí)例化一個(gè)游戲操作類,然后讓其運(yùn)行就可以了。
classProgram
staticvoidMain(string[]args)
Gamegame=newGame();
GameRunnerrunner=newGameRunner(game);
runner.Run();
試著運(yùn)行一下,
看起來一切都好。
加上存檔
雖然游戲可以正常運(yùn)行,但是總感覺還是少了點(diǎn)什么。嗯,存檔功能,一個(gè)游戲沒有存檔是不健全的,畢竟,人生雖然沒有存檔,但是游戲可是有的!讓我們加上存檔功能吧,首先想想怎么設(shè)計(jì)。
需要存檔的數(shù)據(jù)
首先我們要明確,有哪些數(shù)據(jù)是需要存檔的,在這個(gè)游戲中,玩家的生命值、攻擊力、暴擊率;怪獸的生命值、攻擊力和丟失率,游戲的回合數(shù),都是需要存儲(chǔ)的對象。
存檔定義
這是一個(gè)需要仔細(xì)思考的地方,一般來說,需要考慮以下幾個(gè)地方:
存檔需要訪問一些游戲中的私有字段,比如暴擊率,需要在不破壞游戲封裝的情況下實(shí)現(xiàn)這個(gè)功能存檔自身需要實(shí)現(xiàn)信息隱藏,即除了游戲,其他類不應(yīng)該訪問存檔的詳細(xì)信息存檔不應(yīng)該和游戲存放在一起,以防不經(jīng)意間游戲破壞了存檔數(shù)據(jù),應(yīng)該有專門的類存放存檔
備忘錄模式出場
這個(gè)時(shí)候應(yīng)該是主角出場的時(shí)候了。看看備忘錄模式的定義
在不破壞封閉的前提下,捕獲一個(gè)對象的內(nèi)部狀態(tài),并在該對象之外保存這個(gè)狀態(tài)。這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài)
再看看UML,
看起來完全符合我們的需求啊,Originator就是游戲類,知道如何創(chuàng)造存檔和從存檔中恢復(fù)狀態(tài),Memento類就是存檔類,Caretaker是一個(gè)新類,負(fù)責(zé)保存存檔。
經(jīng)過思考,我們決定采取備忘錄模式,同時(shí)加入以下措施:
將存檔定義為游戲中的私有嵌套類,這樣存檔可以毫無壓力的訪問游戲中的私有字段,同時(shí)外界永遠(yuǎn)沒有辦法去實(shí)例化或者嘗試通過轉(zhuǎn)型來獲得這個(gè)類,完美的保護(hù)了存檔類存檔類是一個(gè)簡單的數(shù)據(jù)集合,不包含任何其他邏輯添加一個(gè)存檔管理器,可以放在游戲操作類中,可以通過它看到我們當(dāng)前有沒有存檔存檔放在存檔管理器中存檔實(shí)現(xiàn)一個(gè)空接口,在存檔管理器中以空接口形式出現(xiàn),這樣外部類在訪問存檔的時(shí)候,僅能看到這個(gè)空接口。而在游戲類內(nèi)部,我們在使用存檔之前先通過向下轉(zhuǎn)型實(shí)現(xiàn)類型轉(zhuǎn)換(是的,向下轉(zhuǎn)型不怎么好,但是偶爾可以用一下)
空接口
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;}
創(chuàng)建存檔和從存檔恢復(fù)
在game中添加創(chuàng)建存檔和從存檔恢復(fù)的代碼,在從存檔恢復(fù)的時(shí)候,使用了向下轉(zhuǎn)型,因?yàn)閺拇鏅n管理器讀出來的只是空接口而已
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");
存檔管理器類
添加一個(gè)類專門管理存檔,此類非常簡單,只有一個(gè)存檔,要支持多存檔可以考慮使用List
classGameSaveStore
publicIGameSaveGameSave{get;set;}
在游戲操作類添加玩家選項(xiàng)
首先在游戲操作類中添加一個(gè)存檔管理器
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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年海事專業(yè)技術(shù)資格考試試卷及答案
- 2025年投資理財(cái)師職業(yè)資格考試試題及答案
- 2025年金融市場學(xué)考試試卷及答案
- 2025年翻譯專業(yè)八級考試題及答案
- 互聯(lián)網(wǎng)藝術(shù)品鑒定與價(jià)值評估服務(wù)協(xié)議
- 娛樂行業(yè)替身保險(xiǎn)補(bǔ)充合同細(xì)則
- 高端私人游艇專屬泊位租賃管理服務(wù)合同
- 智能家居產(chǎn)品體驗(yàn)店加盟品牌授權(quán)與區(qū)域保護(hù)合同
- 智能家居研發(fā)項(xiàng)目保密補(bǔ)充協(xié)議
- 網(wǎng)絡(luò)廣告內(nèi)容審查規(guī)范補(bǔ)充協(xié)議
- 三項(xiàng)制度改革培訓(xùn)
- 2025屆“新課程標(biāo)準(zhǔn)”下的中考道德與法治復(fù)習(xí)策略 課件
- T-CTTS 0019-2023 數(shù)字化實(shí)驗(yàn)室等級評價(jià)規(guī)范
- 動(dòng)漫游戲IP衍生品開發(fā)策劃書
- 晉祠完整分享
- 機(jī)器視覺系統(tǒng)應(yīng)用(中級) 課件 5.4書簽缺陷檢測系統(tǒng)聯(lián)調(diào)
- 事業(yè)單位代報(bào)名委托書
- 保溫安全生產(chǎn)管理制度
- 大客戶銷售:謀攻之道
- 建設(shè)單位與施工單位安全生產(chǎn)協(xié)議書 標(biāo)準(zhǔn)版
- 6人小品《沒有學(xué)習(xí)的人不傷心》臺詞完整版
評論
0/150
提交評論