游戲規則
游戲分為甲乙雙方兩人,游戲規則如下
- 游戲雙方各擁有一個 10*10 的地圖中部署戰艦進行初始化分布,布局完成后,玩家只能
看到自己戰艦,看不到對方戰艦, - 戰艦有三種形狀, 每個玩家分別擁有每個模型的一條戰艦,三個模型分別為:

三種戰艦可以自由旋轉,
例:甲為紅色,已為藍色,初始布局可以如下:
乙方地圖(戰艦只對乙方可見)

甲方地圖(戰艦只對甲方可見)

- 游戲開始,甲乙兩人輪流挑選對方坐標進行炸彈盲投,如果炸彈擊中對方戰艦,則標記
擊中,如果沒有擊中,標記 miss,如果一個戰艦的所有位置都被擊中,該戰艦標記位沉
沒, - 戰艦全部沉沒者為失敗方,游戲結束,
要求
- 設計游戲資料結構,流程以及相關物件 Class. 無需設計 UI 界面,
- 描述如何啟動游戲,初始化游戲,進行游戲,以及游戲結束,
- 描述如何對該游戲測驗
附加要求
- 如果船只有多種不規則形狀,如何改進現有系統?
例如引入新型戰艦模型:

- 如果雙方在游戲中各有一次移動一只戰艦坐標的機會,如何添加該功能?
以下是我自己的一些解題思路,僅供參考:
1.相關物件(包含代碼注釋)
通過分析游戲設計需求,定義游戲界面為橫向 X 軸坐標,縱向 Y 軸,
不同戰艦形狀均是以多個 xy 軸坐標上的點假設為 node 物件構成,
利用享元模式,定義 node 物件,而不同的戰艦均是以 node 物件基
于組合模式構成,通一個 ship 中的所有 node 基于雙向鏈表資料結構
組成,ship 中只需要存盤該戰艦 ship 的 firstNode 即可(鏈表的查詢
速度最優,便于查詢 node 并做炮彈擊中等邏輯判斷時對 node 的遍
歷查詢),其中 firstNode 為戰艦的左上腳第一個 node;ship 的初始
化是基于工廠模式實作,01,02,03 分別對應 a\b\c 三類戰艦;
戰艦相關物件及含義
public class Node {
/**
* 每個節點的顏?, --如果被轟炸之后,那節點顏?就是灰?
*/
private NodeColor nodeColor;
private int x;
private int y;
private Node preNode;
private Node nextNode;
public NodeColor getNodeColor() {
return nodeColor;
}
public void setNodeColor(NodeColor nodeColor) {
this.nodeColor = nodeColor;
}public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Node getPreNode() {
return preNode;
}
public void setPreNode(Node preNode) {
this.preNode = preNode;
}
public Node getNextNode() {
return nextNode;
}
public void setNextNode(Node nextNode) {this.nextNode = nextNode;
}
public boolean changeColor(NodeColor color){
this.nodeColor = color;
return true;
} }
NodeColor 列舉型別用于標識 node 的不同顏色,當 node 被擊中,則修改當前 node 的顏
色--如置灰
nodeColor 如下:
public boolean changeColor(NodeColor color){
this.nodeColor = color;
return true;
}
通過工廠類創建戰艦,工廠類的代碼如下:
public class ShipFactory {
public static Map<NodeColor,int[][]> allMap = new ConcurrentHashMap<>(3);
static {
/**
* 虛擬地圖-編號 0-9 ,?實際 UI 中是 1-10
*/
int[][] shipNodeMap4Red = new int[10][10];//紅?地圖
int[][] shipNodeMap4Blue = new int[10][10];//藍?地圖allMap.put(NodeColor.RED,shipNodeMap4Red);
allMap.put(NodeColor.BLUE,shipNodeMap4Blue);
}
public static Ship getInstance(String shipType,NodeColor color,int x,int y){
if (0 < x && x <= 10 && 0 < y && y <= 10){
if("01".equals(shipType)){
/**
* 橫向三點戰艦
*/
if(x -2 > 0 && x < 11 && y > 0 && y < 11 ){
Node firstNode = new Node(color,x , y, null );//左側 node
Node midNode = new Node(color,x- 1, y , firstNode);
Node endNode = new Node(color,x - 2, y, midNode);
if(checkCanBeCreate(firstNode,midNode,endNode)){//判斷 node 是否存在重
復
firstNode.setNextNode(midNode);
midNode.setNextNode(endNode);
endNode.setNextNode(null);
addNodes2Map(firstNode,midNode,endNode);//創建成功之后,記錄創建
記錄return new Ship(true,firstNode);
}else{
firstNode = null;
midNode = null;
endNode = null;
clearNode(firstNode,midNode,endNode);
}
return new Ship(false);
}
return new Ship(false);
}else if("02".equals(shipType)){
/**
* 四點戰艦
*/
if(x -1 > 0 && y - 1 > 0 && x + 1 < 11 && y + 1 < 11){
Node firstNode = new Node(color,x , y, null );//左上? node
Node secondNode = new Node(color,x + 1, y , firstNode);
Node thirdNode = new Node(color,x , y -1 , secondNode);
Node endNode = new Node(color,x + 1 , y -1 , thirdNode);
if(checkCanBeCreate(firstNode,secondNode,thirdNode,endNode)){//判斷node 是否存在重復
firstNode.setNextNode(secondNode);
secondNode.setNextNode(thirdNode);
thirdNode.setNextNode(endNode);
endNode.setNextNode(null);
addNodes2Map(firstNode,secondNode,thirdNode,endNode);//創建成功之
后,記錄創建記錄
return new Ship(true,firstNode);
}else{
firstNode = null;
secondNode = null;
thirdNode = null;
endNode = null;
clearNode(firstNode,secondNode,thirdNode,endNode);
}
return new Ship(false);
}
return new Ship(false);
}else {
/*** 縱向兩點戰艦
*/
if(y -1 > 0 && y< 11 && x >0 && x < 11){
Node firstNode = new Node(color,x , y, null );//左側 node
Node endNode = new Node(color,x - 1, y, firstNode);
if(checkCanBeCreate(firstNode,endNode)){//判斷 node 是否存在重復
firstNode.setNextNode(endNode);
endNode.setNextNode(null);
addNodes2Map(firstNode,endNode);//創建成功之后,記錄創建記錄
return new Ship(true,firstNode);
}else{
firstNode = null;
endNode = null;
clearNode(firstNode,endNode);
}
return new Ship(false);
}
return new Ship(false);
}
}return null;
}
/**
* 當前您地圖中是否已經存在相關 node--防?兩個 node 重復
* @param nodes
* @return
*/
private static boolean checkCanBeCreate(Node... nodes){
for (Node node:nodes ) {
int[][] shipNodeMap = allMap.get(node.getNodeColor());
if(shipNodeMap[node.getX() - 1][node.getY() - 1 ] == 1 ){
return false;
}
}
return true;
}/**
* 將創建過的 node 記錄在記憶體地圖中
* @param nodes
* @return
*/
private static boolean addNodes2Map(Node... nodes){
for (Node node:nodes ) {
int[][] shipNodeMap = allMap.get(node.getNodeColor());
shipNodeMap[node.getX() - 1][node.getY() - 1 ] = 1;
}
return true;
}
/**
* 清除垃圾物件,防?記憶體泄漏
* @param nodes
*/
private static void clearNode(Node ... nodes){
for (Node node:nodes ) {
node.setNextNode(null);
node.setNextNode(null);
}}
}
以上物件為?個戰艦所需要的所有構成要素相關的核?類
炸彈相關物件及含義
public class Bomb {
private int killNodeNum;//當前?彈的威?,默認為 1,即默認只能炸毀?個節點所在的船艦--可
以增加多種模式
private int speed ; //炸彈運?速度,默認為 2, --炸彈每秒移動兩個 node 距離()
private NodeColor selfColor;// 豁免標識,防?炸彈誤炸??
/**
* 轟炸?標點的坐標,當炸彈擊中當前坐標時,通過判斷當前點在地?地圖中是否存在 node,如果
存在則將該敵?
* 的 node 物件查找到并修改其顏?為"NodeColor.GRAY", ?當前 node 所屬的 ship,執?戰損評
估邏輯,如果當前
* ship 的所有 node 顏?都為"NodeColor.GRAY",即當前 ship 被擊毀
*/
private int destXValue;
private int destYValue;/**
* 炸彈構造?法
* @param killNodeNum
* @param destXValue
* @param destYValue
*/
public Bomb(int killNodeNum, int destXValue, int destYValue) {
this.killNodeNum = killNodeNum;
this.destXValue = destXValue;
this.destYValue = destYValue;
}
public NodeColor getSelfColor() {
return selfColor;
}
public void setSelfColor(NodeColor selfColor) {
this.selfColor = selfColor;
}
public int getSpeed() {return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getKillNodeNum() {
return killNodeNum;
}
public void setKillNodeNum(int killNodeNum) {
this.killNodeNum = killNodeNum;
}
public int getDestXValue() {
return destXValue;
}
public void setDestXValue(int destXValue) {
this.destXValue = destXValue;
}public int getDestYValue() {
return destYValue;
}
public void setDestYValue(int destYValue) {
this.destYValue = destYValue;
}
}
2 游戲程序
- 游戲采用聯網對戰模式,雙方需要在規定時間內盡可能多的擊毀敵方戰艦;用戶可以自由創建自己的對戰房間,然后等待對手進入房間發起挑戰,對戰雙方分為紅藍顏色標識,紅方具有先行發射炮彈的權利,每方發射一發炮彈之后必須等待對方發射炮彈之后才能進行下一發炮彈的發射操作,戰艦位置由系統隨機生成;
- 對戰程序中,任意一方可以在海圖中選擇炮彈的打擊坐標,選中并擊發之后,根據炮彈的威力引數攻擊敵艦,目前默認為 1,即只能攻擊坐標中的戰艦;炮彈的運行軌跡和顏色根據本次發射炮彈的己方戰艦以及炮彈的豁免顏色決定(豁免顏色與本方的戰艦顏色一致);當炮彈擊中目標區域之后,判斷是否擊中敵方戰艦,并在游戲界面顯示戰果資訊,同時敵方顯示戰損資訊
- 當游戲規定時間到了卻沒有任何一方戰艦全部被擊毀時,根據雙方擊中的次數和戰果分數,得分高者獲勝,飯制失敗;如果在游戲規定時間內任意一方戰艦全部被擊毀,則另一方獲勝!
3. 游戲測驗
- 使用 junit 測驗框架,對游戲進行單元測驗,單元測驗需要在開發階段完成
- 功能測驗,部署測驗環境,按照用戶的各項功能分別進行測驗
- 壓力測驗,根據游戲設計指標,在特定環境(帶寬、硬體資源等)下,對游戲的運行能力進行壓力測驗
4. 添加其它形狀戰艦
- 方法一,在工廠類中增加新的戰艦型別,如同戰艦 a\b\c 三種型別一樣,基于Node 物件生成新的戰艦即可
- 方法二、理由現有戰艦型別組合,要求總希望增加的戰艦 D,正好可以是戰艦 a\c兩種型別組合可以得到,由于才有了雙向鏈表方式,只需要將兩個型別的鏈表連接起來即可實作
5. 如何添加戰艦移動功能
由于對戰雙方只有一次移動任何一艘戰艦的機會,則
- 第一步,則游戲的介紹中宣告添加此功能,該功能允許用戶在對戰程序中上下左右任意方向移動一次戰艦,且只允許使用一次,
- 第二步,在游戲界面的右下角顯示上下左右操作虛擬按鍵,當用戶已經使用過此功能時,則應該立即置灰,表示已經無法再次使用,目前代碼中我增加了相應限制,即不允許同一個點存在兩個 node,也就是說戰艦的移動不能覆寫到另一個戰艦(可通過代碼修改),
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/298116.html
標籤:其他
下一篇:初學docker容器
