JavaScript - For loop with switch statement continually looping - javascript

I'm relatively new to coding and working on a text based RPG game in JavaScript. The following code allows me to progress through the different scenarios where you are approached with a different bad guy.
I used a For loop in conjunction with a Switch statement and had it working prior, but then I re factored my code to make it more OO & prototypal. Now my For loop continues looping and does not exit. I checked the value of [i] throughout and see it properly goes 0-4, but then it restarts at 0 and I can't figure out why?
var scenario = new Array();
//simple function to create the number of scenarios
function Scenario () {
howManyScenarios = function(number) {
for (i=0; i <= number; i++) {
scenario[i] = ("Scenario " + (1 + i));
};
};
howManyScenarios(4); //if you change the argument, add additional switch cases
//iterating through my howManyScenarios function to build out scenarios using a switch case
createScenarios = function () {
var ii = scenario.length;
for (i=0; i < ii; i++) {
switch(scenario[i]) {
case 'Scenario 1':
alert("You run into a troll");
b = 0;
break;
case 'Scenario 2':
alert("You find a store to purchase goods from");
ItemShop();
break;
case 'Scenario 3':
alert("You run into a ogre");
b = 1;
break;
case 'Scenario 4':
alert("You run into a warewolf");
b = 2;
break;
case 'Scenario 5':
alert("You run into a wizard");
b = 3;
return;
break;
}; //close out switch cases
}; //close out my for loop
}; //close out createScenarios function
createScenarios();
}; //close out Scenario function
Scenario();

Your loop will obviously still continue because you just only ended a case of every loop of i and will still test each value in the array of scenario[i].
How about using variable b as a handler that if an event like you run into a troll has been executed, then set b to a number greater than 0 then check if a value has been inserted into b before switching into the array again using if (b) break; where if b has a value greater than 0 then it will be set as true.
var scenario = new Array();
var b;
//simple function to create the number of scenarios
function Scenario() {
howManyScenarios = function (number) {
for (i = 0; i <= number; i++) {
scenario[i] = ("Scenario " + (1 + i));
};
};
howManyScenarios(4); //if you change the argument, add additional switch cases
console.log(scenario[i]);
//iterating through my howManyScenarios function to build out scenarios using a switch case
createScenarios = function () {
var ii = scenario.length;
for (i = 0; i < ii; i++) {
if (b) break;
switch (scenario[i]) {
case 'Scenario 1':
alert("You run into a troll");
b = 1;
break;
case 'Scenario 2':
alert("You find a store to purchase goods from");
b = 2;
ItemShop();
break;
case 'Scenario 3':
alert("You run into a ogre");
b = 3;
break;
case 'Scenario 4':
alert("You run into a warewolf");
b = 4;
break;
case 'Scenario 5':
alert("You run into a wizard");
b = 5;
return;
break;
}; //close out switch cases
}; //close out my for loop
}; //close out createScenarios function
createScenarios();
}; //close out Scenario function
Scenario();
function ItemShop() {}
ANSWER 2
This one is one way on how we game developers make a functional game by using a series of object arrays, object classes and the like.
I remade your code into something easier to read, hope you learn something from this. :)
var numberofscenarios = 5;
var scenario = []; //array where scenarios will be
//this will be the accessible properties of scenario[] array
var _scenario = function(){
this.name = ""; //name of scenario
this.message = "";
this.doSomething = 0;
this.status = 0 ;//1 = finished and 0 = false
};
var _event = function(mobname){
this.mobname = mobname;
this.battle = function(){//doSomething
console.log("Battle VS "+ this.mobname +" Start!");
};
this.itemShop = function(){//doSomething
console.log(this.mobname + ": Welcome to the shop! How may I help you?");
};
};
//generate the scenarios in the scenario[] array
function generateScenarios() {
for (i = 0; i <= numberofscenarios; i++) {
scenario[i] = new _scenario();
scenario[i].name = i;
switch (scenario[i].name) {
case 1:
scenario[i].message = "You run into a Troll";
scenario[i].doSomething = new _event("Troll");
break;
case 2:
scenario[i].message = "You find a store to purchase goods from";
scenario[i].doSomething = new _event("Shop Keeper");
break;
case 3:
scenario[i].message = "You run into a Ogre";
scenario[i].doSomething = new _event("Ogre");
break;
case 4:
scenario[i].message = "You run into a Werewolf";
scenario[i].doSomething = new _event("Werewolf");
break;
case 5:
scenario[i].message = "You run into a Wizard";
scenario[i].doSomething = new _event("Wizard");
break;
}
}
}
generateScenarios(); //generate the scenarios
//test the array of scenario class
//test the battle with Troll
console.log(scenario[1].message);
scenario[1].doSomething.battle();
//test the shop
console.log(scenario[2].message);
scenario[2].doSomething.itemShop();
//attempt to fight the Shopkeeper
console.log(scenario[2].message);
scenario[2].doSomething.battle();

