设计查找地图

时间:2016-05-11 09:58:54

标签: java dictionary

我在设计正确的映射时遇到了问题。

我正在开发一个自上而下的RPG游戏,你只能在运行时看到地图的部分(块) - 当从一个块移动到另一个块时,会加载新的块数据。

取决于我的位置,加载了不同的数据。

目前我的代码看起来像这样(但肯定更长)

public static final int getChunkIdForPos(int x, int y){
    switch (x) {                    
    case 1248:  
        switch (y) {
        case 1247: return R.raw.overworld_512;
        case 1248: return R.raw.overworld_528;
        case 1249: return R.raw.overworld_544;
        default: break;}break;          
    case 1249:  
        switch (y) {
        case 1247: return R.raw.overworld_513;
        case 1248: return R.raw.overworld_529;
        case 1249: return R.raw.overworld_545;
        default: break;}break;
    }
    return R.raw.overworld_161;
}

问题是此代码不易阅读不易维护。关于如何做得更好的任何想法?

我在考虑使用Map<Integer,<Map<Integer,Integer>>来映射数据,但这需要先创建Map。这也意味着你带着很多“死亡”的人。对象作为键(对于SparseArray<SparseArray<>>

注意:您无法按照此answer - Implemention a Lookup Table

中的建议确定任何数学的返回值

选择此设计的原因是在不创建任何对象的情况下获得答案 - 查找只运行两个开关/案例语句并动态提供答案!

2 个答案:

答案 0 :(得分:0)

如果您使用的Point课程已经实施equalshashcode,则可以将其用作地图中的键。

现在实际的查找机制崩溃为:

static final Map<Point, Integer> lookup = new HashMap<>();

static {
    // Looks a lot like your case statement eh?
    lookup.put(new Point(1248, 1247), 512);
    lookup.put(new Point(1248, 1248), 528);
    lookup.put(new Point(1248, 1249), 544);
    lookup.put(new Point(1249, 1247), 513);
    lookup.put(new Point(1249, 1248), 529);
    lookup.put(new Point(1249, 1249), 545);
    // Could also be populated by other statics.
}

public static final int getChunkIdForPos(int x, int y) {
    Integer got = lookup.get(new Point(x, y));
    return got != null ? got : 161;
}

这样的优雅之处在于地图只构建一次。它是在可预测的时间内构建的(对类的第一次引用),并且可以通过其他模块添加(通过稍微调整)。

以下是正确实施Pointequals的{​​{1}}类的示例。

hashcode

答案 1 :(得分:0)

好的,首先要做的事情是:我将地图限制在10.000x10.000到256x256

  • 代码仍然无法维护!
  • 代码仍然无法扩展!
  • 仍然是最佳性能是使用开关/案例

处理此问题的正确方法是使用代码生成器。在一个单独的项目中,我没有限制创建一个世界地图编辑器,让我可以看到所有组合块。地图完成后(提示:您现在可以保存/加载地图)代码发射器会为您生成一个类。

Chunk editor

魔术是从codeEmitter类完成的:

int[][] worldMap = new int[256][256]; //generated via GUI
File file = new File(fileName);
BufferedWriter br = new BufferedWriter(new FileWriter(file));

//writing header

for (int dy = 0; dy < 256; dy++) {
    br.write("    public static int row_"+dy+"(int x){\n");
    br.write("        switch (x) {\n");
    for (int dx = 0; dx < 256; dx++) {
        br.write("        case " + dx + ": return " + worldMap[dx][dy] + ";\n");
    }
    br.write("        default: return 0;\n");
    br.write("        }\n");
    br.write("    }\n");
    br.write("\n");
}

//writing trailer

结果与问题

中请求的代码非常相似
 //this part of genCode is not explained above
 public static final int getIdForPos(int x, int y, int area){
    switch (y) {
    case 0: return row_0(x);
    case 1: return row_1(x);
    //.. lots of rows
    default: return 0;
    }
 }

 //but this part is generated with the code above
 public static int row_0(int x){
    switch (x) {
    case 0: return 4711;
    case 1: return 815;
    //.. lots of columns
    default: return 0;
    }
}