翁凯老师java城堡游戏续
上次的问题这次大概有了一些解决
硬编码:运行时不能改变
软编码:运行时能够改变
主要体现在哈希表能添加对应的key与value
城堡游戏最终版(增加了操作指令(如go bye help)的扩展性)
主要思路:
上次说的对应关系可以用哈希表软编码,这里的对应关系是方向对应的房间。
于是我们就增加了房间的扩展性 这次是操作指令对应要执行的命令,
相应的我们就增加了操作指令的扩展性
用哈希表来使得操作指令与函数对应,但是哈希表里面的值只能是对象,不能是函数。
但是类里面含有函数,只需要让一个操作指令对应一个类,这样get(操作指令)得到的就是不同的类,让这些类里面共有一个函数docmd(进行操作的函数)【共有函数用继承】
只需要再定义一个父类的对象,就可以用相同的函数名执行不同的操作
代码
MyGame(主类)
import java.util.*;
public class MyGame {
static Scanner in = new Scanner(System.in);
private MyRoom curroom;
private HashMap<String,Handler> handlers = new HashMap<String,Handler>();
public void CreatRoom()
{
//制造房间
MyRoom outside,bedroom,bathroom,livingroom,diningroom,kitchen;
outside = new MyRoom("外面");
bedroom = new MyRoom("卧室");
livingroom = new MyRoom("客厅");
diningroom = new MyRoom("餐厅");
kitchen = new MyRoom("厨房");
bathroom = new MyRoom("浴室");
curroom = outside;
//制造周围的房间
// bed
//地图:->living bath
// din
// kitchen
outside.SetRound("east",livingroom);
livingroom.SetRound("north",bedroom);
livingroom.SetRound("south",diningroom);
livingroom.SetRound("west", outside);
livingroom.SetRound("east", bathroom);
bedroom.SetRound("south", livingroom);
diningroom.SetRound("north",livingroom);
diningroom.SetRound("south",kitchen);
kitchen.SetRound("north",diningroom);
bathroom.SetRound("west",livingroom);
bathroom.SetRound("up", livingroom);
livingroom.SetRound("down", bathroom);
/*扩展了各种方向,现在扩展命令》
因为哈希表不能传入函数,只能传入对象,所以能传入类,而类里面有函数,
后面再定义一个类,让它等于哈希表里面的对应命令的类,然后使用该类的函数就ok*/
}
public void Printstart()
{
System.out.println("欢迎来到三三与然然的家!(可以输入help寻求帮助)");
handlers.put("go",new HandlerGo(this));//如果没有继承,会报错因为是Handler为值,
handlers.put("help", new HandlerHelp(this));
handlers.put("bye", new HandlerBye(this));
CreatRoom();
}
public void Printcurroom()
{
System.out.println("你在: "+curroom);//curroom是MyRoom类
System.out.print("出口有: ");
System.out.println(curroom.GetExit());
//System.out.println();
}
public void play()
{
String[] words = new String[3];
String line,value;
Handler handler = new Handler(this);//这是哈希表里的handler类
while(true) {
value="";
line=in.nextLine();
words = line.split(" ");
handler=handlers.get(words[0]);//得到go bye等命令以确定handler的类型
if(words.length>1)
value=words[1];
if(handler!=null) {
handler.docmd(value);
if(handler.isBye())
break;
}
}
}
public void GoRoom(String direction)
{
MyRoom nextroom=null;
nextroom=curroom.GetRound(direction);//一个返回room的函数,查看direction方向有没有房间
if(nextroom==null)
System.out.println("这里没有门!");
else
curroom=nextroom;
}
public static void main(String[] args) {
MyGame game = new MyGame();
game.Printstart();
game.Printcurroom();
game.play();
}
}
MyRoom类
import java.util.*;
public class MyRoom {
private String description;
private HashMap<String,MyRoom> exit = new HashMap<String,MyRoom>();
//private MyRoom northroom,southroom,westroom,eastroom;//设置一个房间的东南西北的房间;
MyRoom(String description)//构造函数,对房间命名;
{
this.description=description;
}
public void SetRound(String dir,MyRoom room)
{
exit.put(dir, room);//设置方向和房间;
}
public MyRoom GetRound(String direction)
{
return exit.get(direction);
}
public String GetExit()
{
StringBuffer set = new StringBuffer();
for(String dir : exit.keySet()) {
set.append(dir);
set.append(" ");
}//将hash表的key付给set;
return set.toString();
}
public String toString()//description是MyRoom类里面的String
{
return description;
}
}
Handler类(父类)
public class Handler {
protected MyGame room;
public Handler(MyGame room)
{
this.room=room;
}
public void docmd(String cmd)
{
}
public boolean isBye()
{
return false;
}
}
HandlerGo类(执行go这个命令的类)
public class HandlerGo extends Handler{
public HandlerGo(MyGame room)
{
super(room);
}
public void docmd(String cmd)
{
room.GoRoom(cmd);
room.Printcurroom();
}
}
HandlerBye类(执行Bye这个命令的类)
public class HandlerBye extends Handler {
public boolean isBye()
{
System.out.println("欢迎下次再来,再见!");
return true;
}
public HandlerBye(MyGame room)
{
super(room);
}
}
HandlerHelp类(执行help这个命令的类)
public class HandlerHelp extends Handler {
public HandlerHelp(MyGame room)
{
super(room);
}
public void docmd(String cmd)
{
System.out.print("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
}
如何扩展
在这里要增加新的命令
只需要加一个哈希表,key为命令,value为操作的类
再新建一个操作的类就可以了
这样的话,代码其他地方需要改的除了多一个哈希表,就没有了。
总结
是对昨天城堡游戏哈希表以及扩展性的衍生,更加体会到了可扩展性的作用。联想到了是不是还可以加上更多其他的东西来衍生。
哈希表的值只能是对象
学习中的问题
HanderGo类里面的cmd操作是用的主类里面的函数,而要用这个函数,我们就的有一个主类的对象。
所以我们在父类里面创建了一个构造函数,将主类的对象传过来
这样的话子类也得添加一个构造函数,十分麻烦。
有没有其他的办法能在不添加构造函数的情况下完成这个目的呢?
这里父类的成员变量定义是protected
这个是啥意思,为什么不能用public??