Javascript - 查找表的结构

时间:2013-08-02 15:24:19

标签: javascript data-structures

我不太确定标题中的措辞是否准确描述了我要做的事情,请允许我解释一下:

假设在游戏中,你可以从升级中获得不同类型的积分。 但是每个级别获得的每种类型的点数都可以是任意的。

例如, 每2级我得3 offensive分。 但是我在2级,4级,5级和6级得到2 defensive分。 除了第一个,每个级别可能有1 supportive个点。


现在这就是我所做的:

//Suppose I have my hero
var Sylin = new Hero();
Sylin.Level = 5;

//My goal is then to set
//    Sylin.OffensivePoint to 6 
//    Sylin.DefensivePoint to 6
//    Sylin.SupportivePoint to 4 

Sylin.prototype.OffensivePoint = function() {
    return 3*Math.floor(this.Level/2);
};

Sylin.prototype.DefensivePoint = function() {
    var defPoint = 0;
    for(var i=2; i <= this.Level; i++) {
        //maximum level being 6
        if(i==2 || i >= 4) {
            defPoint += 2;
        }
    }
    return defPoint;
};

Sylin.prototype.SupportivePoint = function() {
    return this.Level - 1;
};

这一切都很好,但是如果最高级别被延长,点数列表将被更新,然后它变得非常笨拙,特别是如果我有这样的事情: 每3级有2分,但是9级和13级有3分或者显然缺乏模式,所以我不能像OffensivePoint()所做的那样。


我对这类问题的一般想法是这样的结构:

级别 TotalPoint
。 。 1。 。 。 。 。一个
。 。 2。 。 。 。 。 b
。 。 3。 。 。 。 。 ç
。 。 4。 。 。 。 。 d
。 。 5。 。 。 。 。 Ë
等等,直到达到最高水平

在代码中,我可能会这么做:

Sylin.prototype.talentPoint = function() {
    return readTalentPointTable(this.Level); //?
};

但是如果有20种等级可以获得5种不同类型的分数,那么这仍然会变得非常复杂,比如:/



修改


好的,我可以这样做:

var OffensivePointTable = [0,0,2,2,4,6,8,8,8,10,12];
function getOffensivePoint(level) {
    return OffensivePointTable[level];
}

如果按照增加点数的级别或按上述运行总计存储数据会更容易吗?



编辑2


好的,我是否可以颠倒结构的顺序,首先查看类型,然后是水平?

var theTable = {
    o: [0,1,0,1,1,0,0,0],
    d: [0,0,2,0,2,0,2,0],
    s: [0,1,2,3,4,5,6,7]}

//then your CalculateStats:
Sylin.prototype.CalculateStats = function() {
    this.offensivePoint = 0;
    for(var i=1; i<= this.Level; i++) {
        this.offensivePoint += theTable[o][i];
    }
}

3 个答案:

答案 0 :(得分:1)

为什么不将点存储在对象数组中 -

var pointsTable = [{offensivePionts: 1, defensivePoints: 1}, {offensivePoints: 1, defensivePoints: 2}]; //extend for any level

然后通过引用corrent属性获得返回点 -

function getOffensivePoints(level) {
    return pointsTable[level]['offensivePoints'];
}

您可以使用addLevel等方法轻松扩展数据结构。

答案 1 :(得分:1)

您可以使用一个对象来存储每个表格中要增加的点数(我没有使用您的确切数字,但您明白了这一点):

var LevelPoints = {
  '1': {
      o: 1,
      d: 2,
      s: 1
  }
  '2': {
      o: 3,
      d: 1,
      s: 1
  }
  '3': {
      o: 1,
      d: 1,
      s: 0
  }
  '4': {
      o: 2,
      d: 3,
      s: 1
  }
  //etc.
}

例如,要访问级别2的进攻点增加,请使用LevelPoints['2'].o

我认为这需要大量的输入,但有时只是拥有所有数据会使事情变得更容易。使您的代码对可读并且易于更改总是很好。它也可以作为一个快速参考 - 如果你想知道在6级获得多少攻击点,你可以立即知道。无需破译任何程序代码。当然,这是个人喜好。程序方法更快,使用更少的内存,所以这取决于你是否值得。在这种情况下,差异可以忽略不计,因此我建议采用数据驱动的方法。

另请注意,我使用var来设置此对象。因为它可以被Sylin构造函数的所有实例使用,所以将其设置为实例变量(使用this)是浪费的,因为它将为Sylin的每个实例创建对象。使用var让他们共享它,节省内存。

