动态

详情 返回 返回

牧師與魔鬼 - 动态 详情

一、背景描述
牧師與魔鬼是一款益智遊戲,您將幫助牧師與魔鬼在規定時間內過河。河邊有三個牧師和三個魔鬼。他們都想去這條河的對岸,但只有一艘船,這艘船每次只能載兩個人。而且必須有一個人把船從一邊開到另一邊。在flash遊戲中,您可以單擊它們移動它們,然後單擊go按鈕將船移動到另一個方向。如果神父的人數超過了河兩邊的魔鬼,他們就會被殺死,遊戲就結束了。你可以用很多方法來嘗試。讓所有牧師都活着!祝你好運!

牧師與魔鬼.jpg
(圖片來源:百度百科)

二、MVC設計模式
MVC設計模式是一種軟件架構模式,它將軟件系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。模型負責封裝與業務邏輯相關的數據和方法,視圖負責顯示模型的數據,控制器負責處理用户的請求和更新模型和視圖。MVC設計模式的目的是實現一種動態的程序設計,使後續對程序的修改和擴展簡化,並且使程序某一部分的重複利用成為可能。MVC設計模式也有利於提高程序的可測試性、可維護性和可擴展性。

3fb15665714a8f434c0cdd8f5334fea.png
三、項目介紹

1、對象

對象 數量
牧師 3
魔鬼 3
1
陸地 2
河流 1

2、動作

動作 條件 效果
玩家點擊岸上角色 船上有空位 角色上船
玩家點擊船上角色 角色上岸
玩家點擊船 船上有至少一個角色 開船
玩家點擊restart 重新開始遊戲

3、代碼

4、項目展示

5、實現過程

(1)Director
public class Director : System.Object {

private static Director _instance;
public SceneController currentSceneController { get; set; }

public static Director getInstance() {
    if (_instance == null) {
        _instance = new Director ();
    }
    return _instance;
}

}

這段代碼是用C#語言實現的單例模式(Singleton Pattern)的一個例子。單例模式是一種創建型設計模式,它保證一個類只有一個實例,並提供一個全局訪問點。

這段代碼定義了一個名為Director的類,它有以下特點:

  • 它有一個私有的靜態字段_instance,用來存儲唯一的實例。
  • 它有一個私有的無參構造函數,防止其他類通過new關鍵字創建它的實例。
  • 它有一個公共的靜態方法getInstance,用來獲取或創建唯一的實例。如果_instance為空,就創建一個新的Director對象並賦值給它;如果不為空,就直接返回它。
  • 它有一個公共的屬性currentSceneController,用來設置或獲取當前的場景控制器。

(2)Controller:代碼
這段代碼定義了一個名為FirstController的類,它繼承了MonoBehaviour類,並實現了SceneController和UserAction兩個接口。它有以下特點:

public CoastController fromCoast;
    public CoastController toCoast;
    public BoatController boat;
    private MyCharacterController[] characters;

它有一個常量water_pos,用來表示水面的位置。

它有一個UserGUI類型的字段userGUI,用來顯示用户界面。

它有兩個CoastController類型的字段fromCoast和toCoast,分別表示起始岸和目標岸。

它有一個BoatController類型的字段boat,表示船。

它有一個MyCharacterController類型的數組characters,用來存儲六個角色對象(三個牧師和三個魔鬼)。

void Awake() {
        Director director = Director.getInstance ();
        director.currentSceneController = this;
        userGUI = gameObject.AddComponent <UserGUI>() as UserGUI;
        characters = new MyCharacterController[6];
        loadResources ();
    }

重寫了Awake方法,在該方法中獲取Director單例對象,並將自己設置為當前的場景控制器。然後添加UserGUI組件,並初始化characters數組。最後調用loadResources方法加載資源。

public void loadResources() {
        GameObject water = Instantiate (Resources.Load ("Perfabs/Water", typeof(GameObject)), water_pos, Quaternion.identity, null) as GameObject;
        water.name = "water";

        fromCoast = new CoastController ("from");
        toCoast = new CoastController ("to");
        boat = new BoatController ();

        loadCharacter ();
    }

實現了loadResources方法,在該方法中實例化水面對象,並給它命名為"water"。然後創建fromCoast、toCoast和boat對象,並調用loadCharacter方法加載角色對象。

private void loadCharacter() {
        for (int i = 0; i < 3; i++) {
            MyCharacterController cha = new MyCharacterController ("priest");
            cha.setName("priest" + i);
            cha.setPosition (fromCoast.getEmptyPosition ());
            cha.getOnCoast (fromCoast);
            fromCoast.getOnCoast (cha);

            characters [i] = cha;
        }

        for (int i = 0; i < 3; i++) {
            MyCharacterController cha = new MyCharacterController ("devil");
            cha.setName("devil" + i);
            cha.setPosition (fromCoast.getEmptyPosition ());
            cha.getOnCoast (fromCoast);
            fromCoast.getOnCoast (cha);

            characters [i+3] = cha;
        }
    }

實現了loadCharacter方法,在該方法中循環創建三個牧師和三個魔鬼對象,並給它們命名為"priest0"到"priest2"和"devil0"到"devil2"。然後將它們放置在fromCoast的空位上,並讓它們上岸。同時將它們添加到fromCoast和characters數組中。

