JAVA学习笔记(六)城堡游戏优化(二)以框架+数据来提高代码的可扩展性

城堡游戏优化(二)以框架+数据来提高代码的可扩展性

在之前的文章JAVA学习笔记(五)城堡游戏的优化中,我们取消了代码的硬编码形式,而是使用框架,在Room类中建立了一个数据结构(哈希表),方向—房间的对应关系。还比如说我们创造了一些接口,setExit(),getExit()等等,避免了Game类对Room类的成员变量的直接调用。所以我们有了一种新的思路,尽量把硬编码形式改为使用框架+数据的形式来提高代码的可扩展性。那么我们也可以将命令(help,go,bye)的解析从硬编码形式改为框架+数据的形式。

if (words[0].equals("help")) {
    game.printHelp();
}
else if ( words[0].equals("go")) {
    game.goRoom(words[1]);
}
else if ( words[0].equals("bye")){
    break;
}

我们可以创造三个函数,分别是help,go,bye来表示命令,用函数来执行命令。但是Hash表可以存放类但不能存放函数,所以我们可以定义一个Handler类来处理命令,用Hash表来保存命令与Handler之间的关系。
首先我们要先创造一个Handler父类,用来表示命令的类型,然后在Game里面new一个Hashmap对象,用来存放命令关键字key和命令的类。

private HashMap<String,Handler> handlers = new HashMap<String, Handler>();

创建好了以后我们就需要创建四个类,父类Handler和三个子类,HandlerHelp,HandlerGo和HandlerBye,分别表示查看帮助的命令,前往下一个房间的命令,以及游戏结束的命令。
Handler:

package castlegame;

public class Handler {
    protected Game game;

    public Handler(Game game){
        this.game = game;
    }

    public void doCmd(String word){
    }
    public boolean isBye(){
        return false;
    }
}

HandlerHelp:

package castlegame;

public class HandlerHelp extends Handler{

    public HandlerHelp(Game game){
        super(game);
    }
    public void doCmd(String word){
        System.out.println("迷路了吗?你可以做的命令有:go | bye | help");
        System.out.println("如:\tgo east");
    }
}

HandlerGo:

package castlegame;

public class HandlerGo extends Handler{

    public HandlerGo(Game game){
        super(game);
    }
    public void doCmd(String word){
          game.goRoom(word);
    }
}

HandlerBye:

package castlegame;

public class HandlerBye extends Handler{

    public HandlerBye(Game game){
        super(game);
    }

    public boolean isBye(){
        return true;
    }
}

我们可以看到在四个类中我们创建了一些函数,也定义了一些成员变量,还创造了一些构造器,我们一个一个慢慢来说。
首先我们在Game类中,把所以跟三个命令有关的代码都删除,在main函数里面只留下创造game对象,输出游戏开始界面的代码,然后新创建一个play()函数,用来运行游戏和执行命令。

public static void main(String[] args) {
    Game game = new Game();
    game.printWelcome();
    game.play();
}

然后我们把之前本来存放在main函数里面的执行游戏的命令,放到play()函数里面,用函数来执行整个游戏。

public void play(){
    Scanner in = new Scanner(System.in);
    while (true) {
        String line = in.nextLine();
        String[] words = line.split(" ");
        Handler handler = handlers.get(words[0]);
        String value = "";
        if ( words.length > 1 )
            value = words[1];
        if ( handler != null ){
            handler.doCmd(value);
            if ( handler.isBye() )
                break;
        }
    }
    System.out.println("***********************************");
    System.out.println("游戏到此结束!");
    System.out.println("欢迎下次光临!");
    System.out.println("谢谢!");
    System.out.println("***********************************");
    in.close();
}

这里我们做了一些改动,首先是创造了一个handler对象,来让它等于我们输入的第一个字符串,只这样就相当于跳转到哈希表中我们相应要执行的命令,help对应help,go对应go,bye对应bye。再创建一个value对象来初始化为””。如果我们输入的字符串长度大于1,则使value等于我们输入的第二个字符串,此时的意思就是我们进行了GoRoom这个操作,也就是进入下一个房间,因为无论是help命令,还是bye命令,都是只有一个字符串的。如果第一个字符串不为null的话,则执行命令,也就是执行handler类的doCmd()函数。
在我们的三个handler子类的doCmd()函数中,分别执行的东西是不一样的。在HandlerHelp中执行的是输出帮助的一些语句,在go中是跳转到下一个房间,在bye中是返回一个布尔值,返回true并使循环结束,游戏结束并输出游戏结束的一些语句。那么我们就要在Game()对象中把对应的字典存放到哈希表里面了。