Related

How to make a monster hit a random player in javascript

I am trying to make a game in vue js where i have tank, dps and healer
data: {
tankHealth: 100,
healerHealth: 100,
dpsHealth: 100,
monsterHealth: 200,
gameRunning: false,
turns: [],
},
I have a button that when it gets clicked it enters a setinterval function where every 1 second the tank and dps attack the monster. and the healer heals one of the players. But when it comes to monster attacking the player, i want the monster to attack randomly one of the players like that:
var monsterDamage = self.calculateDamage(10,20); // returns a random number between 10 and 20
var number = self.randomNumberFn(1,3);
// get a random number here so i can randomly pick a player to attack
switch(number) {
case 1:
self.dpsHealth -= monsterDamage;
if(self.dpsHealth <= 0) {
self.dpsHealth = 0;
break;
}
break;
case 2:
self.tankHealth -= monsterDamage;
if(self.tankHealth <= 0) {
self.tankHealth = 0;
break;
}
break;
case 3:
self.healerHealth -= monsterDamage;
if(self.healerHealth <= 0) {
self.healerHealth = 0;
break;
}
break;
}
The problem comes when one of the players is dead. In that case, I want the monster to attack only the players that are alive. In the model i have right now, even if one of the players is dead the monster keeps attacking him
Maybe like this?
do {
var n1 = 1;
var n2 = 3;
var monsterDamage = self.calculateDamage(10, 20);
var number = self.randomNumberFn(n1, n2);
switch (number) {
case 1:
if (self.dpsHealth === 0) { // === checks type too...
n1 = 2;
continue;
}
self.dpsHealth = doDamage(self.dpsHealth, monsterDamage);
break;
case 2:
if (self.dpsHealth === 0) {
continue;
}
self.tankHealth = doDamage(self.tankHealth, monsterDamage);
break;
case 3:
if (self.dpsHealth === 0) {
n2 = 2;
continue;
}
self.healerHealth = doDamage(self.healerHealth, monsterDamage);
break;
}
} while((self.dpsHealth + self.tankHealth + self.healerHealth) === 0)
function doDamage(health, damage) {
if ((health - damage) <= 0) {
return 0;
} else {
return health - damage;
}
}
To solve this problem, you can create an array to hold your living humans, and iterate through said array for a random value.
let livingHumans = [];
if(dpsHealth > 0) {
livingHumans.push({name:'dpsHealth', health:dpsHealth});
}
if(tankHealth > 0) {
livingHumans.push({name:'tankHealth', health:tankHealth});
}
if(healerHealth > 0) {
livingHumans.push({name:'healerHealth', health:healerHealth});
}
// get random value from array
let number = self.randomNumber(1, livingHumans.length)
// once you receive the output,
// you can use the name property to find the player in your object.
name = livingHumans[number].name;
console.log(data[name]);

Javascript - Undefined arrays in iteration

