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");
}
}
posted @   xuchaoxin1375  阅读(22)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2023-06-12 编译原理_文法分析_匹配括号
2023-06-12 C++构造函数和数组
点击右上角即可分享
微信分享提示