public Game()
{
    handlers.put("go",new HandlerGo(this));
    handlers.put( "bye",new HandlerBye(this));
    handlers.put("help",new HandlerHelp(this));
    createRooms();
}

因为我们在HandlerGo类里面的doCmd()函数中,需要调用到Game类里面的goRoom()函数,所以我们需要在Handler父类中protected一个Game对象,创建构造器,并在所有的子类中都创建一个构造器,用super()来得到父类中的Game对象,这样我们才可以在子类中调用到Game类中的函数,同时需要在Game类的Game()对象中,创建哈希表时,输入一个this,把这个对象给到所有的Handler子类中。这样我们就完成了代码的扩展。以下是Game和Room类的完整代码(四个Handler类的代码在上面):

Game:

package castlegame;

import java.util.HashMap;
import java.util.Scanner;

public class Game {
    private Room currentRoom;
    private HashMap<String,Handler> handlers = new HashMap<String, Handler>();

    public Game()
    {
        handlers.put("go",new HandlerGo(this));
        handlers.put( "bye",new HandlerBye(this));
        handlers.put("help",new HandlerHelp(this));
        createRooms();
    }

    public void play(){
        Scanner in = new Scanner(System.in);
        while (true) {
            String line = in.nextLine();
            String[] words = line.split(" ");
            Handler handler = handlers.get(words[0]);
            String value = "";
            if ( words.length > 1 )
                value = words[1];
            if ( handler != null ){
                handler.doCmd(value);
                if ( handler.isBye() )
                    break;
            }
        }
        System.out.println("***********************************");
        System.out.println("游戏到此结束!");
        System.out.println("欢迎下次光临!");
        System.out.println("谢谢!");
        System.out.println("***********************************");
        in.close();
    }

    private void createRooms(){
        Room pub,lobby,study,bedroom,bedroom1;
        //创造房间
        pub = new Room("小酒馆");
        lobby = new Room("大厅");
        study = new Room("书房");
        bedroom = new Room("卧室");
        bedroom1 = new Room("次卧");
        //设置出口
        pub.setExit("east", lobby);
        lobby.setExit("south" ,study);
        lobby.setExit("west" ,pub);
        lobby.setExit("east" ,bedroom1);
        study.setExit("north", lobby);
        study.setExit("east", bedroom);
        bedroom.setExit("west", study);
        bedroom1.setExit("west",lobby);

        currentRoom = pub;
    }

    public void printWelcome(){
        System.out.println("***********************************");
        System.out.println("欢迎来到城堡游戏!");
        System.out.println("这是一个超级无聊的小游戏。");
        System.out.println("如果需要帮助,请输入help。");
        System.out.println("那么我们开始游戏吧!");
        System.out.println("***********************************");
        System.out.println("现在你在"+currentRoom);
        showPrompt();
    }


    private void showPrompt(){
        System.out.println("你在"+ currentRoom);
        System.out.println("出口有:");
        System.out.println(currentRoom.getExitDesc());
    }

    public void goRoom(String direction) {
        Room nextRoom = currentRoom.getExit(direction);
        if(nextRoom == null){
            System.out.println("那里没有门!");
        }
        else{
            currentRoom = nextRoom;
            showPrompt();
        }
    }

    public static void main(String[] args) {
        Game game = new Game();
        game.printWelcome();
        game.play();
    }
}

Room:

package castlegame;

import java.util.HashMap;

public class Room {
    private String description;
    private HashMap<String,Room> exits = new HashMap<String, Room>();

    public Room(String description) {
        this.description = description;
    }

    public void setExit(String direction,Room room){
        exits.put(direction,room);
    }

    public String toString()
    {
        return description;
    }

    public String getExitDesc(){
        StringBuffer sb = new StringBuffer();
        for ( String direction : exits.keySet() ){
            sb.append(direction);
            sb.append(' ');
        }
        return sb.toString();
    }

    public Room getExit(String direction){
        return exits.get(direction);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值