Display array of movieclips and dynamically update them? - arrays

So I have this Array, named combo. I want to fill it with movieclips according to the user clicks (if user clicks 1, then add "1" to the Array and display it on an area.
Problem is, I do not know how to do it.
For the record, I have 4 movieclips, fire, wind, earth and spirit. When the user clicks one of them, I want the Array to update. Array's max length is 6 and it is always checked against a "true_combo" Array.
My questions are:
1) How do I remove the oldest item in the Array if the length has reached 6?
2) How do I display the movieclips one next to another (smaller versions of the buttons, not new movieclips), according to Combo?
3) How do I dynamically update the movieclip list on the stage?
This is a stripped version of my current fla
https://www.dropbox.com/s/17d9rgclz29ft1u/Untitled-1.fla
This is the code to check the combo against true combo:
function checkthis(e:Event)
{
if(combo.length == truecombo.length)
for(var o:int = 0; o < combo.length; o++)
{
if(combo[o] == truecombo[o])
{
bravo.play();
}
}
}

1
You can use the Array.shift() (remove first item in array) or Array.pop() (remove last item in array)
2 / 3
Use a for-loop and change the position of the items according the array. I assume the items in the array are references to the movieclips, then this would be functions you could use.
function add(clip:DisplayObject)
{
if (this.combo.length >= 6)
{
// remove child and remove it from the list
removeChild(this.combo.shift());
}
this.combo.push(clip);
this.addChild(clip);
reorder();
}
function reorder()
{
for(var i:int = 0; i < combo.length; i++)
{
combo[i].x = i * 50;
}
}
update:
You can download an example of this implementation here (Flash CS6 file) or watch it here
update 2
function checkthis(e:Event)
{
var isValid:Boolean = true;
if(combo.length == truecombo.length)
{
for(var o:int = 0; o < combo.length; o++)
{
if(combo[o] != truecombo[o])
{
// if one item isnt the same it should fail.
isValid = false;
}
}
}
if (isValid)
{
bravo.play();
}
}

Related

update objects in array with useState (reactJS)

Go to the end of this question for the solution that worked for me!
i'm currently making my own chess game and i want to check if a position already occurred 3 times. I keep the current position in a 2d array. This is what i tried:
Initialize the useState:
const [positionList, setPositionList] = useState([])
structure of the state should look like this
[
{
position: //some 2d array,
counter: 1
},
{
position: //another 2d array,
counter: 1
}
]
Compare the positions from the array with the current position
(if the position already existed, set counter one up)
let found = false
for (let i = 0; i < positionList.length; i++) {
if (JSON.stringify(positionList[i].position) === JSON.stringify(position)) {
positionList[i].counter = positionList[i].counter + 1
found = true;
break;
}
}
if the position never occurred before, add it to the array
if (found === false) {
setPositionList([...positionList, {position: position, counter: 1}]);
}
The 2nd and 3rd code block gets executed after every move (after players turn).
But for some reason, if "found" is false, it wont add the new position to the array but replace the last object in the array. And furthermore, when i log the changes made to "positionList" with a useEffect, it gets reset after every move to the default value (basically empty array), even though im not changing the state in any other part of my code.
I log the positionList like this:
useEffect(() => {
console.log(positionList)
}, [positionList])
I just cant figure out my error, hopefully someone can help.
Thanks!
EDIT:
I decided to try another way of counting the positions. I now only have one array which contains every position that occured in the correct order. Then i just loop through the array and count the amount of times the current position is in the array. My code looks like this:
Note: I think its important to note that you need to create a copy of the array you want to push. Otherwise all entrys in the array will be completly the same and you won't get the expected output (also see here)
function checkForThreefoldRepetition () {
let counter = 0;
for (let i = 0; i < positionList.length; i++) {
if (JSON.stringify(positionList[i]) === JSON.stringify(position)) {
counter++;
}
}
if (counter === 2) {
const updateGameOver = {
gameOver: true,
reason: "threefold repetition",
winner: "draw"
}
setGameOver(updateGameOver)
}
}
useEffect(() => {
let positionCopy = [];
for (let i = 0; i < position.length; i++) {
positionCopy[i] = position[i].slice();
}
setPositionList([...positionList, positionCopy]);
checkForThreefoldRepetition()
}, [playerTurn])
I think your problem is you are modifying current state directly like this one which is not a proper way of updating state :
positionList[i].counter = positionList[i].counter + 1
So this extra render cause problems,I think.

