我有Tile
代表游戏二维世界中的牌。瓷砖的4面可以有任意数量的墙。我现在有这样的事情:
interface Tile {
boolean isWallAtTop();
boolean isWallAtRight();
boolean isWallAtLeft();
boolean isWallAtBottom();
}
在其他地方我也有16张图片,每张图片都有一张图片。像这样:
static final Image WALLS_ALL_AROUND = ...
static final Image WALL_ON_TOP_AND_RIGHT = ...
/* etc etc all 16 possibilities */
我想写一个
static Image getWallImage(Tile tile)
我想要避免是对经历诸如
之类的可能性的折磨if (tile.isWallTop && tile.isWallRight
&& !tile.isWallBottom && !tile.isWallLeft) {
return WALL_ON_TOP_AND_RIGHT;
}
有没有人知道这样做的可行方法?
答案 0 :(得分:15)
Go go小工具位掩码。对每个瓷砖使用4位掩模,说明哪一面有墙。
A B C D
位A表示顶部的墙,B表示右侧,C表示底部,D表示左侧。定义常量以帮助您在逻辑上与掩码相交,即
if (tile.Walls & (WALL_LEFT | WALL_RIGHT))
// Do stuff
为了找到图像,这个4位掩码产生16种可能性。使用它作为图像“数组”的索引,这样您就可以毫不费力地直接找到正确的图像。
答案 1 :(得分:4)
tile对象是否有其他属性?如果不是(或者你可以将它们分解出来),你可以将tile对象本身变成16个常量的枚举,并使用Tile.getImage()
方法返回传递给构造函数的固定图像。这称为Flyweight pattern:
class Tile {
public final boolean isWallAtTop;
public final boolean isWallAtRight;
public final boolean isWallAtLeft;
public final boolean isWallAtBottom;
public final Image image;
private Tile(boolean top, boolean right, boolean left,
boolean bottom, Image image)
{
this.isWallAtTop = top;
this.isWallAtRight = right;
this.isWallAtLeft = left;
this.isWallAtBottom = bottom;
this.image = image;
}
public static final Tile WALLS_ALL_AROUND =
new Tile(true, true, true, true, new Image("allWalls.png"))
// more constants here, plus other methods that work with
// only the wall data
}
在Java中,您甚至可以将其实现为“真正的”枚举。
对于由图块组成的地图,您可以拥有一个简单的二维Tile引用数组,或者如果您需要其他数据用于单个图块,则需要另一个包含“其他数据”的SpecificTile
类以及对上面一个Tile对象的引用。
答案 2 :(得分:2)
我建议像下面那样创建一个标志枚举。
[Flags]
public enum WallLocations
{
None = 0,
Left = 1,
Right = 2,
Top = 4,
Bottom = 8
}
然后,您可以使用字典从墙壁位置映射到图像。
Dictionary<WallLocations, Image> map = new Dictionary<WallLocations, Image>();
map.Add(WallLocations.None, image0000);
map.Add(WallLocations.Left, image1000);
map.Add(WallLocations.Right, image0100);
map.Add(WallLocations.Top, image0010);
map.Add(WallLocations.Bottom, image0001);
map.Add(WallLocations.Left | WallLocations.Right, image1100);
// ....
至少在C#中,您还可以使用所有16个案例扩展枚举定义。
[Flags]
public enum WallLocations
{
None = 0,
Left = 1,
Right = 2,
Top = 4,
Bottom = 8,
LeftAndRight = Left | Right,
LeftAndTop = Left | Top,
LeftAndBottom = Left | Bottom,
RightAndTop = Right | Top,
RightAndBottom = Left | Bottom,
TopAndBottom = Top | Bottom,
AllExceptLeft = Right | Top | Bottom,
AllExceptRight = Left | Top | Bottom,
AllExceptTop = Left | Right | Bottom,
AllExceptBottom = Left | Right | Top,
All = Left | Right | Top | Bottom
}
答案 3 :(得分:0)
你能不能用旗帜枚举做什么?
答案 4 :(得分:0)
您应该将墙配置放入单个变量中,并构建此变量到平铺图像的映射。
答案 5 :(得分:0)
不是将WALLS_ALL_AROUND
设为图像,而是将其作为包含图像的对象,以及处理允许的移动和诸如此类所需的任何其他逻辑。在Location
对象中,您可以将walls
属性设置为WALLS_ALL_AROUND
,您可以查询该图像并处理与其他墙相关的逻辑。
由于每组图像只需要16个这些(不可变)对象的实例(如果你只有一组图像,每个图像可能是Tile
的单个子级),你也可以节省内存。 / p>
答案 6 :(得分:0)
一个体面的OO解决方案可能涉及Strategy Pattern。一种可能的实现方式是使用WallConfiguration类和WallFactory来创建它们。然后,Tile将包含WallConfiguration。实现(C ++风格)看起来像这样:
class Tile
{
private:
WallConfiguration walls;
// Other Tile data
public:
enum Walls
{
TOP,
BOTTOM,
LEFT,
RIGHT,
TOP_RIGHT,
TOP_LEFT
// Fill in the rest
}; //Enums have a place!
Tile(Walls wall)
{
walls = WallFactory.getConfiguration(wall);
}
这方面的一个有趣的优点是,现在,当你添加爆炸墙的能力(并且来吧......你知道你要去,'因为我们都喜欢把事情搞砸了),你可以将这个职责添加到WallConfiguration类中,例如,当你炸掉左墙时,它会知道如何获得正确的自身实例。