Javascript array being set, no idea where - javascript

For a school project I need to make a game in C. However, since I'm much more fond with javascript + js can give a easy visual implementation, I decided to write my game in js before in c, to get my structure right. That's why my code's so weirdly looped.
Now, the issue is that I have a switches[] array that has the switches being pressed (1/0). I want to compare this to another array, oldArray[]. Now, when comparing, they are both ALWAYS the same for some reason, and I just can't find it. Here's a full sample on jsfiddle.net. The issue is in the memory() function. This line isn't working properly:
if (switches[i] == 1 && oldArray[i] == 0 && guessedArray[i] == 8 && i != oldtouch) {...}
because switches[] always seems to be equal to oldArray[].
In the fiddle, press Start and check the consle output after clicking some buttons.

They are equal, because when the assignment statement oldArray = switches is executed, both variables point to the same underlying object in memory.
To copy all the values from one array to the other, without having them point to the same object, do oldArray = switches.slice(0)
See this for further discussion: Copying array by value in JavaScript

Related

How can I filter to an array and choose a random Id from it?

Good night folks.
I'm new to programming, less than 2 months, so I don't quite understand how to make this work. Here's exactly what I want to do:
I have this game I'm trying to make which needs to do a raffle between existing units that fit the condition "is alive" and have "is able to use the prize". To do that, I was told I needed to include an array with the unit Id for the units that can receive it, then filter them by "is alive" to choose from by a random generator. Thing is, I have no idea how to make this work. I've tried this code, but it does not work. Anyone has any idea why or how I should do it instead?
var rafflearray = []; // the array containing the units
if (root.getExternalData().isUnitRegistered() = true) {var character = root.getCurrentSession().getPlayerList().getData()}; // establish the character as a variable
if (var character.getAliveStatus = true ) {rafflearray.push(character)}; // checks his alive status and send him to the array
var chosen = rafflearray [Math.random()*chosenarray.lenght]; // to choose amongst them
chosen.addItem()
Thanks in advance for the attention!
I strongly suggest going through Javascript Fundamentals (here section 1 & 2) before this project. However I hope this answer helps you
First of all you cannot use var inside if statements like
if(var character.getAliveStatus = true)
And you need to use == or === instead of = , like:
if(isAlive === true){
// Code to be executed
}
// the difference between '==' and '===' can be found in the docs mentioned below
see Javascript Operators from here on section 3
var is for declaring a variable which is not limited to its parent blocks see javascript scoping
In your case I'm not sure if you have an array of players already or if you're trying to make one.
In the first situation, I suggest you use Array.filter() function which is a cool way. For example :
// Assuming 'players' is the array of players in the game
// filtering out raffle worthy players
let raffle_worthy = players.filter(player => player.getAliveStatus === true);
// Randomly choosing 1 person between the raffle worthy players
let chosen = raffle_worthy[Math.floor(Math.random * raffle_worthy.length)]
You may want to take a look at Array.filter() docs and also Js Math has been used in the above example
On the other hand if you dont have an array of players and getting them one by one, I'm not really sure if I can understand the way you get users and what gathers them

Undefined index... but it says it's defined in the debugger