或者,您可以在每个级别存储运行总计,但是IMO这需要更多的努力,没有充分的理由。写一个函数需要花费更少的时间:

Sylin.prototype.CalculateStats = function() {
    this.OffensivePoint = 0;
    this.DefensivePoint = 0;
    this.SupportivePoint = 0;

    for (var i = 1; i <= this.Level; i++) {
        this.OffensivePoint += LevelPoints[i].o;
        this.DefensivePoint += LevelPoints[i].d;
        this.SupportivePoint += LevelPoints[i].s;
    }
}

然后只要用户更改角色的级别,就可以运行此功能。无需传递关卡,因为该函数已经可以访问this.Level变量。

答案 2 :(得分:1)

当然,您始终可以创建所有点的硬编码数组,但您也可以简单地对异常进行硬编码,并在可能的情况下坚持使用算法。

只是一个想法......这需要你的英雄跟踪他的观点,而不是动态地重新编译它们,但这可能是一件好事。

//have a map for exceptions
var pointExceptionsMap = {
    '9': {
        off: 3 //3 points of offense on level 9
    }
};

Sylin.prototype.levelUp = function () {
    var ex = pointExceptionsMap[++this.level];

    //update offense points (should be in another function)
    this.offense += (ex && typeof ex.off === 'number')? 
        ex.o /*exception points*/: 
        this.level % 2? 0 : 2; //2 points every 2 levels

};

然后升级,您执行hero.levelUp()并获得积分hero.offense。我没有测试任何东西,但那是个主意。但是,如果您需要能够直接设置级别,则可以使用setLevel函数调用levelUp适当的次数,但是,您必须使用修饰符才能使用也趋于平稳。

您还可以使用我当前的想法,找到实现异常算法的有效方法。例如,您仍然可以动态编译攻击点的数量,然后根据异常在该结果中添加或删除点。因此,如果您需要每2个级别获得2个积分,而级别9则需要3个积分,这意味着向编译点添加1个额外点。但是,因为当你达到更高级别时,你想保留该异常,你也必须跟踪所有添加的异常点。

编辑:此外,没有什么可以阻止您将函数用作新的异常算法而不是简单的数字,如果您打算使算法可配置,您可以简单地允许用户覆盖默认值。例如,您可以使用公共updateOffense函数来封装逻辑,以便可以覆盖它。这与Strategy design pattern类似。

EDIT2:这是我试图解释的complete example,希望它有所帮助!

var Hero = (function () {

    function Hero() {
        this.level = 0;
        this.stats = {
            off: 1,
            def: 0
        };
    }

    Hero.prototype = {
        statsExceptions: {
            '3': {
                off: 3 //get 3 points
            },
            '6': {
                def: function () {
                    //some algorithm, here we just return 4 def points
                    return 4;
                }
            }
        },
        levelUp: function () {
            ++this.level;
            updateStats.call(this, 1);

        },
        levelDown: function () {
            updateStats.call(this, -1);
            --this.level;
        },
        setLevel: function (level) {
            var levelFn = 'level' + (this.level < level? 'Up' : 'Down');

            while (this.level !== level) {
                this[levelFn]();
            }
        },

        statsFns: {
            off: function () {
                return (this.level % 2? 0 : 2);
            },
            def: function () {
                return 1;
            }
        }
    };

    function updateStats(modifier) {
        var stats = this.stats,
            fns = this.statsFns,
            exs = this.statsExceptions,
            level = this.level,
            k, ex, exType;

        for (k in stats) {
            if (stats.hasOwnProperty(k)) {
                ex = exs[level];
                ex = ex? ex[k] : void(0);
                exType = typeof ex;

                stats[k] += (exType === 'undefined'?
                    /*no exception*/
                    fns[k].call(this) :
                    /*exception*/
                    exType === 'function' ? ex.call(this) : ex) * modifier;
            }
        }
    }

    return Hero;
})();

var h = new Hero();

console.log(h.stats);

h.setLevel(6);

console.log(h.stats);

h.setLevel(0);

console.log(h.stats);

h.levelUp();

console.log(h.stats);

//create another type of Hero, with other rules
function ChuckNorris() {
    Hero.call(this); //call parent constructor
}

ChuckNorris.prototype = Object.create(Hero.prototype);

//Chuck gets 200 offense points per level y default
ChuckNorris.prototype.statsFns.off = function () {
    return 200;
};

//Not exceptions for him!
ChuckNorris.prototype.statsExceptions = {};

console.info('Chuck is coming!');

var c = new ChuckNorris();

c.setLevel(10);

console.log(c.stats);