Flash AS3 How to display a random item from an xml list then remove that item from the list so it will not be reused - actionscript-3

I'm using Flash AS3 trying to display random questions from an xml list on stage. When the user clicks an option it should move on to another question but the one they got should be removed from the list so it will not come back.
I have the randomize part okay but can't figure out how to remove the question from the list.
Here is the section I have.
function randomizeQuestion():void {
var numOfQuestions:Number = xmlData.item.length();
var shuffledNumbers:Array = new Array(randomAns.length);
var randomPos:Number = 0;
//Randomizes selected question
currentQuestion = int(Math.random() * numOfQuestions);
//Randomizes answer numbers
for (var i:int = 0; i < shuffledNumbers.length; i++)
{
randomPos = int(Math.random() * randomAns.length);
shuffledNumbers[i] = randomAns.splice(randomPos, 1)[0];
}
randomAns = shuffledNumbers;
correctAns = xmlData.item[currentQuestion].children().(hasOwnProperty("#correct"));
}

Try to get index:
correctAnsIndex = xmlData.item[currentQuestion].children().(hasOwnProperty("#correct")).childIndex();
or if more elements, to get first one:
correctAnsIndex = xmlData.item[currentQuestion].children().(hasOwnProperty("#correct"))[0].childIndex();
then use delete where appropriate, like here:
delete xmlData.item[correctAnsIndex];

I would add another array to your code in which you can store all the questions that are eligible. As a question gets asked, remove it from that array. So you'll have one array of allQuestions and another array of eligibleQuestions. allQuestions can just be a comprehensive list. Then, push all the questions you want to go through into the eligibleQuestions array. As the questions get answered, splice them from the array.

It would be good to also share an example of your XML file that you're loading, but let's use the example below.
<data>
<item>
<question></question>
<option1></option1>
<option2></option2>
</item>
<item>
<question></question>
<option1></option1>
<option2></option2>
</item>
</data>
Based on the code you have, I assume your function is being called each time you want to randomize a question.
Now what you'd want to do is create an array that holds the number of <item> tags you have outside of this function so that you can remove values from it whenever you want.
You can create this var numOfQuestions:Array = new Array(); as a global variable and then initialize it using a loop before you enter the randomizeQuestions() function.
for(var i = 0; i < xmlData['item'].length(); i++)
{
numOfQuestions.push(i);
}
Basically this array will serve as a method of calling a specific item and removing it from the program without altering the actual XML file in any way.
Then whenever you wish to remove an element you use
numOfQuestions.splice(numOfQuestions.indexOf(valueToBeRemoved), 1);
This will search the array for the element you wish to remove and then remove it from the array.
Lastly the randomizeQuestion function has to be modified.
currentQuestion = int(Math.random() * numOfQuestions.length); //since numOfQuestions is now an array instead of a Number

Related

Array of stagewebviews