I am working on a Nodejs tool which uses an API.
My issue is that I don't understand why the previous element of the array is not registered properly and is "Undefined" when the iterator is incremented.
this.pptab = new Array();
this.tabplayers = new Array();
for (var i = 0; i < (argsname.length - 1); i++) {
osuApi.getUser({ "u": argsname[i], "m": argsmode.join('=') }).then(user => { //calling the osu!api
this.pptab[i] = user[0].pp_raw;
this.tabplayers[i] = user[0].username;
console.log("Player -1: " + this.tabplayers[i - 1]); // This displays "Undefined" in each iteration
});
}
Two issue one in loop condition [ i **<** (argsname.length-1)] you do not require (-1 ) as of smaller then condition. Second if condition required for first step.
this.pptab = new Array();
this.tabplayers = new Array();
for (var i = 0; i < (argsname.length); i++) {
osuApi.getUser({ "u": argsname[i], "m": argsmode.join('=') }).then(user => { //calling the osu!api
this.pptab[i] = user[0].pp_raw;
this.tabplayers[i] = user[0].username;
if(i>0) {
console.log("Player -1: " + this.tabplayers[i-1]); // for first player -1 does not exist
}
});
}
I think you are doing something wrong when converting your string command to an array and then shifting it. See this:
Code is here:
https://repl.it/#LatinWarrior/StackoverflowQuestion
This is what I wrote:
let argsname = "!topsetup Player1 Player2 Player3 m=2".split(' ');
let argsnameWithShift = argsname.shift();
console.log(argsname);
console.log(argsnameWithShift);

Javascript scope variable to switch case?

In C you can scope a variable to a switch case, like this.
With javascript I get unexpected token using the following:
const i = 1
switch (i) {
// variables scoped to switch
var s
var x = 2342
case 0:
s = 1 + x
break
case 1:
s = 'b'
break
}
Is there another way to do this or should I just declare my variables outside the switch?
EDIT:
This is a workaround I considered but it didn't end up working. The reason being that each case has its own scope.
const i = 1
switch (i) {
case i:
// variables scoped to switch
var s
var x = 2342
case 0:
s = 1 + x
break
case 1:
s = 'b'
break
}
some alternative:
/* curly braces inside the case */
const i = 1
switch (i) {
case 0: {
let x = 2342;
let s = 1 + x;
console.log(x+' & '+s+' from inside');
} break;
case 1: {
let x = 2342;
let s = 'b';
console.log(x+' & '+s+' from inside'); /* 2342 & b from inside */
} break;
}
console.log(x+' & '+s+' from outside'); /* Uncaught ReferenceError */
or
/* curly braces outside the switch */
const i = 1
{
let x = 2342;
let s;
switch (i) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
}
console.log(x+' & '+s+' from inside'); /* 2342 & b from inside */
}
console.log(x+' & '+s+' from outside'); /* Uncaught ReferenceError */
Since var creates variables at function scope anyway, using it is pretty pointless. For this to work at a granularity below function scopes you'll have to use let and a browser/compiler which supports it, and then introduce a new block which you can scope things to (within switch it's simply invalid syntax):
if (true) {
let s;
switch (i) {
...
}
}
This scopes s to the if block, which for all intents and purposes is identical to the "switch scope" here.
If you cannot support let, you'll need to use an IIFE:
(function () {
var s;
switch (...) ...
})();
No, this is invalid syntax. A case or default statement is expected within a switch. You can check the specification here: http://www.ecma-international.org/ecma-262/5.1/#sec-12.11
You can also try entering your code in a JSLinter and see that this an error: http://jslint.com/
Expected 'case' and instead saw 'var'.
The workaround that you're considering would be the same thing as putting them outside the switch statement. Remember, var has function-level scope, not block-level scope. That means they are bound to the entire function containing the switch. You should declare them outside of the switch because that is where they are accessible.
const i = 1;
var s;
var x = 2342;
switch (i) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
default:
break;
}
console.log("s is " + s);
It should be declared outside the switch. The below might help:
var i = 1, x = 2342;
var s;
switch (i)
{
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
}
console.log("s is " + s);
JavaScript defines 3 levels of scope:
Global - Anything not delcared in a function
Function - Anything declared in a function using the var keyword
Block - Anything declared in a block container ({}) using let
So, to creae a scope an entire construct, you have two choices: Function or Block
In order to get the the behavior you are looking for with a function:
const i = 1
function doSwitch(data){
// variables are not scoped to switch, but are
// scoped to the function, which only contains
// the switch.
var s;
var x = 2342;
switch (data) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
default:
s = "other";
}
console.log("s is " + s)
}
doSwitch(18);
Or, in order to get the functionality with a block using let
const i = 1;
// Wrapping the switch in its own block allows for let to work:
{
// variables are not scoped to switch, but are
// scoped to the function, which only contains
// the switch.
let s;
let x = 2342;
switch (i) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
default:
s = "other";
}
console.log("s is " + s)
}
// Test:
console.log(s, x); // ReferenceError

