玩游戲的時候,會有關卡以及boss,通過boss戰后,獲得新裝備,新開啟關卡,并會提示存儲當前進度,以便以后可以再重玩當前boss戰,比如生化危機,鬼泣等等殺完一個boss爽了,然后存儲下當前進度,但是這種存儲都是需要介質持久化,如果需要在內存中長久駐留,那么就要采用一些方式存儲。
當玩家創建一個角色的時候,與該角色相關的東西都會附加上,比如裝備,角色外貌,場景等等,這些東西封裝為一個對象,然后將對象狀態保存在外部,就是備忘錄模式了,下面為第一版簡略類圖:
Roll是角色,RollState是角色附加的東西:裝備,場景,殺了幾個boss,獲得的新裝備等等也就是當前角色的狀態,GameState是用來存儲角色狀態的類,GameStateManager是角色狀態管理類,但是這種方式,只能針對不同角色存儲一種狀態的情況,
比如鬼泣主角:但丁 當第一關通過后,獲得新裝備,新關卡,此時存儲下來,即GameStateManager.setGameState()方法,內部用map存儲即manager.put("但丁",gameState),但是用map只能存儲但丁的一個狀態,如果再有另外一個角色:惡魔但丁,同樣會只能存儲一個狀態,上面類圖只針對不同角色,當前狀態,以及上一個狀態之間的切換。如果一個角色有多個狀態,狀態之間跳躍,比如打完第6關,玩家想切換回第3關玩,如果遇見這種情況,那么將GameStateManager的map泛型第二個參數改為聚集即可。第二版類圖如下:
:
GameStateManager成員變量第二個泛型參數改為Collection<GameState>,里面參數即可根據角色名字和第幾個關卡獲取狀態,代碼如
package designpattern.memento;

public class Roll


{
private RollState rollState = new RollState("默認裝備", "默認樣子", "出生場景");

private String name;

public Roll(String name)

{
this.name = name;
}

public void killBossA()

{
System.out.println("殺了boss1,獲得新裝備,開啟關卡2");
rollState.setEquipment("新裝備");
rollState.setAppearance( "獲得新外型");
rollState.setScene("開啟關卡2");
}

public void killBossB()

{
System.out.println( "殺了boss2,獲得更好的裝備,開啟更難關卡");
rollState.setEquipment( "更強裝備");
rollState.setAppearance( "獲得更酷外型");
rollState.setScene(name + "開啟關卡3");
}

public RollState getRollState()

{
return rollState;
}

public void setRollState(RollState rollState)

{
this.rollState = rollState;
}

public String getName()

{
return name;
}

public void setName(String name)

{
this.name = name;
}


/** *//**
* 創建備份點
*
* @return
*/
public GameState createGameState()

{
return new GameState(rollState);
}


/** *//**
* 獲得上次備份點
*
* @param gameState
*/
public void restoreGameState(GameState gameState)

{
this.rollState = gameState.getRollState();
}

@Override
public String toString()

{
return name+":"+this.getRollState().getEquipment()+", "+this.getRollState().getAppearance()+", "+this.getRollState().getScene();
}
}

package designpattern.memento;


/** *//**
* @author Administrator 角色狀態類
*/
public class RollState


{

private String equipment;
private String appearance;
private String scene;

public RollState()

{
}

public RollState(String equipment, String appearance, String scene)

{
this.equipment = equipment;
this.appearance = appearance;
this.scene = scene;
}

public String getEquipment()

{
return equipment;
}

public void setEquipment(String equipment)

{
this.equipment = equipment;
}

public String getAppearance()

{
return appearance;
}

public void setAppearance(String appearance)

{
this.appearance = appearance;
}

public String getScene()

{
return scene;
}

public void setScene(String scene)

{
this.scene = scene;
}

}

package designpattern.memento;

public class GameState


{
private RollState rollState;

public GameState(RollState rollState)

{
this.rollState = rollState;
}

public RollState getRollState()

{
return rollState;
}

public void setRollState(RollState rollState)

{
this.rollState = rollState;
}

}

package designpattern.memento;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class GameStateManager


{
private Map<String, ArrayList<GameState>> managers = new HashMap<String,ArrayList<GameState>>();

public GameState getGameState(String rollName, int indexBoss)

{
return managers.get(rollName).get(indexBoss);
}

public void setGameState(String rollName, GameState gameState)

{
ArrayList<GameState> list = null;
if ((list = managers.get(rollName)) != null)

{
list.add(gameState);
} else

{
managers.put(rollName,new ArrayList<GameState>(Arrays.asList(gameState)));
}
System.err.println(managers.get(rollName));
}
}

package designpattern.memento;

public class Client


{
public static void main(String[] args)

{
Roll roll = new Roll( "但丁");
GameStateManager states = new GameStateManager();
//玩家初始場景,即出生點
states.setGameState(roll.getName(), roll.createGameState());
roll.killBossA();
//殺完bossA 存儲
states.setGameState(roll.getName(), roll.createGameState());
roll.killBossB();
//殺完bossB存儲
states.setGameState(roll.getName(), roll.createGameState());
//玩家想返回殺bossA之前場景 內部使用線性表存儲 0即代表玩家出生點,初始場景,一般游戲里面會對每個boss戰場景標記
roll.restoreGameState(states.getGameState(roll.getName(), 0));
System.out.println(roll.toString());
roll.restoreGameState(states.getGameState(roll.getName(), 1));
System.out.println(roll.toString());
}
}

這跟事物原理一致
上面有個bug,Roll類里面killBossA方法應該改為:
// rollState.setEquipment("新裝備A");
// rollState.setAppearance("獲得新外型A");
// rollState.setScene("開啟關卡2");
rollState = new RollState("新裝備A","獲得新外型A","開啟關卡2");
killBossB方法應該改為:
rollState = new RollState("更強裝備B","獲得更酷外型B","開啟關卡3");
// rollState.setEquipment("更強裝備B");
// rollState.setAppearance("獲得更酷外型B");
// rollState.setScene(name + "開啟關卡3");
否則都傳遞的是引用,修改的是同一個引用,保存的都是同一個狀態。
因為roll角色的狀態是通過RollState引用來保存,而不是基本變量和string類型
posted on 2013-09-28 14:57
朔望魔刃 閱讀(260)
評論(0) 編輯 收藏 所屬分類:
設計模式&&數據結構