2

I have an object that looks like:

var monsters = {
    zombies:  {
        name: "zombie",
        hitPoints: 10,
        loot: "magic knife"
    },
    skeleton: {
        name: "skeleton",
        hitPoints: 15,
        loot: "magic shield"
    },
    ghoul:  {
        name: "ghoul",
        hitPoints: 12,
        loot: "magic helm"
    }
};  

I'm trying to set a function that will randomly select one of the properties in the variable. (zombies, skeleton, ghoul)

Here's what I have:

var travel = function(direction) {
        var newRoom = rooms[currentRoom.paths[direction]];
        if (!newRoom) {
            $("<p>You can't go that way.</p>").properDisplay();
        }
        else {
            currentRoom = newRoom;
            $("<p>You are now in the " + currentRoom.name + " Room.</p>").properDisplay();
                if (currentRoom.hasMonsters) {
                    function pickRand(monsters) {
                        var result;
                        var count = 0;
                        for (var prop in monsters)
                            if (Math.random() < 1/++count)
                                result = prop;
                            return $("<p>Holy Crap!  There's a" + result + "in here!</p>").properDisplay(); 

                    }
        }
        else {
            $("<p>Whew!  Nothing here.</p>").properDisplay();
        }
        }
    };

Note: The hasMonsters is in a separate object. It determines if a specific room has a monster or not.

How can I randomly select one of the monsters and insert in the output? I'm guessing I'm calling the object incorrectly and that's why it's not working.

megler
  • 217
  • 1
  • 2
  • 9
  • Why not just use an array for monsters? Since you seem to have the name of each monster inside each monster object anyway. – Prashanth Chandra Nov 11 '15 at 03:26
  • I thought about that, but once I figure this part out, there will be another function that calls the monsters hit points and if it has loot, etc. I think an object will handle that better than multiple arrays. – megler Nov 11 '15 at 03:27
  • You create the `pickRand` function but never call it. – 001 Nov 11 '15 at 03:49
  • If you have a "name" property in your monster class, this is a clear indication that your list is conceptually an array, not an associative array. – Femi Nov 11 '15 at 03:51
  • Does this answer your question? [Pick random property from a Javascript object](https://stackoverflow.com/q/2532218/90527) – outis Nov 05 '21 at 20:40

2 Answers2

4

Will something like this work? You can keep your monsters as an object and use Object.keys to fetch your keys (in this case your monsters) as an array. Then it's just a matter of plucking out a random monster with Math.random:

// so you have some object where the keys are your monsters
var monsters = { ghost: '..', skeleton: '..', donald_trump: '..'};

// grab your monsters above as an array
var monsterArray = Object.keys(monsters);

// pick your monster at random
var randomKey = Math.floor(Math.random() * monsterArray.length);

console.log('holy crap we found a ' + monsterArray[randomKey]);
David Zorychta
  • 13,039
  • 6
  • 45
  • 81
  • So even if it's in an object, so I have to restate it in the array? I'm not really strong on objects yet and I keep calling them wrong, but I think it's the direction I ultimately need to go in. – megler Nov 11 '15 at 03:40
  • Since the keys in your object are the names of the monsters, we just use Object.keys as a convenient method of grabbing your monsters in a way that lets us say "give me monster at position X" (something we can't do with an unordered object but can do with an array). Then we use Math.random() as position X so that the monster we pick is random. – David Zorychta Nov 11 '15 at 03:46
  • here is what I have: `if (currentRoom.hasMonsters) { function pickRand() { var monsterArray = Object.keys(monsters); var randomKey = Math.floor(Math.random() * monsterArray.length); return $("

    Holy Crap! There's a" + monsterArray[randomKey] + "in here!

    ").properDisplay(); }` But nothing happens as a result. What am I missing?
    – megler Nov 11 '15 at 03:52
  • "

    Holy Crap! There's a" + randomKey + "in here!

    "
    – David Zorychta Nov 11 '15 at 04:01
  • that didn't seem to work either. Here's a fiddle of what I have: https://jsfiddle.net/udzhdw94/ I also tried it with randomKey vs monsterArray[randomKey] – megler Nov 11 '15 at 04:02
  • Your solution worked. I was forgetting to call the function. Thanks @JohnnyMopp for pointing that out. – megler Nov 11 '15 at 04:07
  • haha just noticed you were missing the call to pickRand in your jsfiddle. Cool game dude, good luck :) – David Zorychta Nov 11 '15 at 04:07
1

now I see what you're asking. I want the name property called. Right now it will properly call what I'm guessing is the entire object. How do i call the name only?

Try using Object.keys()

var monsters = {
    zombies:  {
        name: "zombie",
        hitPoints: 10,
        loot: "magic knife"
    },
    skeleton: {
        name: "skeleton",
        hitPoints: 15,
        loot: "magic shield"
    },
    ghoul:  {
        name: "ghoul",
        hitPoints: 12,
        loot: "magic helm"
    }
};  

document.body.onclick = function() {
  
  var keys = Object.keys(monsters);
  var rand = Math.floor(Math.random() * keys.length)
  var res = monsters[keys[rand]];
  var key = Object.keys(res);
  var prop = res[key[Math.floor(Math.random() * key.length)]];
  console.log(res, prop);
  this.innerHTML += "<br>" + JSON.stringify(prop) + "<br>"
  
}
click
guest271314
  • 1
  • 15
  • 104
  • 177
  • first poster casted downvote. He also casted mine . i deleted my answer his repu increase 1 . Try yours too . – Anik Islam Abhi Nov 11 '15 at 03:42
  • I did not downvote, if you're referring to me. @guest271314 I tried the following, but no luck `if (currentRoom.hasMonsters) { function pickRand() { var keys = Object.keys(monsters); var rand = Math.floor(Math.random() * keys.length) var res = monsters[keys[rand]]; return $("

    Holy Crap! There's a" + res + "in here!

    ").properDisplay();`
    – megler Nov 11 '15 at 03:43
  • @megler What is expected result ? – guest271314 Nov 11 '15 at 03:54
  • The expected result would be the output of "Holy crap..." - In this case, nothing happens at all. It just tells me what room I'm in. – megler Nov 11 '15 at 03:55
  • Whats is expected result from _"trying to set a function that will randomly select one of the properties in the variable. (zombies, skeleton, ghoul)"_ , _"How can I randomly select one of the monsters and insert in the output?"_? Tried stacksnippets ? – guest271314 Nov 11 '15 at 03:57
  • @guest271314 - I apologize that I'm not communicating what I'm trying to do correctly. My goal is when the user enters the northEast room of the game, the game tells them there is a monster in that room. The monster is randomly generated from the monster object, so it's going to either be a zombie, skeleton or ghoul. This will eventually become more complicated, but for now, that's what I'm trying to do. – megler Nov 11 '15 at 04:01
  • 1
    @megler You create the function but you never actually call it. – 001 Nov 11 '15 at 04:02
  • @megler _" The monster is randomly generated from the monster object, so it's going to either be a zombie, skeleton or ghoul."_ Yes , though what property or value is expected result of random property in `monsters` ? `name` , property ? Entire object ? , `hitPoints` ? What should be returned at `$("

    Holy Crap! There's a" + res + "in here!

    ").properDisplay();` ? Also as pointed out by @JohnnyMopp , `pickRand` is not called at licked jsfiddle
    – guest271314 Nov 11 '15 at 04:04
  • thanks @JohnnyMopp! Just caught that. Between that and one more fix, it now works. Thank you and @Macmee! – megler Nov 11 '15 at 04:06