I am in the need of multiple staged WebViews for holding multiple loaded websites at the same time.
I was hoping to manage this by making an array of webviews object, so i could call them later as view[i].
var view:Array=[webview0, webview1, webview2];
for each (var v in view){
var v:StageWebView = new StageWebView();
This gives error: 1086: Syntax error: expecting semicolon before left bracket.
Does someone know how to make an array like that?
You're doing something really weird there in terms of syntax. If you just want an Array of freshly created instances, it goes like that:
// Initialize the array.
var Views:Array = new Array;
// This loop counts 0,1,2.
for (var i:int = 0; i < 3; i++)
{
// Create a new instance.
// Yes, you can omit () with new operator if there are no arguments.
var aView:StageWebView = new StageWebView;
// Assign the new element to your array.
Views[i] = aView;
}
Or, if you need only 3 then you don't need to go algorithmic.
var Views:Array = [new StageWebView, new StageWebView, new StageWebView];
Not on topic but related:
Here is an example of one HTML page hold multiple StageWebViews
https://www.w3schools.com/graphics/tryit.asp?filename=trymap_basic_many

How do i populate an Array in one class based on a textfield in another class?(Actionscript 3.0)

i have a class (TheList.as). in which i have an array "Data" and it has a couple of values. Then i have a loop through which i am creating a scrollable list which uses the values from "Data" array. [I am trying make a unit converter]
Then i have another class "Units.as". In that class i have created three instances of "TheList". A main list ("myList"), and to sublists "ListFrom" and "ListTo". They are using values from "Data" array. Now i have text field whose value changes to whatever item is clicked. When i click "Angle" in the main list, i want the sublists to get populated with ("Degree", "Radian" etc)..
Here is what i tried
if(myList._TextLabel.text == "Angle")
{
ListFrom.Data = ["Degree", "Radian"];
}
But nothing happens, i do not get any error either. When i do this in an "ENTER_FRAME" event and trace (ListFrom.Data), i can see that the values change, but they do not get assigned to the list items in the list. I would really appreciate the help. Thanks!
Here are complete Classes for understanding the situation better(the code is pretty messy, as i am a newbie to OOP)
TheList.as: http://pastebin.com/FLy5QV9i
Units.as : http://pastebin.com/z2CcHZzC
where you call ListFrom.Data = ["Degree","Radian"], make sure when the data changed, the renders in the ListFrom have been set new data. for example, you may use MyRender in ListFrom for show, you should debug in the set data method in MyRender.
you should call the code below after you call ListFrom.Data = ["Degree","Radian"];
for (var i:int = 0; i < Data.legnth;i++) {
var render:MyRender = ListFrom[i] as MyRender;
if (render) {
render.data = Data[i];
} else {
var render:MyRender = new MyRender();
render.data = Data[i];
ListFrom.addChild(render);
}
}
You can use event listeners, singleton classes or reference one class to another, depending on the style you want. All are equally valid and fast / efficient.

as3 dynamic variable within a loop

I need to have the screenPage var accessible for later calls. I am dynamically creating several pages. The issue is when I call screenPage.startDrag(); then it only drags the last page. How can I add a var in the name or make all the screenPages accessible through code?
Here is code in short:
var screenPage:MovieClip;
for(var p = 1; daTotalPages >= p; p++)
{
screenPage = new theFlagScreen();
}
Can I make screenPage a dynamic var and add like a 1 at the end and then a 2 and so forth with the loop?
Why not use an array ?
var pages:Array = new Array;
for(var p = 1; daTotalPages >= p; p++)
{
var screenPage:MovieClip = new theFlagScreen();
pages.push(screenPage)
}
Now you have an array containing all of your instances.
var myPage:MovieClip = pages[5] as MovieClip;
myPage.startDrag();
Also, the code you have above is creating an instance each time through, but since you then go ahead and create a new one each iteration and assign it to the same variable without storing it or adding it to the display list.... once you create a new one, the last one is marked for garbage collection.
The result is only the LAST instance you created still exists as it's the only one that has a variable that references it.
screenPage is a reference to just ONE thing. In your loop you keep overwriting it as you go and so you end up with it pointing to the very last instance of theFlagScreen... all the others are now lost.
You should follow prototypical's advice and store these instances in an array, that way you don't lose them.

Splice then re-index array in ActionScript 3

I want to remove the first four indexes from the array using splice(), then rebuild the array starting at index 0. How do I do this?
Array.index[0] = 'one';
Array.index[1] = 'two';
Array.index[2] = 'three';
Array.index[3] = 'four';
Array.index[4] = 'five';
Array.index[5] = 'six';
Array.index[6] = 'seven';
Array.index[7] = 'eight';
Array.splice(0, 4);
Array.index[0] = 'five';
Array.index[1] = 'six';
Array.index[2] = 'seven';
Array.index[3] = 'eight';
I am accessing the array via a timer, on each iteration I want to remove the first four indexes of the array. I assumed splice() would remove the indexes then rebuild the array starting at 0 index. it doesn't, so instead what I have done is created a 'deleteIndex' variable, on each iteration a +4 is added to deleteIndex.
var deleteIndex:int = 4;
function updateTimer(event:TimerEvent):void
{
Array.splice(0,deleteIndex);
deleteIndex = deleteIndex + 4;
}
What type of object is "Array" in the code you have shown? The Flash Array object does not have a property named "index". The Array class is dynamic, which means that it let's you add random properties to it at run time (which seems to be what you are doing).
In any case, if you are using the standard Flash Array class, it's splice() method updates the array indexes automatically. Here is a code example that proves it:
var a:Array = [1,2,3,4,5];
trace("third element: ", a[2]); // output: 3
a.splice(2,1); // delete 3rd element
trace(a); // output: 1,2,4,5
trace(a.length); // ouput: 4
trace("third element: ", a[2]); // output: 4
If I am understanding what you want correctly, you need to use the unshift method of Array.
example :
var someArray:Array = new Array(0,1,2,3,4,5,6,7,8);
someArray.splice(0,4);
somearray.unshift(5,6,7,8);
Also, you are using the Array Class improperly, you need to create an instance of an array to work with first.
The question is confusing because you used Array class name instead of an instance of an array. But as the commenter on this post said, if you splice elements, it automatically re-indexes.
im not sure what you want to do, but Array=Array.splice(0,4) should fix somethin..

Re-stacking MovieClips in an Array

I was trying to make a similar thing with the game SameGame (ie. the block above the removed blocks fall downward). Before trying this with an Array that contains MovieClips, this code worked (tried it with int values). With MovieClips on the array, it seems not working the same way.
With int values, example:
popUp(0, 4): Before: 1,2,3,4,5,6,7,8,9,10; After: 1,2,3,4,6,7,8,9,10
But with MovieClips:
popUp(0, 4): Before: 1,2,3,4,5,6,7,8,9,10; After; 1,2,3,4
// Assume the numbers are movieclips XD
Basically, it strips everything else, rather than just the said block >_<
Here's the whole method. Basically, two extra arrays juggle the values above the soon-to-be removed value, remove the value, then re-stack it to the original array.
What could be wrong with this? And am I doing the right thing for what I really wanted to emulate?
function popUp(col:uint, row:uint)
{
var tempStack:Array = new Array();
var extraStack:Array = new Array();
tempStack = IndexArray[col];
removeChild(tempStack[0]);
for(var ctr:uint = tempStack.length-(row+1); ctr > 0; ctr--)
{
removeChild(tempStack[ctr]);
extraStack.push(tempStack.pop());
trace(extraStack);
}
tempStack.pop();
for(ctr = extraStack.length; ctr > 0; ctr--)
{
tempStack.push(extraStack.pop());
//addChild(tempStack[ctr]);
}
IndexArray[col] = tempStack;
}
PS: If it's not too much to ask, are there free step-by-step guides on making a SameGame in AS3 (I fear I might not be doing things right)? Thanks in advance =)
I think you just want to remove an element and have everything after that index shift down a place to fill what you removed. There's an inbuilt function for this called splice(start:uint, length:uint);
Parameters:
start - the index to start removing elements from
length - the amount of elements to remove
var ar:Array = ["hello","there","sir"];
ar.splice(1, 1);
ar is now -> ["hello", "sir"];
As per question:
Here's an example with different types of elements:
var ar:Array = [new MovieClip(), "some string", new Sprite(), 8];
ar.splice(2, 1);
trace(ar); // [object MovieClip], some string, 8
And further example to display the indexes being changed:
trace(ar[2]); // was [object Sprite], is now 8