Java-翁恺进阶 城堡游戏的前世今生

初版代码

出版代码问题较多,耦合性大
主要存在两个类 Game与Room 并且两者分工不明确

package castle;

import java.util.*;

public class Game {
	private Room currentRoom;
	
	public Game()
	{
		creatRooms();
	}
	
	private void creatRooms()
	{
		Room outside, lobby,pub,study,bedroom;
		
	   // 制造房间
		outside = new Room("城堡外");
		lobby = new Room("大堂");
		pub = new Room("小酒吧");
		study = new Room("书房");
		bedroom = new Room("卧室");
		
		// 初始化房间的出口
		outside.setExits(null,lobby,study,pub);
		lobby.setExits(null,null,null,outside);
		pub.setExits(outside,bedroom,null,null);
		bedroom.setExits(null,null,null,study);
		
		currentRoom = outside;        //从城堡门外开始
	}
	
	
	private void printWelcome()
	{
		System.out.println();
		System.out.println("欢迎来到城堡!");
		System.out.println("这是一个超级无聊的游戏。");
		System.out.println("如果需要帮助,请输入'help'");
		System.out.println();
		System.out.println("现在你在:" + currentRoom);
		System.out.println("欢迎来到城堡");
		System.out.println("出口有:");
		if(currentRoom.northExit !=null)
			System.out.print("north");
		if(currentRoom.eastExit !=null)
			System.out.print("east");
		if(currentRoom.southExit !=null)
			System.out.print("south");
		if(currentRoom.westExit !=null)
			System.out.print("west");
		System.out.println();
		
	}
	
	//  以下为用户命令
	
	private void printHelp()
	{
		System.out.println("迷路了吗?你可以做的命令有:go bye help");
		System.out.println("如:\tgo east");
	}
	
	private void goRoom(String direction)
	{
		Room nextRoom = null;
		if(direction.equals("north")){
			nextRoom = currentRoom.northExit;
		}
		if(direction.equals("east")){
			nextRoom = currentRoom.eastExit;
		}
		if(direction.equals("south")){
			nextRoom = currentRoom.southExit;
		}
		if(direction.equals("west")){
			nextRoom = currentRoom.westExit;
		}
		
		if(nextRoom == null){
			System.out.println("那里没有门!");
		}
		else{
			currentRoom = nextRoom;
			System.out.println("你在"+ currentRoom);
			System.out.println("出口有:");
			if(currentRoom.northExit != null)
				System.out.println("norh");
			if(currentRoom.eastExit != null)
				System.out.println("east");
			if(currentRoom.southExit != null)
				System.out.println("south");
			if(currentRoom.westExit != null)
				System.out.println("west");		
			System.out.println();
		}
		
	}
	
	


	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		Game game = new Game();
		game.printWelcome();
		
		while (true){
			String line = in.nextLine();
			String[] words = line.split(" ");
			if ( words[0].equals("help")){
				game.printHelp();
			}else if ( words[0].equals("go")){
				game.goRoom(words[1]);
			}else if ( words[0].equals("bye")){
				break;
			}
		}
		
		System.out.println("感谢您的光临。再见!");
		in.close();
		

	}

}

package castle;

public class Room {
	public String description;
	public Room northExit;
	public Room southExit;
	public Room eastExit;
	public Room westExit;
	
	public Room(String description)
	{
		this.description = description;
	}
	
	public void setExits(Room north,Room east,Room south,Room west)
	{
		if(north != null)
			northExit = north;
		if(east != null)
			eastExit = east;
		if(south != null)
			southExit = east;
		if(west != null)
			westExit = west;
	}
	
	@Override
	public String toString()
	{
		return description;
	}



	public void southExit(Object object, Room lobby, Room study, Room pub) {
		// TODO Auto-generated method stub
		
	}

}

一版存在的问题
1.代码重复
2. 代码扩展性
例如当我们想要增加一个up方向的时候,我们发现我们需要在Room多加一个方向,同时Game中的许多方法 如 showPrompt goRoom 初始化等等,也都要加上代码去判断那个up

再版代码

仍然是两个类

package castle;

import java.util.Scanner;

public class Game {
    private Room currentRoom;
        
    public Game() 
    {
        createRooms();
    }

    private void createRooms()
    {
        Room outside, lobby, pub, study, bedroom;
      
        //	制造房间
        outside = new Room("城堡外");
        lobby = new Room("大堂");
        pub = new Room("小酒吧");
        study = new Room("书房");
        bedroom = new Room("卧室");
        
        //	初始化房间的出口
        outside.setExit("east", lobby);
        outside.setExit("south", study);
        outside.setExit("west", pub);
        lobby.setExit("west", outside);
        pub.setExit("east", outside);
        study.setExit("north", outside);
        study.setExit("east", bedroom);
        bedroom.setExit("west", study);
        lobby.setExit("up",pub);
        pub.setExit("down",lobby);//加入后与 Room 没有任何关系了

        currentRoom = outside;  //	从城堡门外开始
    }

    private void printWelcome() {
        System.out.println();
        System.out.println("欢迎来到城堡!");
        System.out.println("这是一个超级无聊的游戏。");
        System.out.println("如果需要帮助,请输入 'help' 。");
        System.out.println();

        showPrompt();
    }

    // 以下为用户命令

    private void printHelp() 
    {
        System.out.print("迷路了吗?你可以做的命令有:go bye help");
        System.out.println("如:\tgo east");
    }

    private void goRoom(String direction) 
    {
        Room nextRoom = currentRoom.getNext(direction);

        if (nextRoom == null) {
            System.out.println("那里没有门!");
        }
        else {
            currentRoom = nextRoom;
            showPrompt();
        }
    }

