java_文字城堡游戏(翁恺)(我稍微补了些提示性语句,以及落入陷阱的情况判断)
本程序包括了oop的,抽象,继承,封装,多态,低耦合,易扩展,框架化+数据的特性.
package oop.example; /*一个代码单元应该负责一个聚合的任务(也就是说,一个任务可以被看作是 一个逻辑单元)。一个方法应该实现一个逻辑操作,而一个类应该代表一定类型的实体。聚合 理论背后的要点是重用:如果一个方法或类是只负责一件定义明确的事情,那么就很有可能在 另外不同的上下文环境中使用。遵循这个理论的一个额外的好处是,当程序某部分的代码需要 改变时,在某个代码单元中很可能会找到所有需要改变的相关代码段。 从程序中识别出框架和数据,以代码实现框架,将部分功能以数据的方式加载,这样能在很大程度上实现可扩展性。*/ import java.util.HashMap; import java.util.Scanner; import java.util.logging.Handler;/*这是IDEA自动导入带来的坑,要么关闭自动导入(但是我觉得为Handler换个名字比较实在(和系统类名,本来就不建议嘛) 为此,我吃了不少苦头,一直感觉莫名其妙,以后遇到类似的多态报错问题,可以怀疑下是否和系统中的某个包下的类名冲突了(主要是自动导入功能要注意的) 还有eclipse虽然打开慢,但是编译运行快,不过它的报错似乎无法向idea那样及时的自动更新状态. 其实,IDEa的自动导入和自动优化导包虽然不错,但还算不上完美(自动优化可能会将你刚导入的还未用的包个删掉); 因此当出现了莫名其妙的错误时,导入的包也要看是否有多余的东西,不能完全依赖idea的自动化.*/ public class Game { /*成员域有一个Room引用类,一个HashMap容器,存储功能映射*/ private Room currentRoom; private HashMap<String, Handlerr> handlers = new HashMap<>(); /*Game主公共类的构造器constructor*/ public Game() { /*这里用到的this是当前这个Game对象的引用(会在main(args)时实例化出一个游戏game对象.*/ // System.out.println(this.getClass().getName());//查看一下this所指对象是啥类型(Game) //该构造器将 功能字符串和对应的功能类(Handler的若干子类)建立映射关系放入handlers容器中 /*从程序中识别出框架和数据,以代码实现框架, 将部分功能以数据的方式加载,(比如下面的操作)这样能在很大程度上实现可扩展性。*/ handlers.put("bye", new HandlerBye(this)); handlers.put("help", new HandlerHelp(this)); handlers.put("go", new HandlerGo(this)); createRooms(); } /*创建房间以及内置出口信息*/ public void createRooms() { Room outside, lobby, pub, study, bedroom;/*多余的逗号导致会错误全线变量混乱*/ //创建房间 lobby = new Room("大堂"); study = new Room("书房"); outside = new Room("城堡外"); pub = new Room("酒吧"); bedroom = new Room("卧室"); //初始化出口(同一个方间可以设置多个出口.(出口方向所通向的房间) /*然而,这里的通路需要小心,每个房间都应该有去有回,如果进入到一个新地方后没有提供通路,那就困死在里面啦.*/ lobby.setExit("south", outside); lobby.setExit("west", bedroom); pub.setExit("west", outside); study.setExit("south", lobby); outside.setExit("east", pub); outside.setExit("north", lobby); bedroom.setExit("east", lobby); /*初始化当前所在房间(位置)为outside(城堡外面)*/ currentRoom = outside; } public void printWelcome() { System.out.println(); System.out.println("欢迎!"); System.out.println(); System.out.println("这是一个超级无聊的城堡游戏"); System.out.println(); System.out.println("如果你需要帮助请输入:help"); System.out.println(); System.out.println("那么现在开始吧!"); System.out.println(); //System.out.println("你现在在" + currentRoom + " " + currentRoom.getExitDesc()); showPrompt(); System.out.println(); } //以下为提供用户(玩家)的命令(操作): /*不过此前应给创建好各个房间以及内置存储了各个房间可走的方向-下个位置房间键值对的信息.*/ public void goRoom(String dir) { Room nextRoom = currentRoom.getExit(dir); if (nextRoom == null) { System.out.println("那里没有门"); } else { currentRoom = nextRoom;//更新currentRoom. /*System.out.println("你现在在" + currentRoom + " " + currentRoom.getExitDesc()); System.out.println();*/ showPrompt(); } } /*showPrompt附属个goRoom()方法,以便反馈操作的结果*/ public void showPrompt() { System.out.println("你在" + currentRoom); System.out.print("出口有: "); System.out.println(currentRoom.getExitDesc()); System.out.println(); } /*开始游戏:*/ public void play() { Scanner in = new Scanner(System.in);//创建一个Scanner对象; while (true) { System.out.println("输入您的指令:"); String line = in.nextLine();//读入玩家的操作字符串 String[] words = line.split(" ");//预备解析玩家的操作,将处理的结果存入到一个String 数组中 Handlerr handler;//声明一个功能类对象的引用(对象管理者) //handlers容器是装载着功能类的对象(handlers容器对象属于Game对象) handler = handlers.get(words[0]);/* 执行处理第一个词语解析:查询word[0]动作将对用什么操作(功能); 返回一个功能类即Handlerr类的对象(到这里,handler已经指定好了功能对象(可能是 HandlerGo/HandlerHelp/HandlerBye中的某一个*/ /*为了提高健壮性,设置一个过渡字符串变量value*/ String value = " "; if (words.length >= 2) { /*有两个词语的合法操作中,第二个词一定是方向*/ value = words[1]; } /*如果上头返回的handler功能存在(即handler!=null):*/ if (handler != null) { handler.doCmd(value);/*通过功能类对象调用对应的功能(当然,现在提供的操作中有第二个词的只有go dir,ye也就是说,value如果非空且合法的话,应该是east/west/north/south中的某个*/ /*游戏是否终止的检查阶段:*/ if(!currentRoom.isSave()){break;}//当前是否落入死胡同.//此外,如果isSave()的具体实现在Room中发生变化,只要功能还是一样,就不会影响当前代码; /*bye操作比较特殊,在所有的玩家可执行的操作功能的功能对象中都从handlerr父类那里继承过了isBye()方法,只不过, 仅在通过HandlerBye功能对象调用isBye()方法判断结果是才返回true,默认情况下继承过来的都是return false的操作 即特地地判断一下是否终止游戏.(通过检查handler是否发出终止的信号(return true)*/ if (handler.isBye()) { break; } } } in.close();//结束从Console的输入需求 } public static void main(String[] args) { Game game=new Game(); game.printWelcome(); game.play(); System.out.println("感谢您的光临。再见!"); } }
package oop.example; import java.util.HashMap; class Room { private String description; boolean isOk=true; /*设有一个容器*/ private HashMap<String, Room> exits = new HashMap<String, Room>();//String型对象保存方向的字符串,Room型对象为房间 //constructor:描述这是个什么房间: public Room(String description) { this.description = description; } //重写toString以便打印对象(的指定属性(字段)) public String toString() { return description; } //设置(该房间指定出口方向通往的房间)(具体实现是将dir和room映射对放入容器exits对象中 public void setExit(String dir, Room room) { exits.put(dir, room); } //获取出口的描述信息:(将容器中保存的键(房间名)打印出来 public String getExitDesc() { StringBuffer sb = new StringBuffer();//StringBuffer对象中的内容可以方便变动,开销较小 int cnt=0; for (String s : exits.keySet()) {//迭代容器exits中保存的键值. sb.append(s);//挨个地将内容(这里是表示方向的字符串)添加到StringBuffer对象中. sb.append(" ");//追加一个空格来隔开, cnt++; }//这样就达到提示玩家,当前有那些方向可以走 //统一处理这些字符串 if(cnt==0){ System.out.print("没有其他方向可走啦,"); System.out.print("你落入陷阱了!!\n 游戏结束!"); isOk=false; } return sb.toString();//返回字符串 } //获取当前房间执行go direction操作时将会到达那个地方(房间)(这一个方法也是提供给game的接口 public Room getExit(String direction) { return exits.get(direction); } public boolean isSave(){return isOk;} }
package oop.example; abstract class Handlerr { protected Game game; /*在Handler类中创建一个Game对象的引用(管理者而已),用来记住*/ public Handlerr(Game game) { this.game = game; } public boolean isBye() { return false; } /*必须重写的*/ public abstract void doCmd(String cmd) ; }
package oop.example; class HandlerBye extends Handlerr { public HandlerBye(Game game) { super(game);/*super()在不同的子类(继承自不同父类)的时候,所代表的的方法也不同,此处是 oop.example.Handlerr @Contract(pure = true) public Handlerr(Game game) 即当前类的父类Handlerr类的构造方法.*/ /*当然,super一般不用写,系统会自加上,淡入如果构造器有参数的时候,那么就需要传参个super()了*/ } /*super()方法:(直接父类对象的引用。可以通过super.*来 访问和调用父类中被子类覆盖(重写)的方法或属性)*/ @Override public boolean isBye() { return true; } @Override public void doCmd(String cmd) { /*空*/ } }
package oop.example; public class HandlerGo extends Handlerr { public HandlerGo(Game game) { super(game); } @Override public void doCmd(String cmd) { game.goRoom(cmd); } }
package oop.example; public class HandlerHelp extends Handlerr { public HandlerHelp(Game game) { super(game); } @Override public void doCmd(String cmd) { System.out.println("迷路了吗?可以输入:go/bye/help 如:\t go east"); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-06-12 编译原理_文法分析_匹配括号
2023-06-12 C++构造函数和数组