public void moveBoat() {
        if (userGUI.status != 0 ) return;
        if (boat.isEmpty ())
            return;
        boat.Move ();
        userGUI.status = check_game_over ();
    }

實現了moveBoat方法,在該方法中判斷遊戲狀態是否為0(未結束),如果不是則返回。然後判斷船是否為空,如果是則返回。否則調用boat的Move方法移動船,並更新遊戲狀態。

public void characterIsClicked(MyCharacterController characterCtrl) {
        if (userGUI.status != 0 ) return;
        if (characterCtrl.isOnBoat ()) {
            CoastController whichCoast;
            if (boat.get_to_or_from () == -1) { // to->-1; from->1
                whichCoast = toCoast;
            } else {
                whichCoast = fromCoast;
            }

            boat.GetOffBoat (characterCtrl.getName());
            characterCtrl.moveToPosition (whichCoast.getEmptyPosition ());
            characterCtrl.getOnCoast (whichCoast);
            whichCoast.getOnCoast (characterCtrl);

        } else {                                    // character on coast
            CoastController whichCoast = characterCtrl.getCoastController ();

            if (boat.getEmptyIndex () == -1) {        // boat is full
                return;
            }

            if (whichCoast.get_to_or_from () != boat.get_to_or_from ())    // boat is not on the side of character
                return;

            whichCoast.getOffCoast(characterCtrl.getName());
            characterCtrl.moveToPosition (boat.getEmptyPosition());
            characterCtrl.getOnBoat (boat);
            boat.GetOnBoat (characterCtrl);
        }
        userGUI.status = check_game_over ();
    }

實現了characterIsClicked方法,在該方法中判斷遊戲狀態是否為0(未結束),如果不是則返回。然後判斷角色對象是否在船上,如果是則執行下列操作:

聲明一個CoastController類型的變量whichCoast,用來表示目標岸。
判斷船的位置是在起始岸還是目標岸,如果是目標岸,則將whichCoast賦值為toCoast;如果是起始岸,則將whichCoast賦值為fromCoast。
調用boat的GetOffBoat方法讓角色對象下船,並傳入角色對象的名字作為參數。
調用角色對象的moveToPosition方法讓角色對象移動到whichCoast的空位上,並傳入空位座標作為參數。
調用角色對象的getOnCoast方法讓角色對象上岸,並傳入whichCoast作為參數。
調用whichCoast的getOnCoast方法讓whichCoast記錄角色對象,並傳入角色對象作為參數。
如果角色對象不在船上,則執行下列操作:

聲明一個CoastController類型的變量whichCoast,用來表示當前岸,並調用角色對象的getCoastController方法獲取當前岸。
判斷船是否已滿,如果是則返回。
判斷船的位置是否與當前岸一致,如果不是則返回。
調用whichCoast的getOffCoast方法讓角色對象下岸,並傳入角色對象的名字作為參數。
調用角色對象的moveToPosition方法讓角色對象移動到船的空位上,並傳入空位座標作為參數。
調用角色對象的getOnBoat方法讓角色對象上船,並傳入boat作為參數。
調用boat的GetOnBoat方法讓船記錄角色對象,並傳入角色對象作為參數。
最後更新遊戲狀態。

int check_game_over() {    // 0->not finish, 1->lose, 2->win
        int from_priest = 0;
        int from_devil = 0;
        int to_priest = 0;
        int to_devil = 0;

        int[] fromCount = fromCoast.getCharacterNum ();
        from_priest += fromCount[0];
        from_devil += fromCount[1];

        int[] toCount = toCoast.getCharacterNum ();
        to_priest += toCount[0];
        to_devil += toCount[1];

        if (to_priest + to_devil == 6)        // win
            return 2;

        int[] boatCount = boat.getCharacterNum ();
        if (boat.get_to_or_from () == -1) {    // boat at toCoast
            to_priest += boatCount[0];
            to_devil += boatCount[1];
        } else {    // boat at fromCoast
            from_priest += boatCount[0];
            from_devil += boatCount[1];
        }
        if (from_priest < from_devil && from_priest > 0) {        // lose
            return 1;
        }
        if (to_priest < to_devil && to_priest > 0) {
            return 1;
        }
        return 0;            // not finish
    }

實現了check_game_over方法,在該方法中判斷遊戲是否結束,如果結束則返回相應的狀態碼,如果未結束則返回0。判斷遊戲是否結束的邏輯如下:

聲明四個整型變量from_priest、from_devil、to_priest和to_devil,分別表示起始岸和目標岸的牧師和魔鬼數量,並初始化為0。
調用fromCoast和toCoast的getCharacterNum方法獲取各自的牧師和魔鬼數量,並分別累加到相應的變量中。
如果目標岸的牧師和魔鬼數量之和等於6,説明所有角色都過河了,遊戲勝利,返回2。
調用boat的getCharacterNum方法獲取船上的牧師和魔鬼數量,並根據船的位置累加到相應的變量中。
如果起始岸或目標岸的魔鬼數量多於牧師數量,且牧師數量大於0,説明有牧師被吃掉了,遊戲失敗,返回1。
否則遊戲未結束,返回0。

四、參考資料:
牧師與魔鬼
Unity3D遊戲編程-牧師與惡魔
Unity使用MVC架構製作牧師與魔鬼小遊戲

Add a new 评论

Some HTML is okay.