    public void showPrompt(){
        System.out.println("现在你在" + currentRoom);
        System.out.print("出口有:");
        System.out.print(currentRoom.getExitexplain());
        System.out.println();
    }
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		Game game = new Game();
		game.printWelcome();

        while ( true ) {
        		String line = in.nextLine();
        		String[] words = line.split(" ");
        		if ( words[0].equals("help") ) {
        			game.printHelp();
        		} else if (words[0].equals("go") ) {
        			game.goRoom(words[1]);
        		} else if ( words[0].equals("bye") ) {
        			break;
        		}
        }
        
        System.out.println("感谢您的光临。再见!");
        in.close();
	}

}

Room

package castle;

import java.util.HashMap;

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

/*
    public Room getNorth(){
        return northExit;
    }
*/

    public Room(String description) {
        this.description = description;
    }  //中文翻译

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

    public Room getNext(String direction) {
        return exits.get(direction);
    }

    @Override
    public String toString() {
        return description;
    }

    public String getExitexplain() {
        StringBuilder ret = new StringBuilder();
        for (String dir : exits.keySet()) {
            ret.append(dir);
            ret.append(' ');
        }
        return ret.toString();
    }

    public Room getExit(String direction){
        return exits.get(direction);

    }
}

一版到二版进步很多

  1. 消除了代码的重复性,利用了showPrompt()方法进行消除
  2. 利用HashMap去存放 key与value这样使得 我们可以任意添加各种方向,而不用改动多处代码,这就是因为我们使两类之间,如一些成员变量设为private,或者通过其他的框架代码 使之不能直接通过这个类去访问另一个类,而是就在那个类本身中进行。
  3. 修改了goRoom 让本身做一些事情增加了getExit(String direction)
  4. “硬编码”到容器

三版

主要就是实现了框架与数据的结合,构造函数去记录传递数据
实现了 各种方法的指令化

package castle;

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("help",new HandlerHelp(this));
        handlers.put("bye",new HandlerBye(this));
//在写一个方法的时候,如果该方法需要一个该类的对象做参数的时候,通常传入this代指该类的对象

        createRooms();
    }

    private void createRooms()
    {
        Room outside, lobby, pub, study, bedroom;
      
        //	制造房间
        outside = new Room("城堡外");
        lobby = new Room("大堂");
        pub = new Room("小酒吧");
        study = new Room("书房");
        bedroom = new Room("卧室");
        
        //	初始化房间的出口
        outside.setExit("east", lobby);
        outside.setExit("south", study);
        outside.setExit("west", pub);
        lobby.setExit("west", outside);
        pub.setExit("east", outside);
        study.setExit("north", outside);
        study.setExit("east", bedroom);
        bedroom.setExit("west", study);
        lobby.setExit("up",pub);
        pub.setExit("down",lobby);//加入后与 Room 没有任何关系了

        currentRoom = outside;  //	从城堡门外开始
    }

    private void printWelcome() {
        System.out.println();
        System.out.println("欢迎来到城堡!");
        System.out.println("这是一个超级无聊的游戏。");
        System.out.println("如果需要帮助,请输入 'help' 。");
        System.out.println();

        showPrompt();
    }

    // 以下为用户命令

    public void goRoom(String direction)
    {
        Room nextRoom = currentRoom.getExit(direction);

        if (nextRoom == null) {
            System.out.println("那里没有门!");
        }
        else {
            currentRoom = nextRoom;
            showPrompt();
        }
    }

    public void showPrompt(){
        System.out.println("现在你在" + currentRoom);
        System.out.print("出口有:");
        System.out.print(currentRoom.getExitexplain());
        System.out.println();
    }

    public void play(){
        Scanner in = new Scanner(System.in);
        while ( true ) {
            String line = in.nextLine();
            String[] words = line.split(" ");
            String value="";
            Handler handler = handlers.get(words[0]);
            if(words.length>1)
                value=words[1];
            if (handler != null)
                handler.doCmd(value);
            if (handler.isBye())
                break;

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

        System.out.println("感谢您的光临。再见!");
	}

}

整体大概这个样子,之后再想添加别的功能直接添加类就好了。
在这里插入图片描述

四版

利用内部类去实现一个个指令
Handler为接口,在Game.java构造函数里用匿名类完成go,bye,help功能
因为这样可以直接访问类内部的成员变量 而非要进行刻意记录传递值

// Game.java
public class Game {
    private Room currentRoom;
    private HashMap<String, Handler> handlers = new HashMap<String, Handler>();
    protected ArrayList<String> cmds = new ArrayList<String>();
 
    public Game() {
        handlers.put("bye", new Handler() {
            @Override
            public void doCmd(String word) {
 
            }
 
            @Override
            public boolean isBye() {
                return true;
            }
        });
        handlers.put("help", new Handler() {
            @Override
            public void doCmd(String word) {
                System.out.println("迷路了吗?你可以做的命令有:" + cmds);
 
                System.out.println("如:\tgo east");
            }
 
            @Override
            public boolean isBye() {
                return false;
            }
        });
        handlers.put("go", new Handler() {
            @Override
            public void doCmd(String word) {
                goRoom(word);
            }
 
            @Override
            public boolean isBye() {
                return false;
            }
        });
        for (String cmd : handlers.keySet()) {
            cmds.add(cmd);
        }
 
        createRooms();
 
    }
     
     
// Handler.java
package castle;
 
public class Handler {
    public void doCmd(String word) {
    }
 
    public boolean isBye() {
        return false;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_46243503/article/details/106202134