var animal:String ="Cat";
var isFish:Boolean;
isFish = isItAFish(animal);
trace(isFish);
function isItAFish (animal:String):Boolean {
var fishArray:Array = new Array("haddock", "Trout", "Salmon", "Cod");
for(var i:int = 0; i < fishArray.length; i++){
if (fishArray[i] == animal){
return true;
break;
}
}
return false;
}
I just need help explaining this code guys and girls. The "isFish = isItAFish (animal); trace(isFish); is where I'm confused from.
//animal is a string that contains the value "Cat"
var animal:String ="Cat";
//isFish is a boolean that will be used as a flag
var isFish:Boolean;
//isFish value will be changed from the outcome of the function isItAFish with the animal value.
isFish = isItAFish(animal);
trace(isFish);
//This function requires 1 string parameter and returns a boolean.
function isItAFish (animal:String):Boolean
{
//fishArray is a list of all your possible fishes.
var fishArray:Array = new Array("haddock", "Trout", "Salmon", "Cod");
/*
We iterate the array to see if animal ("Cat") is inside the fishArray possible values.
This loop will run exactly the number of times of the array's content. In this case, 4 times.
*/
for(var i:int = 0; i < fishArray.length; i++)
{
/*
We are comparing the values of the fishArray against animal ("Cat").
fishArray[i] holds the value of the current loop count.
For example, the first loop will be fishArray[0] which is "haddock".
The 4th loop will contain the value "Cod".
*/
if (fishArray[i] == animal)
{
//If we find a match, we return 'true' and stop the loop.
return true;
break;
}
}
//IF the loop ends without any matches we return 'false'.
return false;
}
Related
I have an array with six buttons called "sostaletters" and an array with six elements called "addedletters". What I want is every time a button is been clicked a new movieclip from the array "addedletters" to be added on stage. For example if the third element of the array "sostaletters" is been clicked then the third element of the array "addedletters" to be added on stage. How i can do that?
This is what i have done for my array "sostaletters"
var sostaletters:Array = [a7,a17,a24,a1,a18]
for each (var letter:MovieClip in sostaletters) {
letter.buttonMode = true;
letter.isClicked = false;
letter.addEventListener(MouseEvent.CLICK, kanoklick2);
function kanoklick2(event:MouseEvent):void
{
event.target.alpha = 0.5;
if(event.currentTarget.isClicked == false){
clickCount2 ++;
event.currentTarget.isClicked = true;
sostaletters[i].x = positionsArray[i].xPos;
sostaletters[i].y = positionsArray[i].yPos;
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
if(clickCount2 == sostaletters.length){
addChild(welldoneman);
myTimer.start();
if (contains(kremmala)) {
removeChild(kremmala)
}
for (var i:int= 0; i< wrongletters.length; i++)
{
wrongletters[i].removeEventListener(MouseEvent.CLICK, kanoklick);
}
for (var o:int= 0; o< sostaletters.length; o++)
{
sostaletters[o].removeEventListener(MouseEvent.CLICK, kanoklick2);
}
trace("All buttons have been clicked");
}
}
}
Neal Davis has already gave a right answer. But I shall make a code review for more clarity. See my comments in the code.
var sostaletters:Array = [a7,a17,a24,a1,a18]
// "sostaletters" is an Array. So it is better to use iteration by index
for each (var letter:MovieClip in sostaletters) {
letter.buttonMode = true;
letter.isClicked = false;
letter.addEventListener(MouseEvent.CLICK, kanoklick2);
// You will create "kanoklick2" function at each iteration.
// Move this declaration from this loop
function kanoklick2(event:MouseEvent):void {
event.target.alpha = 0.5;
// There is no need to compare a boolean property with "false" or "true"
// You can write "if(event.currentTarget.isClicked)"
if(event.currentTarget.isClicked == false) {
clickCount2 ++;
event.currentTarget.isClicked = true;
// You declare an "i" variable below.
// So the compiler will not fire en error.
// But you will not get an index of the current letter.
sostaletters[i].x = positionsArray[i].xPos;
sostaletters[i].y = positionsArray[i].yPos;
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
// If number of "sostaletters" are not changed
// you can save its value in a variable for an example "sostalettersNum"
if (clickCount2 == sostaletters.length) {
addChild(welldoneman);
myTimer.start();
if (contains(kremmala)) {
removeChild(kremmala)
}
// You declare an "i" variable. And use it above to get a current letter.
// But an "i" will not contain its index.
// It will be equal to "wrongletters.length"
for (var i:int= 0; i
When my random word appears the user has to memorise it and click the correct corresponding image to it. I'm trying to write the code that runs if the user selects the right image. I have paired my words and images in my array. I'm just unsure as how to go about calling this function.
This is what I've attempted so far, but this isn't working. I'm new to actionscript3 so excuse the lack of knowledge as I am trying to teach myself.
All help greatly appreciated!!
This is one way you can do this:
See code comments
basket.visible = false;
//------ Home Button ------\\
backhome1btn.addEventListener(MouseEvent.CLICK, goback1Click);
function goback1Click(event:MouseEvent):void{
gotoAndStop("homepage");
}
//-------------------
var score:int = 0;
var items:Array = new Array(); //store all food items in array
var wordsToShow:Array = new Array(); //store all words to show in array - this is the array that will keep track of which has been asked (or rather not asked yet)
//to reduce redundant code, call this with each food item (below)
function initFoodItem(item:MovieClip, word:String):void {
item.word = word; //forget the array, just store the word on the image as a dynamic property
item.addEventListener(MouseEvent.CLICK, foodClicked);
items.push(item); //add to array
wordsToShow.push(item); //add to array
item.visible = false;
}
initFoodItem(oc, "Orange Juice");
initFoodItem(sand, "Sandwich");
//...repeat for all other food items
//now randmize the words to show array:
wordsToShow.sort(function(a,b):int {
return(Math.random() > .5) ? 1 : -1;
});
var curAnswer:MovieClip; //a var to store the current correct answer
//this does the next question per se
function displayWord():void {
if(wordsToShow.length < 1){
//they've all been asked
gotoAndPlay("gameoverpage");
return;
}
curAnswer = wordsToShow.pop(); //assigns the last item in the array to the cur asnwer, and pop also removes that item from the array (so it won't get asked again)
randomword.text = curAnswer.word; //assign the text to the word value of this item
randomword.visible = true;
remember.visible = true;
}
remember.addEventListener(MouseEvent.CLICK, readyClick);
//when you click your ready button
function readyClick(e:MouseEvent):void {
//we have an array of all items, let's loop through it and change them all to be visible
for (var i:int = 0; i < items.length; i++) {
//items[i].alpha = 1; //alpha values are 0 - 1 in AS3
items[i].visible = true; //use visible instead of alpha if just toggling visibility, it's more efficient
}
randomword.visible = false;
remember.visible = false;
bask.visible = true;
notepape.visible = false;
//! another reason to use visible instead of alpha = 0, is alpha = 0 items will still be clickable! visible = false items cannot be clicked.
}
function foodClicked(e:MouseEvent):void {
if (e.currentTarget == curAnswer) {
//if the current target (the item clicked) is the same item as what we stored in curAnswer, you answered correctly, so do this:
score += 10; //or however much you get for answering correctly
gotoAndStop("listpage"); //not sure what this does?
displayWord();
}else {
//wrong
gotoAndStop("gameoverpage");
}
}
I want to return just 1 item in the filtered array
my code is
private function audioProgress(event:Event):void{
var wordindex:int=0;
function filterFun(element:int, index:int, array:Array):Boolean {
return (element < soundChannel.position);
}
var arr:Array=soundPositions.filter(filterFun);
}
I want "arr" to contains just one item
How can I do that
If I read your code correctly, you are trying to sync to a playing sound? Then using Array.filter is inefficient - you only need to keep track of the most recently passed marker.
Assuming that your soundPositions array is numerically sorted, this can be done in a simple loop:
private var current : int = 0;
private function audioProgress(event:Event):void{
while( current < soundPositions.length -1 &&
soundPositions[current+1] < soundChannel.position )
current++;
doStuffWith(soundPositions[current]);
}
This way, there will only be one iteration of the array - total. The while loop starts at the current index, and it will exit when the value is greater than or equal to the sound's position, so current will always point to the last item the (virtual) playhead has passed.
You need the index of the item you want. If you just want the first item, use:
arr[0];
Another variant to get one item from the initial array:
private function audioProgress(event:Event):void{
var wordindex:int=0;
var firstRequiredItemIndex:int = -1;
function filterFun(element:int, index:int, array:Array):Boolean {
if (element < soundChannel.position)
{
firstRequiredItemIndex = index;
return true;
}
else
{
return false;
}
}
if (soundPositions.some(filterFun))
{
// Your element
soundPositions[firstRequiredItemIndex];
}
}
The function 'some' executes a test function on each item in the array until an item is reached that returns true. So there is no need to check the whole array.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#some%28%29
Is there a way to generically remove an object from an array?
(maybe not using array.filter or creating a new array)
Example:
var arr:Array= new Array();
//create dummy objs
for (var i:uint=0; i < 10; i++){
var someObject:SomeClassObject = new SomeClassObject();
someObject.Name ="Amit"+ i;
someObject.Site="http://www.mysite.com/"+i;
//...many more props
arr.push(someObject);
}
//
removeElement("Amit4",arr);
removeElement("Amit8",arr);
//...so on so forth
Currently im using array.splice() to remove object
for (var i:Number=0; i < arr.length; i++)
{
if (arr[i].Name == element)
{
arr.splice(i, 1);
}
}
I want to write removeElement in such a way that i can use it for different
types of objects.
currently removeElement becomes dependant on implmentation..
Suppose if i want to remove a file from array of files given file name..i wud have to
again write "removeElement" by changing criteria.
Also may be i can vary the criteria varing criteria?
example :
arr= removeElement("Site","http://www.mysite.com/6",arr)
will remove object from arr whose "Site" property is equal to "http://www.mysite.com/6"
(using above example)
ie. removeElement(criteria:object,criteria_value(s):object,arr)
Thanks All.
Use
if(array.indexOf(obj) != -1)
array.splice(array.indexOf(obj),1);
I think the most flexible approach is the one followed by Array::filter. It's up to the caller to determine whether an item should be filtered out of the list or not, through a function callback.
Now, if you want to do it in place, you could write a simple function like this:
function remove(list:Array,callback:Function):Array {
for(var i:int = list.length - 1; i >= 0; i--) {
if(!callback(list[i])) {
list.splice(i,1);
}
}
return list;
}
This returns the list, as it could be convenient if you wanted to chain calls, but it acts on the array you passed instead of creating a new one.
Also note that it loops backwards. Otherwise, splice will get you bogus results.
You could use it like this:
var arr:Array = [1,2,9,10,455];
trace(arr);
function removeCallback(item:Number):Boolean {
return item < 10;
}
remove(arr,removeCallback);
trace(arr);
This way you are not restricted to equality (or inequality). The caller determines if the item should be kept or removed, by returning true or false respectively (to match filter). So, it's pretty much like filter, except it works in-place. If you want, you could also keep the same interface for the callback (passing the index of the item and a reference to the original array) to make it more coherent.
By the way, you can use strings as indices for an array, and then you can safely use the 'delete' keyword to delete an object from inside the "middle" (there's actually no "middle" in this situation :) of the array.
e.g.:
var arr:Array = new Array();
arr['o1'] = new Object();
arr['o1'].someproperty = true;
arr['o2'] = new Object();
arr['o2'].someproperty = true;
arr['o3'] = new Object();
arr['o3'].someproperty = true;
trace (arr['o2'].someproperty);
//Returns 'true'
trace (arr['o2']);
//Returns '[object Object]'
delete arr['o2'];
trace (arr['o2']);
//Returns 'undefined'
trace (arr['o2'].someproperty);
//Returns 'TypeError: Error #1010: A term is undefined and has no properties.'
The disadvantage is you won't be able to know the length of the array (arr.length will return 0), but you can of-course track it yourself...
Here is a generic function which will do what you want:
public static function removeItem(array: Array, propertyName: String, value: String): Array
{
var newArray: Array = [];
for (var index: int = 0; index < array.length; index++) {
var item: Object = array[index];
if (item && item.hasOwnProperty(propertyName)) {
if (item[propertyName] != value)
newArray.push(item);
}
}
return newArray;
}
Would it be possible to use Array.indexOf() to search through an Array by the properties of the Objects within the array:
var myArray:Array = new Array();
var myMovieClip = new MovieClip();
myMovieClip.name = "foo";
myArray.push(myMovieClip);
myArray.indexOf(MovieClip.name == "foo"); //0
OR
myArray.indexOf(myMovieClip.name == "foo"); //0
Both indexOf() above do not work, is there away to achieve this with the correct syntax?
Look into Array's filter method (newly available for AS3). You can write a filter method that returns all objects that will meet your criteria (in your case, a movieclip with a certain name)
index of will search for an entry ... MovieClip.name == "foo" should throw a compiler error, since MovieClip does not have a property "name" ... myMovieClip.name == "foo" will be true, and then you will get the index of true, if it is in the array at all ...
if you really need the index, you will need to iterate over the array ... by key ... or in an incremental loop, if the array is numeric and dense ...
if the array is associative (string keys used) you imperatively need to use for-in loops, since filter and related functions will only cover numeric indices ...
in a numeric array, i'd suggest one of the following two approaches:
//this will return an array of all indices
myArray.map(function (val:*,index:int,...rest):int { return (val.name == "foo") ? index : -1 }).filter(function (val:int,...rest):Boolean { return val != -1 });
//here a more reusable utility function ... you may want to put it to some better place ... just as an example ...
package {
public class ArrayUtils {
public static function indexOf(source:Array, filter:Function, startPos:int = 0):int {
var len:int = source.length;
for (var i:int = startPos; i < len; i++)
if (filter(source[i],i,source)) return i;
return -1;
}
}
}
//and now in your code:
var i:int = ArrayUtils.indexOf(myArray, function (val:*,...rest):Boolean { return val.name == "foo" });
hope that helped ... ;)
greetz
back2dos
Though back2dos' method is cool, I think beginners might find it overly-complicated, so for the sake of them here is a simpler method, that may be easier to use, though won't be as versatile for any situation as back2dos' method.
var myArray:Array = new Array();
var myMovieClip1 = new MovieClip();
var myMovieClip2 = new MovieClip();
myMovieClip1.name = "foo";
myMovieClip2.name = "bar";
myArray.push(myMovieClip1);
myArray.push(myMovieClip2);
function getIndexByName(array:Array, search:String):int {
// returns the index of an array where it finds an object with the given search value for it's name property (movieclips, sprites, or custom objects)
for (var i:int = 0; i < array.length; i++) {
if (array[i].name == search) {
return i;
}
}
return -1;
}
trace("bar index = "+getIndexByName(myArray, "bar"));
trace("foo index = "+getIndexByName(myArray, "foo"));
myMovieClip.name == "foo";
^== if you want to assign a variable, use
myMovieClip.name = "foo";
Here is what I did. Change the function name if you want... this is all just for the sake of explanation.
getObjectFromArrayByProperty(arrayToSearch, 'oBjectProperty', 'value');
function getObjectFromArrayByPoperty(array:Array, _property, search:String):Object{
for (var i:int = 0; i < array.length; i++) {
if (array[i][_property] == search) {
return array[i];
}
}
return null;
}
This returns the object instead of just an index. If a match is not found, the function returns null.