What's the difference between angular.equals and _.isEqual?

I mean is there any difference in performance? Which one is able to make the best deep comparison? Sometimes angular's equals function is not able to find every difference.
I have also noticed, that the angular version of this function is not checking the '$$hashKey' key.
They basically act the same by comparing the values itself and all inner properties. Performance is also close to being the same, at least this will be a difference in 100-200 ms for 10000 elements. I have created small tests suite, warning: your browser page will freeze for few seconds when you run code snippet. I'm not totally sure is this correct way to measure performance so feel free to suggest better ways.
angular
.module("comparsion", [])
.controller("ComparsionCtrl", function($scope) {
var testCases = 10000;
console.time("underscore");
for(var i = 0; i < testCases; i++) {
var obj = createRandomObj(5, true);
var obj1 = createRandomObj(5, true);
_.isEqual(obj, obj1);
}
console.timeEnd("underscore");
console.time("angular");
for(var i = 0; i < testCases; i++) {
var obj = createRandomObj(5, true);
var obj1 = createRandomObj(5, true);
angular.equals(obj, obj1);
}
console.timeEnd("angular");
// Random object generator from http://stackoverflow.com/questions/2443901/random-object-generator-in-javascript
function createRandomObj(fieldCount, allowNested)
{
var generatedObj = {};
for(var i = 0; i < fieldCount; i++) {
var generatedObjField;
switch(randomInt(allowNested ? 6 : 5)) {
case 0:
generatedObjField = randomInt(1000);
break;
case 1:
generatedObjField = Math.random();
break;
case 2:
generatedObjField = Math.random() < 0.5 ? true : false;
break;
case 3:
generatedObjField = randomString(randomInt(4) + 4);
break;
case 4:
generatedObjField = null;
break;
case 5:
generatedObjField = createRandomObj(fieldCount, allowNested);
break;
}
generatedObj[randomString(8)] = generatedObjField;
}
return generatedObj;
}
// helper functions
function randomInt(rightBound)
{
return Math.floor(Math.random() * rightBound);
}
function randomString(size)
{
var alphaChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var generatedString = '';
for(var i = 0; i < size; i++) {
generatedString += alphaChars[randomInt(alphaChars.length)];
}
return generatedString;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<div ng-app="comparsion">
<div ng-controller="ComparsionCtrl"></div>
</div>
angular.equals:this is angular equals comparision.
_.isEqual:this is underscore equal functionality.you need to import underscore js before using this.

How do I use one function to call the other function by if/case statement?

Does anyone know what typo I made, because my editor, and I can't seem to make it work
number=5;
switch (number) {
case 5:
box.onclick = function1;
break;
case 50:
box.onclick = function2;
break;
}
I've also tried doing it in switch.
Try not using the reserved word var as a variable name:
var x=5;
if (x==5){
box.onclick = function1;
}
if(x==50){
box.onclick = function2;
}
var is the reserved word to create variables. You can't use it as a name. This is the correct syntax:
var x = 5;
if (x == 5) {
box.onclick = function1;
}
if (x == 50) {
box.onclick = function2;
}
With this code:
number=5;
switch (number) {
case 5:
box.onclick = function1;
break;
case 50:
box.onclick = function2;
break;
}
case 50 will never be hit because you set number to 5 before entering the switch block. Therefore box onclick will never equal function2. Therefore, when you click the box, function2 will not be run. Is this really an accurate representation of your actual code, or is it a simplification that has left out important information?
You can't use reserved JavaScript words for declaring variables.
Try to replace var=5 to myVar=5 for example.
var myVar = 5;
if (myVar ==5){
box.onclick = function1;
}
if(myVar ==50){
box.onclick = function2;
}
Also, check out this reference: JavaScript Reserved Words

Categories