Get two arrays, compare and remove duplicates in Google Apps Script

I have got two lists on a google spreadsheet: 'Existing Companies' and 'New Companies'.
I would like to compare the two and find out which unique entries in 'New Companies' do not exist in 'Existing Companies', get those entries and eliminate from 'New Companies' all other entries.
I have made the following script to do it:
function grabNewCompanies() {
// grab existing companies list from sheet into an array
var sh = SpreadsheetApp.openById("sheetID").getSheetByName("sheetName")
var row = sh.getDataRange().getLastRow()
var existingCompanies = sh.getRange(2,1,row - 1,1).getValues()
Logger.log(existingCompanies)
//grab new companies added
var sh = SpreadsheetApp.openById("sheetID").getSheetByName("sheetName")
var row = sh.getDataRange().getLastRow()
var newCompanies = sh.getRange(2,4,row - 1, 1).getValues()
Logger.log(newCompanies)
var array = [];
for(i=0; i<newCompanies.length; i++) {
for(j=0; j<existingCompanies.length; j++) {
if(newCompanies[i][0] !== existingCompanies[j][0]) {
array.push([newCompanies[i][0]]);
}
Logger.log(array)
}
I have ran this script but it has failed.
The two arrays (existingCompanies and newCompanies) are returned correctly.
However, the comparison between the two does not seem to be working: it always returns the first element of the newCompanies array, regardless of whether it exists in existingCompanies.
Also, I am unsure about how to ensure that the values pushed into array are not duplicated if newCompanies contains more than one entry which does not exist in existingCompanies.
Thank you.
You want to retrieve the difference elements between existingCompanies and newCompanies. If my understand for your question is correct, how about this modification? I think that there are several solutions for your situation. So please think of this as one of them.
Modification points:
In the case that your script is modified, it picks up an element from newCompanies and it checks whether that is included in existingCompanies.
If that picked element is not included in existingCompanies, the element is pushed to array. In this modification, I used true and false for checking this.
This flow is repeated until all elements in newCompanies are checked.
Modified script 1:
When your script is modified, how about this?
From:
var array = [];
for(i=0; i<newCompanies.length; i++) {
for(j=0; j<existingCompanies.length; j++) {
if(newCompanies[i][0] !== existingCompanies[j][0]) {
array.push([newCompanies[i][0]]);
}
}
}
To:
var array = [];
for(i=0; i<newCompanies.length; i++) {
var temp = false; // Added
for(j=0; j<existingCompanies.length; j++) {
if(newCompanies[i][0] === existingCompanies[j][0]) { // Modified
temp = true; // Added
break; // Added
}
}
if (!temp) array.push([newCompanies[i][0]]); // Modified
}
Logger.log(array)
Modified script 2:
As other patterns, how about the following 2 samples? The process cost of these scripts are lower than that of the script using for loop.
var array = newCompanies.filter(function(e) {return existingCompanies.filter(function(f) {return f[0] == e[0]}).length == 0});
Logger.log(array)
or
var array = newCompanies.filter(function(e) {return !existingCompanies.some(function(f) {return f[0] == e[0]})});
Logger.log(array)
If I misunderstand your question, please tell me. I would like to modify it.

Checking array object existence

So, I am trying to check the existence of recently pushed array object.
I am developing the web application using angularJS.
I have an array which is defined as
vm.data.detail
So I have a form that let user to CRUD a module. The module is about product stock take. There is a button that will run addProduct() function in my angular controller.
addProduct function:
function addProduct() {
//to check whether the array is empty.
if (vm.data.detail.length == 0) {
vm.data.detail.push({
product: vm.data.product_id.selected,
current_qty: vm.data.product_id.selected.qty,
new_qty: Number(vm.data.product_id.selected.qty) - Number(1),
difference: Number(vm.data.product_id.selected.qty) - (Number(vm.data.product_id.selected.qty) - Number(1)),
remarks: ''
});
console.log("Product just been added");
}
//if the array is not empty
else {
for (var i = 0; i < vm.data.detail.length; i++) {
//to check whether the selected product is already inside the array
if (vm.data.product_id.selected.name == vm.data.detail[i].product.name) {
console.log("same product selected");
//data
}
//if there is no selected product inside the array, then add it
else {
console.log("different product has just been selected");
vm.data.detail.push({
product: vm.data.product_id.selected,
current_qty: vm.data.product_id.selected.qty,
new_qty: 0,
difference: 0,
remarks: ''
});
}
}
}
}
Above code works well when the array just consists of one product. The problem occurs when I am trying to add another product B into the product. Here is the condition :
Product A is already inside the array.
Product B is selected, and then added into the array. Now the array consists of 2 products.
When I am testing to add a new product B, I don't know why the array is still pushed with a new Product B. So now, the array consists of 3 Products (1 Product A, and 2 Product B).
What I wanted is, when I am trying to add the second product B, the array won't be pushed by new product B.
What am I missing here? Have been dealing with it for hours and can't figure out what I have to add for the "validation".
Please note that, the object the array pushing is already correct. I am just don't know how to put the if else. Looks like the logic inside is still lacking of something, but I couldn't figure out what is missing
Thank you so much for the help given.
You're commiting a simple mistake, you are doing the check of else inside the array, you must move it to outside.
Tips:
You can use Array.prototype.find() method to check if the element exists in array, which is much better than perform a traditional for-loop.
As you may have noticed in documentation, the find method have no compatibility with IE and Opera browsers, so if you need this compatibility, you can use Array.prototype.filter().
Below is the code, with both versions (with find and filter) and also with the necessary modifications:
function addProduct() {
//to check whether the array is empty.
if (!vm.data.detail.length) { // you can simply use (!length) instead of comparing with 0
vm.data.detail.push({
product: vm.data.product_id.selected,
current_qty: vm.data.product_id.selected.qty,
new_qty: Number(vm.data.product_id.selected.qty) - Number(1),
difference: Number(vm.data.product_id.selected.qty) - (Number(vm.data.product_id.selected.qty) - Number(1)),
remarks: ''
});
console.log("Product just been added");
}
//if the array is not empty
else {
// if there's no obj with the same name inside the array, it returns undefined, otherwise it returns the object.
var obj = vm.data.detail.find(function(value) {
return value.product.name == vm.data.product_id.selected.name;
});
/* Using FILTER:
var obj = vm.data.detail.filter(function(value) {
return value.product.name == vm.data.product_id.selected.name;
})[0];
*/
// Now you can test, if the object exists
if (obj) {
console.log("same product selected");
}
//if there is no selected product inside the array, then add it
else {
console.log("different product has just been selected");
vm.data.detail.push({
product: vm.data.product_id.selected,
current_qty: vm.data.product_id.selected.qty,
new_qty: 0,
difference: 0,
remarks: ''
});
}
}
}
I hope it helps!
It's a basic logic error. You're doing
for each element {
if element is different from given {
add given to array
}
}
What you need to do is
var allElementsDifferentFromGiven = true
for each element {
if element is same as given {
allElementsDifferentFromGiven = false
break
}
}
if (allElementsDifferentFromGiven) {
add given to array
}
But JavaScript arrays have methods to do that:
if (array.every(function(element) {
return true if element is different given
})) {
add given to array
}
I think problem is here :
because there product is property on Detail object and product does not have name property , it is not matching criteria and going to else condition and pushing into name list.
//to check whether the selected product is already inside the array
if(vm.data.product_id.selected.name == vm.data.detail[i].product.name){
it should be
//to check whether the selected product is already inside the array
if(vm.data.product_id.selected.name == vm.data.detail[i].product){
console.log("same product selected");
//data
}

Array not resetting in Game

Hey guys so i am developing a Game and i have an Array that keeps track of my 5 movie clips that are added to the stage by the array. I have a Player movie clip as well so the Player movie clip is Hittesting with all the 5 diamond movie clips which are added to the stage like so:
private var nPoints:Number = 5;..........
public function addPointsToStage():void
{
for (var i = 0; i < nPoints; i++)
{
trace(aPointsArray.length);
points = new mcGainPoints();
stage.addChild(points);
points.x = startPoint.x + (xSpacing * i);
points.y = startPoint.y - (ySpacing * i);
aPointsArray.push(points);
}
}
Now when the Player comes in contact with all the 5 movie clips everything works fine and the output for the array looks like this:
0
1
2
3
4
Then it continues to the next level.
But say that my Player doesnt hit any of the 5 movie clips or only hits a couple of them, when the next level is started the output looks like this:
5
6
7
8
9
and when the next level is started weird things start happening like points start adding to the highscore by themselves.
I think the problem is that im not destroying the array holding the 5 movie clips correctly this is the code i use to start the next level and destroy the array:
if(player.hitTestObject(mcGoal_1))
{
//Remove all points from array/stage
for (var i:int = 0; i < aPointsArray.length; i++)
{
if (aPointsArray[i].parent)
{
parent.removeChild(aPointsArray[i]);
}
startNextLevel();
}
The mcGoal_1 is the object of the game so if the player hits the goal_1 then destroy all array objects on screen and start next level. This is the startnextlevel function.
private function startNextLevel():void
{
//add points to next stage
addPointsToStage();
}
So can you see why when the next level starts the array isnt reset back to 01234? I think thats why the game has that bug of randomly adding points. Please any help will be appreciated
//Remove all points from array/stage
for (var i:int = 0; i < aPointsArray.length; i++)
if (aPointsArray[i].parent)
parent.removeChild(aPointsArray[i]);
// just one statement, no braces
aPointsArray.length=0; // clear the array itself, not just
// points from display list!
startNextLevel(); // now start level
An incorrect order of correct statements leads to a disaster. Always check your code flow, what executes now and what then, and how many times.
It doesn't look like you're removing anything from the array.
You can use a combination of .indexOf() and .splice() to remove items from an array:
function removeMc(clip:MovieClip):void
{
if(clip.parent) clip.parent.removeChild(clip);
// Also remove from array.
var index:int = aPointsArray.indexOf(clip);
aPointsArray.splice(index, 1);
}
It might also be worth simply emptying the array when you startNextLevel():
private function startNextLevel():void
{
aPointsArray.length = 0;
//add points to next stage
addPointsToStage();
}
Just assign your array to null value. so that array will start from begining whenever you require. i hope the following code code would helps you.
var nPoints:Number = 5;
var points:poin;
var aPointsArray:Array;
var startPoint:Number = 0;
var xSpacing:Number = 20;
var ySpacing:Number = 20;
addPointsToStage();
function addPointsToStage():void
{
aPointsArray = null;
aPointsArray = new Array();
for (var i:int = 0; i < 6; i++)
{
trace(aPointsArray.length);
points = new poin();
addChild(points);
points.x = 100+ (xSpacing * i);
points.y = 200 - (ySpacing * i);
aPointsArray.push(points);
}
}

#1023 StackOverflow ERROR

I have problem with this array thing I am doing. U can just plug in the code and run.
I need to have 2 things display out of the same array and which ever is picked gets kickedout from the array and stashed into another one.
One of the 2 things that are displaying out is picked at random and the other one goes in order it was put in.
So the logic I applied, or tried applying and is not working very well is..
Once the 2 things display out and if u pick the index count, no numbers change since the index count becomes subtracted by one, so the object after it gets pushed up.
but if the random choice is picked the index count moves up by one since it needs to keep moving...
The error i get is this:
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChild()
at Level3Torture_fla::MainTimeline/civilizedorder()[Level3Torture_fla.MainTimeline::frame1:87]
at Level3Torture_fla::MainTimeline/goNext()[Level3Torture_fla.MainTimeline::frame1:114]
at Level3Torture_fla::MainTimeline/switchpic()[Level3Torture_fla.MainTimeline::frame1:79]
This is the Code:
import flash.sampler.NewObjectSample;
import flash.display.Sprite;
import flash.events.MouseEvent;
var eating_breakfast:Sprite;
var walking:Sprite;
var swimming:Sprite;
var art:Sprite;
var choices:Array = new Array ();
//Sprite Creation
eating_breakfast = new Sprite ();
eating_breakfast.graphics.beginFill(0xE39D43);
eating_breakfast.graphics.drawRect(0,0,50,50);
eating_breakfast.graphics.endFill();
eating_breakfast.x = 50;
eating_breakfast.y = 50;
walking = new Sprite ();
walking.graphics.beginFill(0xC3266C);
walking.graphics.drawRect(0,0,50,50);
walking.graphics.endFill();
walking.x = 100;
walking.y = 100;
swimming = new Sprite ();
swimming.graphics.beginFill(0x48AFD1);
swimming.graphics.drawRect(0,0,50,50);
swimming.graphics.endFill();
swimming.x = 150;
swimming.y = 150;
art = new Sprite ();
art.graphics.beginFill(0xafdb44);
art.graphics.drawRect(0,0,50,50);
art.graphics.endFill();
art.x = 200;
art.y = 200;
//adding sprites into array
choices.push( eating_breakfast);
choices.push(walking);
choices.push(swimming);
choices.push(art);
var indexcount = 0;
var randomize:Number;
var storageArray: Array = new Array ();
civilizedorder();
randomizedorder();
this.addEventListener(MouseEvent.CLICK,switchpic);
//pick the target generated object
function switchpic(t:MouseEvent)
{
//for index count
if (t.target == choices[indexcount])
{
storageArray.push(choices[indexcount]);
removeChild(choices [indexcount]);
removeChild(choices [randomize]);
choices.splice(indexcount,1);
goNext();
};
// for randomize
if (t.target == choices[randomize])
{
storageArray.push(choices[randomize]);
removeChild(choices [indexcount]);
removeChild(choices [randomize]);
choices.splice(randomize,1);
indexcount++;
trace("The Index count is" + indexcount);
goNext();
}
}
//generates the index count object
function civilizedorder()
{
addChild(choices [indexcount]);
choices[indexcount].x = 300;
}
trace("The number of choices in the choice array is " + choices.length);
//generates the randomized object
function randomizedorder()
{
randomize = Math.floor(Math.random() * choices.length);
trace("the random number is" + randomize);
if (randomize == indexcount )
{
randomizedorder();
}
else
{
addChild(choices [randomize]);
}
}
//EDIT
function goNext()
{
trace("The storagearray has " + (storageArray.length));
if (choices.length < 0 || choices.length > 0)
{
if (indexcount > choices.length-1)
{
indexcount = choices.length - 1;
}
civilizedorder();
randomizedorder();
}
}
It is giving me a new error now. It's called StackOverflow. I am not entirely sure what is going wrong now.
EDIT: To add a conditional and check if you will be out of bounds for adding a child in this array, try this:
if(indexcount <= choices.length){
addChild(choices [indexcount]);
}
Try commenting out the splicing in the switchpic() method. That or re-add those values/sprite instances to the array.
I think that you've sliced from the "choices" array twice in the switchpic() method, and never actually add to the array ever again. So you'll eventually end up with an empty choices array. Hence the error.
In the second conditional, if (t.target == choices[randomize]), you increment indexcount, and then call goNext() which regenerates the randomize value to not equal the indexcount, but also tries to re-add a child sprite.
This could cause an array of 4 items to become 2 items, and then, possibly, randomize = 0, indexcount = 1. In the second pass, you might have an array of 0 items, with randomize = 0, indexcount = 1 and the error to occur.
Here's the flow, I imagine:
It looks like you're clicking on an instance of a sprite.
Then it calls switchpic(), which executes:
...
choices.splice(indexcount,1);
...
and then goNext()
which calls civilizedorder()
which executes:
...
addChild(choices [indexcount]);
...
you should check indexcount is never outside of 0-3 range.
in function goNext(), change the code as follows:
function goNext()
{
trace("The storagearray has " + (storageArray.length));
if(choices.length <> 0)
{
if(indexcount > choices.length-1)
indexcount = choices.length-1;
civilizedorder();
randomizedorder();
}
}

Resources