I'm currently working on a primitive graphic for the inventory
that shows how much space is currently taken and how much theres
left.
It does this by showing 5 rows of 20 squares
(Gray = free space, yellow =space taken).
Now, my problem is that I want to find all values that
are 1 and put them in the last array.
So that the array goes from:
var myMap:Array = [
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0],
[1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,0]
];
to
var myMap:Array = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
Basically I want to sort the entire array so that all zero's come first
and all 1's get put in the last one till its full, then the second last one and so on.
I'm away I will most likely need an algorithm for this but I am hoping theres an easier way to do this. I'm usually a C# developer so AS3 is not my strongest suit.
hopefully someone understood what I ment and can help me, its 4:30 am, so I might not be as lucid as I'd like.
~Thanks
EDIT
Added the code so people can get more of a informed look:
Keep in mind most of the names and so on are placeholders, currently I just need it working.
private function _showInventoryGraphic()
{
var mapWidth = 20;
var mapHeight = 5;
var myMap:Array = [
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0],
[1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,0]
];
var posX:int = 15;
var posY:int = 15;
var startPosY:int = 250;
for (var i:int=0; i<mapHeight; i++)
{
for (var u:int = 0; u < mapWidth; u++)
{
if (myMap[i][u] == 0)
{
var grayRect:Shape = new Shape;
grayRect.graphics.beginFill(0x808080);
grayRect.graphics.drawRect(posX*u, startPosY, 10,10);
grayRect.graphics.endFill();
addChild(grayRect);
}
if (myMap[i][u] == 1)
{
var yellowRect:Shape = new Shape;
yellowRect.graphics.beginFill(0xFFFF00);
yellowRect.graphics.drawRect(posX*u, startPosY, 10,10);
yellowRect.graphics.endFill();
addChild(yellowRect);
}
}
startPosY += posY;
}
}
After trying it out from a few different approaches, I think the biggest challenge is the fact that it is a 2d array.
The first attempt was similar, but like quicksort, where there were 2 pointers at either end of the 2d array and they moved 'inwards' looking for a scenario where the first pointer was a '1' and the last pointer was a '0' and swapping the two, until the pointers met in the 'middle'. I gave up on this method while trying to properly decrement and increment the linear counters in a 2d array. =b
The second attempt was by keeping track of the last index in the array that was as empty and the last index in the array that was full. Then within the addItem and removeItem methods I'd put the item in the correct spot and update the counters to avoid a sort. This seemed to work, but maybe a bit messy and perhaps harder to maintain in the future. It sorts the result in separate arrays.
In the third attempt for a 'direct sort', I think the most simple way then is just flatten the array apart in to a 2d array, sort it, then rejoin it. You would be correct in that this is not the most efficient method, though one thing to consider is how often this needs to run and how efficient it really needs to be given the context. I think a 2d array of only 100 elements is not too big of an issue to use an inefficient sort method?
Maybe someone else can come up with better/cleaner methods. =b
Below is code for what I mentioned.
Second attempt (Note: I did not test this one fully, but it seemed to work):
import flash.geom.Point;
var unsortedMap:Array = [
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0]
];
var sortedMap:Array = [
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0]
];
var rowSize:int = unsortedMap[0].length;
var rowCount:int = unsortedMap.length;
// points to the last index at start, since want to have filled items at the 'end'
var emptySpotPointer:Point = new Point(rowSize - 1, rowCount - 1);
var fullSpotPointer:Point = new Point(rowSize - 1, rowCount - 1);
function print2dArray(prefix:String, input:Array):void {
trace(prefix);
for(var row:String in input){
trace("\t"+ input[row]);
}
trace("");
}
function addItem(inputX:int, inputY:int):void {
if(unsortedMap[inputY][inputX] == 1){
trace("addItem() - Already an item here: "+ inputX +", "+ inputY);
return;
}
trace("addItem() - Adding an item: "+ inputX +", "+ inputY);
unsortedMap[inputY][inputX] = 1;
sortedMap[emptySpotPointer.y][emptySpotPointer.x] = 1;
fullSpotPointer.x = emptySpotPointer.x;
fullSpotPointer.y = emptySpotPointer.y;
if(emptySpotPointer.x == 0){
emptySpotPointer.x = rowSize - 1;
emptySpotPointer.y--;
} else {
emptySpotPointer.x--;
}
}
function removeItem(inputX:int, inputY:int):void {
if(unsortedMap[inputY][inputX] == 0){
trace("removeItem() - No item here to remove: "+ inputX +", "+ inputY);
return;
}
trace("removeItem() - Removing an item here: "+ inputX +", "+ inputY);
unsortedMap[inputY][inputX] = 0;
sortedMap[fullSpotPointer.y][fullSpotPointer.x] = 0;
if(fullSpotPointer.x == (rowSize - 1)){
fullSpotPointer.x = 0;
fullSpotPointer.y++;
} else {
fullSpotPointer.x++;
}
}
// testing stuff here
// -----------------------------------------------------------------
function addRandomitems():void {
var randomX:int = Math.floor(Math.random() * rowSize);
var randomY:int = Math.floor(Math.random() * rowCount);
addItem(randomX, randomY);
}
function removeRandomitems():void {
var randomX:int = Math.floor(Math.random() * rowSize);
var randomY:int = Math.floor(Math.random() * rowCount);
removeItem(randomX, randomY);
}
print2dArray("unsortedMap", unsortedMap);
print2dArray("sortedMap", sortedMap);
trace("Test: Adding items now ---------------------");
var counter:int = 0;
for(counter = 0; counter < 50; counter++){
addRandomitems();
print2dArray("unsortedMap", unsortedMap);
print2dArray("sortedMap", sortedMap);
}
trace("Test: Removing items now ---------------------");
for(counter = 0; counter < 50; counter++){
removeRandomitems();
print2dArray("unsortedMap", unsortedMap);
print2dArray("sortedMap", sortedMap);
}
Third attempt:
import flash.utils.getTimer;
var myMap:Array = [
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0],
[1,0,0,0,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,0]
];
function sort(inputArray:Array):Array {
var rowSize:int = inputArray[0].length;
var flat:Array = new Array();
// flattening the array here
for(var row:String in inputArray){
flat = flat.concat(inputArray[row]);
}
flat.sort();
var result:Array = new Array();
// recreating the original array here by cutting out 'rowSize' chunks and reforming the 2d array
while(flat.length > 0){
result.push(new Array(flat.splice(0, rowSize)));
}
return result;
}
// testing
var startTimer:int = flash.utils.getTimer();
for(var counter:int = 0; counter < 10000; counter++){
sort(myMap);
}
// Running the above 10,000 times takes 1836ms for me.
trace(flash.utils.getTimer() - startTimer);
// just to see the output:
trace(sort(myMap).join("\n"));
please inspect me coding:
function createRandomList():void
{
var newlist:Array = [0,1,2];
var curlist:Array = item[selectedlevel - 1] //selectedlevel = 1;
var normal:int = curlist[0];
var tempboo1:Boolean = false;
var tempboo2:Boolean = false;
var tempboo3:Boolean = false;
while (curlist[0] + curlist[1] + curlist[2] > 0)
{
if (Number(curlist[0]) == 0 && tempboo1 == false)
{
newlist.splice(newlist.indexOf(0), 1);
tempboo1 = true;
}
if (Number(curlist[1]) == 0 && tempboo2 == false)
{
newlist.splice(newlist.indexOf(1), 1);
tempboo2 = true;
}
if (Number(curlist[2]) == 0 && tempboo3 == false)
{
newlist.splice(newlist.indexOf(2), 1);
tempboo3 = true;
}
var temp:int = Math.floor(Math.random()*(newlist.length));
curlist[temp] -= 1;
generatedlist.push(Number(newlist[temp]));
trace(item);
}
while (normal > 0)
{
var temp2:int = Math.floor(Math.random() * 3) + 1;
generatednormal.push(Number(temp2));
normal--;
}
}
My item was [[5,0,0],[10,0,0]];
But after became [[0,0,0],[0,0,0]];
I just want to duplicate Array item to be a new variable curlist.
Every time it traces, returning item[0][0] decreasing 1, I only want to use curlist as a temp Array to calculate a new random Array based on item[0].
Ouput:
4,0,0,10,0,0
3,0,0,10,0,0
2,0,0,10,0,0
1,0,0,10,0,0
0,0,0,10,0,0
Is there any links between them, or is it my problem? Please help! If you need any more infoemation, please comment me!
Arrays are passed by reference, not value. That means when you modify an array through any property that points to it, the original array will be modified.
To make a duplicate, you can use .slice()
Returns a new array that consists of a range of elements from the original array, without modifying the original array. The returned array includes the startIndex element and all elements up to, but not including, the endIndex element.
If you don't pass any parameters, the new array is a duplicate (shallow clone) of the original array.
You can clone your arrays if you want to create a new reference.
function clone( source:Object ):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject( source );
myBA.position = 0;
return( myBA.readObject() );
}
var a:Array = [[0,0],[1,1]];
var b:Array = clone(a);
b[0] = [2,2];
trace(a)
trace(b)
Output
0,0,1,1
2,2,1,1
It works for any object, not only arrays.
More infos here : AS3 - Clone an object
var array : Array = [ 1, 2, 3];
var array2 : Array = array.concnt();
array[ 0 ] = 4;
trace( array );// 1, 2, 3
trace( array 2);// 4, 2 ,3
So use .concat() to duplicate an array with primitives. If you have an arrays with arrays. Duplicate the children arrays, and put them into an empty one. If you have children of children arrays and so forth, make something recursive.