作为一个相当绿色的Java编码器,我为自己设置了一个尝试编写简单文本冒险的巨大挑战.不出所料,我已经遇到了困难!
我正在尝试为我的Location类提供一个属性来存储它包含的出口.我为此使用了一个布尔数组,基本上保存表示每个出口的true/false值.我并不完全相信
a)这是最有效的方法
b)我正在使用正确的代码来填充数组.
我会很感激任何和所有的反馈,即使它是一个完整的代码超载!
目前,在实例化一个Location时,我会生成一个String,我将其发送到setExits方法:
String e = "N S U";
secretRoom.setExits(e);
Run Code Online (Sandbox Code Playgroud)
在Location类中,setExits如下所示:
public void setExits(String e) {
if (e.contains("N"))
bexits[0] = true;
else if (e.contains("W"))
bexits[1] = true;
else if (e.contains("S"))
bexits[2] = true;
else if (e.contains("E"))
bexits[3] = true;
else if (e.contains("U"))
bexits[4] = true;
else if (e.contains("D"))
bexits[5] = true;
}
Run Code Online (Sandbox Code Playgroud)
我会说实话,我认为这看起来特别笨重,但我想不出另一种方法.我现在还不完全确定如何编写getExits方法......
欢迎任何帮助!
gex*_*ide 127
最有效和最富有表现力的方式如下:
使用enum
s作为退出并使用a EnumSet
来存储它们.EnumSet
是一个有效的Set
实现,它使用位字段来表示枚举常量.
以下是如何做到这一点:
public enum Exit { North, West, South, East, Up, Down; }
EnumSet<Exit> set = EnumSet.noneOf(Exit.class); // An empty set.
// Now you can simply add or remove exits, everything will be stored compactly
set.add(Exit.North); // Add exit
set.contains(Exit.West); // Test if an exit is present
set.remove(Exit.South); //Remove an exit
Run Code Online (Sandbox Code Playgroud)
枚举设置将所有出口存储在一个long
内部,因此您的代码具有表现力,快速,并节省大量内存.
Ros*_*rew 29
你有没有理由用String
s 做这个并没有传入booleans
,即
public void setExits(boolean N, boolean E, boolean S, boolean W, boolean U, boolean D)
Run Code Online (Sandbox Code Playgroud)
或者有制定者?
public void setNorthOpen(boolean open)
{
bexits[4] = open;
}
Run Code Online (Sandbox Code Playgroud)
其次,为什么你将出口存储为一个布尔数组,它是一个小的有限集,为什么不呢
boolean N,S,E,W,U,D;
Run Code Online (Sandbox Code Playgroud)
那时你不需要跟踪每个方向的数组中的数字.
也
这是一个正确的答案(如果不是像@gexicide那样完全最优)但我完全鼓励任何人在这里查看其他答案,以便以不同的方式了解如何在Java中完成任务.
备查
有效的代码属于Code Review,而不是Stack Overflow.虽然正如@kajacx指出的那样,这段代码实际上不应该起作用.
kaj*_*acx 15
好的,首先,你的setExits()
方法不会按预期工作,链接if-elseif将最大限度地执行1个代码分支,例如:
if (e.contains("N"))
bexits[0] = true;
else if (e.contains("W"))
bexits[1] = true;
Run Code Online (Sandbox Code Playgroud)
即使e
同时包含N
和W
,只bexits[0]
将被设置.此方法也只会添加退出(例如,调用setExits("")
不会删除任何现有的退出.
我会将该方法更改为:
bexits[0] = e.contains("N");
bexits[1] = e.contains("W");
...
Run Code Online (Sandbox Code Playgroud)
此外,我绝对不会记得北方在索引0上,西方在1上,...所以通常的做法是使用最终的静态常量命名索引:
public static final int NORTH = 0;
public static final int WEST = 1;
...
Run Code Online (Sandbox Code Playgroud)
然后你可以用你的setExits
方法写:
bexits[NORTH] = e.contains("N");
bexits[WEST] = e.contains("W");
...
Run Code Online (Sandbox Code Playgroud)
(更容易读)
最后,如果您希望代码更加精心安排,您可以创建一个Exits
表示可用出口的类,并由布尔数组支持.然后在创建String的地方,您可以创建此类,并自己保存,然后生成然后解析字符串.
编辑:
作为@gexicide的答案,有一个非常方便的类EnumSet
,可能比bollean数组更好地表示出口.
将EnumSet
在对方的回答是做到这一点的最好办法,我只是想,虽然加上一句话,就是为将来当你开始就在你是否可以移动但如果你正在向不看.
和EnumSet
你一样EnumMap
.
如果你定义一个Room类/接口,那么你可以在Room类中
Map<Direction, Room> exits = new EnumMap<>(Direction.class);
Run Code Online (Sandbox Code Playgroud)
您现在可以将链接添加到地图中,如下所示:
exits.put(Direction.NORTH, theRoomNorthOfMe);
Run Code Online (Sandbox Code Playgroud)
然后你的代码在房间之间移动可以是非常通用的:
Room destination=currentRoom.getExit(directionMoved);
if (destination == null) {
// Cannot move that way
} else {
// Handle move to destination
}
Run Code Online (Sandbox Code Playgroud)
我将创建一个Exit枚举,并在location类上设置一个Exit对象列表.
所以它会是这样的:
public enum Exit { N, S, E, W, U, D }
List<Exit> exits = parseExits(String exitString);
location.setExits(exits);
Run Code Online (Sandbox Code Playgroud)
鉴于您的代码是什么样的,这是我可以提出的最具可读性的实现:
public class Exits {
private static final char[] DIRECTIONS = "NSEWUD".toCharArray();
public static void main(String... args) {
String input = "N S E";
boolean[] exits = new boolean[DIRECTIONS.length];
for(int i = 0; i< exits.length; i++) {
if (input.indexOf(DIRECTIONS[i]) >= 0) {
exits[i] = true;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
话虽如此,有一些更清洁的解决方案可能.我个人会用枚举和一个EnumSet
.
顺便说一句,您的原始代码是不正确的,因为它将数组中的大多数值设置为true.