Skip to content Skip to sidebar Skip to footer

Javascript - Structure For A Look-up Table

I am not quite sure if the wording in the title accurately describes what I am looking to do, allow me to explain: Suppose in a game, you get different type of points from leveling

Solution 1:

You could use an object to store the amount of points to increment at each table (I didn't use your exact numbers, but you get the idea):

varLevelPoints= {
  '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.
}

For example, to access the offensive point increase at level 2, use LevelPoints['2'].o.

This requires a lot of typing I suppose, but sometimes just having all the data there makes things easier. Making your code readable to you and easy to change is always nice. It's also useful as a quick reference—if you're wondering how many offensive points will be gained at level 6, you can know immediately. No need to decipher any procedural code. Of course, this is personal preference. Procedural approaches are faster and use less memory, so it's up to you whether that's worth it. In this case the difference will be negligible, so I recommend the data-driven approach.

Also, note that I used var to set this object. Because it can be used by all instances of the Sylin constructor, setting it as an instance variable (using this) is wasteful, as it will create the object for every instance of Sylin. Using var lets them all share it, saving memory.

Alternately, you could store the running total at each level, but IMO this requires more effort for no good reason. It would take less of your time to write a function:

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;
    }
}

Then just run this function any time the user changes the level of the character. No need to pass the level, as the function will already have access to the this.Level variable.

Solution 2:

Why not store the points in an array of objects -

varpointsTable= [{offensivePionts:1, defensivePoints:1}, {offensivePoints:1, defensivePoints:2}];//extendforanylevel

And then just get return points by referencing the corrent property -

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

You can easily extend the datastructure with methods like addLevel etc.

Solution 3:

Sure you could always create an hardcoded array of all points, however you could also simply hardcode the exceptions and stick with an algorithm when you can.

Just an idea... that would require your hero to keep track of his points instead of recompiling them dynamically however, but that's probably a good thing.

//have a map for exceptionsvar 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

};

Then to level up, you do hero.levelUp() and to get the points hero.offense. I haven't tested anything, but that's the idea. However, if you require to be able to set the level directly, you could either have a setLevel function that would call levelUp the right amount of times but, you would have to use a modifier to allow you leveling down as well.

You could also use my current idea and find an efficient way of implementing exceptionnal algorithms. For instance, you could still dynamically compile the number of offense points, and then add or remove points from that result based on exceptions. So if you need 2 points every 2 levels, but 3 for the level 9, that means adding 1 additionnal point to the compiled points. However, since when you reach higher levels, you wan to retain that exception, you would have to keep track of all added exception points as well.

EDIT: Also, nothing prevents you from using a function as a new exceptionnal algorithm instead of a simple number and if you plan to make the algorithms configurable, you can simply allow users to override the defaults. For instance, you could have a public updateOffense function that encapsulates the logic, so that it can be overriden. That would be something similar to the Strategy design pattern.

EDIT2: Here's a complete example of what I was trying to explain, hope it helps!

varHero = (function () {

    functionHero() {
        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 pointsreturn4;
                }
            }
        },
        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 () {
                return1;
            }
        }
    };

    functionupdateStats(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;
            }
        }
    }

    returnHero;
})();

var h = newHero();

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 rulesfunctionChuckNorris() {
    Hero.call(this); //call parent constructor
}

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

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

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

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

var c = newChuckNorris();

c.setLevel(10);

console.log(c.stats);

Post a Comment for "Javascript - Structure For A Look-up Table"