(EDIT: I solved my issue! Though I still don't understand the situation I see in the debugger. See my answer for more details)
(TL;DR: index is always undefined when used with a certain array. Doubt that would be enough info, but maybe for someone who's experienced this before.)
So basically, I'm using an array in javascript, and I started noticing some odd behaviour, so I went to the debugger, and I found that a defined variable representing the index was being treated as undefined. It's ONLY the case with this specific array, and it's index. I don't get errors saying that it's undefined, but when I look in the debugger, it says it's undefined when I hover over the variable in the array call (but it's defined if I hover over it anywhere before the array call), and I'm getting bugs that make it clear that the array is not being used properly. It makes absolutely no sense to me, but maybe someone's encountered a similar issue.
Take this example of code, It's drawing a tilemap layer for my MapRenderer class. The culprit here is "this.Map.layers". When I go into this function in the debugger, layerIndex is defined if I hover over the function parameter, but if I hover over it on the array call, it says it's undefined, and the whole logic breaks.
DrawLayer(ctx, camPos, layerIndex)
{
// Get the map/tile position based on the camera position, to decide which tile to start drawing.
var mapCamPos = new Point(Math.floor(camPos.x/TILESIZE),
Math.floor(camPos.y/TILESIZE));
// Get the max tile position based on camera position, to decide where to stop drawing.
var camPosLimit = new Point(Math.ceil(this.DrawSize.x/TILESIZE)+mapCamPos.x,
Math.ceil(this.DrawSize.y/TILESIZE)+mapCamPos.y);
// loop through all tiles we need to draw using rows and columns.
for(var row=mapCamPos.y;row<this.Map.layers[layerIndex].height&&row<=camPosLimit.y;row++)
{
for(var col=mapCamPos.x;col<this.Map.layers[layerIndex].width&&col<=camPosLimit.x;col++)
{
var currentTileID = this.GetTileID(layerIndex, row, col);
if (currentTileID >= 0 && !isNaN(currentTileID))
{
var drawPos = new Point(((col*TILESIZE)-camPos.x), ((row*TILESIZE)-camPos.y));
this.Spritesheet.PlayFrame(currentTileID);
this.Spritesheet.Draw(ctx, drawPos);
}
}
}
}
This is happening in many instances of my code wherever I'm using that array. I want to add how this started, because all of this logic was working previously. I had my tilemap working with multiple csv files, which I loaded as 2d arrays into an array. Today, I decided to switch it all to use one json file, as it is simply cleaner (one file rather than one csv per map layer), and I can add extra properties and stuff in the future rather than just having the tileIDs. So, in the above example, this.Map gets initialized through an ajax call(using jquery) to read the json file, before DrawLayer ever gets called. Still, I don't see why this would cause this. Doing "mapRenderer.Map.layers" in the console tells me that it's a normal array, and when I try calling it normally from the console, it works fine. I'm so confused at this issue. I had literally the same function before and it worked, just that my array has changed a bit(it used to be just "this.Layers", instead of "this.Map.layers"), but it's still a normal array... I don't see why it would behave so differently just because it was generated via json...
Any help or explanations would be greatly appreciated, thanks.
I still don't understand the situation I see in the debugger, maybe it's a firefox bug, or feature I don't understand. But I managed to fix my issue. It was a basic logic bug: I'm using the "Tiled" map editor, and when you export those maps to CSVs, the tile IDs are zero-based, meaning empty tiles are -1. When you export to json, they aren't zero-based, meaning empty tiles are 0, which I failed to notice, and this was the root of all my current issues. If anyone can explain why the firefox debugger might say defined variables are "undefined" when you hover over them, that would still be good to know.

Google Spreadsheet String Comparison

I have used:
SpreadsheetApp.getActiveSheet().getRange(... some Range ...).getValues();
to store strings from a spreadsheet's cells into an array. The strings are then compared with other strings, but the comparison (using ==) always fails even though the values are the same.
Browser.msgBox("is '"+topPlayerNames[j]+"' == '"+name+"'? "+(topPlayerNames[j] == name));
// displays:
is 'Data' == 'Data'? false
Why is the javascript comparison failing? Is there hidden formatting in cell values disrupting the comparison?
Since the getRange() will give you a two dimensional array, By interpreting them something like
var values = SpreadsheetApp.getActiveSheet().getRange(... some Range ...).getValues();
Browser.msgBox(values);
is just output the data in your expected way and exactly not matching with each other. The reason for not matching is your variable container keeps
values = [['a','b',...],['d','f',....]]. So it will output the data when you ask to out put the data. But when comparing,
Does [['a','b',...]] == 'a','b',... ?? The answer is it is not.
So you need to get out your data from the array to compare with others. In that case use values[0][0] to get 'a' (in my example) or to get 'd', values[1][0] .... and so on. You know element numbers are begin with 0 in javascript array. :)
Now you can compare them. So values[0][0] == 'a' will output TRUE (in my example)
However You didn't mentioned what is topPlayerNames[j], If it is also like values in above, then you need to consider it too in the explained way.
(Your question has limited variables. So I was need to write more when explaining. Next time please give some explained question with respective variable. Use short variables for long statements. That will help to answer in an easy way.)
See What is the correct way to check for string equality in JavaScript?
I would use
topPlayerNames[j].equals(name)
I never trust == with strings, as it so often causes a bug.

Two drop down option lists in a form using javascript

I have a problem with two drop down lists ( options ) in a form. They both work separately but together they don't work at all. It's like they are canceling each other out or something. If anyone can help me then I'll be truly grateful. Here's the code with the problem... JS fiddle - http://jsfiddle.net/wemdragon/3Uz/
There are a couple problems. First off, .val() gets a string rather than an int, so if ('0') will return true. Therefore, options 2! is always emitted no matter what you have selected for the second option. You need to update that conditional to check if (second.val() != 0) (this will coerce '0' and 0 and return true -- you can also get more specific or simply use an empty string as the value instead, which is probably preferred).
Second of all, your calculation code is never reached since it is the else in the chain of ifs that cover all possible combination of selections. You need some other flag to check that the calculation should be done, or make it a function that is called when a valid selection is made.

jQuery "Autocomplete" plugin is messing up the order of my data

I'm using Jorn Zaefferer's Autocomplete plugin on a couple of different pages. In both instances, the order of displayed strings is a little bit messed up.
Example 1: array of strings: basically they are in alphabetical order except for General Knowledge which has been pushed to the top:
General Knowledge,Art and Design,Business Studies,Citizenship,Design and Technology,English,Geography,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else
Displayed strings:
General Knowledge,Geography,Art and Design,Business Studies,Citizenship,Design and Technology,English,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else
Note that Geography has been pushed to be the second item, after General Knowledge. The rest are all fine.
Example 2: array of strings: as above but with Cross-curricular instead of General Knowledge.
Cross-curricular,Art and Design,Business Studies,Citizenship,Design and Technology,English,Geography,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else
Displayed strings:
Cross-curricular,Citizenship,Art and Design,Business Studies,Design and Technology,English,Geography,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else
Here, Citizenship has been pushed to the number 2 position.
I've experimented a little, and it seems like there's a bug saying "put things that start with the same letter as the first item after the first item and leave the rest alone". Kind of mystifying. I've tried a bit of debugging by triggering alerts inside the autocomplete plugin code but everywhere i can see, it's using the correct order. it seems to be just when its rendered out that it goes wrong.
Any ideas anyone?
max
EDIT - reply to Clint
Thanks for pointing me at the relevant bit of code btw. To make diagnosis simpler i changed the array of values to ["carrot", "apple", "cherry"], which autocomplete re-orders to ["carrot", "cherry", "apple"].
Here's the array that it generates for stMatchSets:
stMatchSets = ({'':[#1={value:"carrot", data:["carrot"], result:"carrot"}, #3={value:"apple", data:["apple"], result:"apple"}, #2={value:"cherry", data:["cherry"], result:"cherry"}], c:[#1#, #2#], a:[#3#]})
So, it's collecting the first letters together into a map, which makes sense as a first-pass matching strategy. What i'd like it to do though, is to use the given array of values, rather than the map, when it comes to populating the displayed list. I can't quite get my head around what's going on with the cache inside the guts of the code (i'm not very experienced with javascript).
SOLVED - i fixed this by hacking the javascript in the plugin.
On line 549 (or 565) we return a variable csub which is an object holding the matching data. Before it's returned, I reorder this so that the order matches the original array of value we were given, ie that we used to build the index in the first place, which i had put into another variable:
csub = csub.sort(function(a,b){ return originalData.indexOf(a.value) > originalData.indexOf(b.value); })
hacky but it works. Personally i think that this behaviour (possibly coded more cleanly) should be the default behaviour of the plugin: ie, the order of results should match the original passed array of possible values. That way the user can sort their array alphabetically if they want (which is trivial) to get the results in alphabetical order, or they can preserve their own 'custom' order.
What I did instead of your solution was to add
if (!q && data[q]){return data[q];}
just above
var csub = [];
found in line ~535.
What this does, if I understood correctly, is to fetch the cached data for when the input is empty, specified in line ~472: stMatchSets[""] = []. Assuming that the cached data for when the input is empty are the first data you provided to begin with, then its all good.
I'm not sure about this autocomplete plugin in particular, but are you sure it's not just trying to give you the best match possible? My autocomplete plugin does some heuristics and does reordering of that nature.
Which brings me to my other answer: there are a million jQuery autocomplete plugins out there. If this one doesn't satisfy you, I'm sure there is another that will.
edit:
In fact, I'm completely certain that's what it's doing. Take a look around line 474:
// loop through the array and create a lookup structure
for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
/* some code */
var firstChar = value.charAt(0).toLowerCase();
// if no lookup array for this character exists, look it up now
if( !stMatchSets[firstChar] )
and so on. So, it's a feature.

Categories