Efficiently navigating arrays and selected strings - arrays

I am a noob playing around with actionscript but i feel this question is a basic coding questionMy project is similar to this picture.
I have four quadrant areas (Red, blue, yellow, and green) that I am adding text buttons to each area with a single word in each button. There are 16 words in each section that are added from 4 arrays that have the preset words (redWordArray, greenWordArray, yellowWordArray, blueWordArray). When clicked, the text button glows using a glow filter and the word gets added to another array for data collecting. For instance, a red word when clicked gets added to a red array (redChosenArray). When the word is clicked again, it removes the glow filter and is removed from the chosen array.
I am finding that my performance is slow and I am wondering if I am adding and deleting words correctly and efficiently. These are my functions for adding the glow filters and the selected word to the array. I would love your insights for best coding practices as I am sure it is a mess!
Thank you!
function selectWord(event:MouseEvent):void
{
var tempWord:String = event.currentTarget.mood.text;
var tempArray:Array;
if (event.currentTarget.clicked == false)
{
event.currentTarget.filters = filterArray;
event.currentTarget.clicked = true;
tempArray = addToArray(tempWord)
tempArray.push(tempWord);
trace(redChosen);
trace(blueChosen);
trace(yellowChosen);
trace(greenChosen);
trace("");
}else if(event.currentTarget.clicked == true)
{
event.currentTarget.filters = emptyFilterArray;
event.currentTarget.clicked = false;
removeMoodWord(tempWord);
trace(redChosen);
trace(blueChosen);
trace(yellowChosen);
trace(greenChosen);
trace("");
}
}
function addToArray(moodWord:String):Array
{
var wordFound:Boolean = false;
var allWords:int = 16;
var chosenArray:Array;
while (!wordFound)
{
for (var h:int = 0; h < allWords; h++)
{
if (moodWord == redWords[h])
{
chosenArray = redChosen;
wordFound = true;
}else if (moodWord == yellowWords[h])
{
chosenArray = yellowChosen
wordFound = true;
}else if (moodWord == greenWords[h])
{
chosenArray = greenChosen
wordFound = true;
}else if (moodWord == blueWords[h])
{
chosenArray = blueChosen
wordFound = true;
}
}
}
return chosenArray;
}
function removeMoodWord(moodWord:String):void
{
if (redChosen.indexOf(moodWord) >= 0)
{
redChosen.splice(redChosen.indexOf(moodWord), 1);
}else if (blueChosen.indexOf(moodWord) >= 0)
{
blueChosen.splice(blueChosen.indexOf(moodWord), 1);
}else if (yellowChosen.indexOf(moodWord) >= 0)
{
yellowChosen.splice(yellowChosen.indexOf(moodWord), 1);
}else if (greenChosen.indexOf(moodWord) >= 0)
{
greenChosen.splice(greenChosen.indexOf(moodWord), 1);
}
i fee}

Related

game maker - how to navigate a map with 2d array

I have to make a navigable map
the starting point is in the center
there are three worlds + the final stage
pressing up I have to navigate from the base to the first level of the first world and go next level in second and third
pressing down I have do go from the third to the second and from the second to the first level and from the first level of the world to the base
pressing left and right I have to change the world
now:
I already made a lot of menus using different methods, but alway using a 1d array
obj_menu:
create event:
///menu
menu[0] = "new";
menu[1] = "load";
menu[2] = "exit";
space = 55;
mpos = 0;
step event:
///move
if(inputs) {
var move = 0;
move -= max(keyboard_check_pressed(vk_up),0);
move += max(keyboard_check_pressed(vk_down),0);
if(move != 0) {
mpos += move;
if(mpos < 0) {
mpos = array_length_1d(saveload) -1;
}
if(mpos > array_length_1d(saveload) -1) {
mpos = 0;
}
}
//push
if(keyboard_check_pressed(vk_enter)) {
scr_menu();
}
}
scr_menu();
switch(mpos) {
case 0: { scr_new_game(); break; } //new
case 1: { scr_load_game(); break; } //load
case 2: { game_end(); break; } //exit
default: { break; }
}
This time I have to navigate in a 2d array
I did this:
obj_map:
create event:
///navigation setup
if(crash_to_base) { lvl[0,0] = true }
if(base_to_ruins_1) { lvl[1,0] = true }
if(ruins_1_to_ruins_2) { lvl[1,1] = true }
if(ruins_2_to_ruins_3) { lvl[1,2] = true }
if(base_to_city_1) { lvl[2,0] = true }
if(city_1_to_city_2) { lvl[2,1] = true }
if(city_2_to_city_3) { lvl[2,2] = true }
if(base_to_lab_1) { lvl[3,0] = true }
if(lab_1_to_lab_2) { lvl[3,1] = true }
if(lab_2_to_lab_3) { lvl[3,2] = true }
if(base_to_castle) { lvl[4,0] = true }
//posizione del menu
mposh = 0;
mposv = 0;
mpos[mposv,mposh] = 0;
step event:
///map navigation
if(inputs) {
moveh -= max(keyboard_check_pressed(vk_left),0);
moveh += max(keyboard_check_pressed(vk_right),0);
movev -= max(keyboard_check_pressed(vk_up),0);
movev += max(keyboard_check_pressed(vk_down),0);
if(moveh != 0) {
//mposh += move;
}
if(movev != 0) {
//mposv += move;
}
push = keyboard_check_pressed(vk_enter);
if(push) {
scr_map();
}
}
how to translate the first method to de sencond need??
Not quite sure what your having difficulty with, perhaps you could elaborate on what exactly the problem is? On a side note however your 1D menu navigation code can be greatly simplified to:
mpos += keyboard_check_pressed(vk_up) - keyboard_check_pressed(vk_down);
var len = array_length_1d(saveload);
if (mpos < 0) { mpos = len - 1; }
if (mpos > len - 1) { mpos = 0; }
and in terms of a 2d map navigation system, it might not be beneficial to use 2d arrays and instead you could use a ds_map which allows you to store all information on each location in one data structure. For instance
var lvlMap = ds_map_create()
lvlMap[?"base-title"] = "Base"
lvlMap[?"base-travel-right"] = "crash"
lvlMap[?"base-travel-left"] = "fortress"
then when you try to move right/left:
var next_location = lvlMap[?current_location+"-travel-"+direction]
current_location = next_location

How to assign value to Numbers in Array?

Hey everyone so I have an Array private var frames:Array; which I give value and initiate in my constructor function like so frames = [2, 3, 4, 5, 6, 7, 8];
Now I am trying to give a string value to each number in the array for my hitTest Function. I was thinking something on the lines of a for loop and giving them values there but having some issues here is what I have so far:
for (var i:int = 0; i < frames.length; i++)
{
var currentFrameNumber = frames[i];
//assign values to numbers in array
if (currentFrameNumber == 2)
{
trace("2_RED");
currentWires.sRed = "RED";
}
if (currentFrameNumber == 3)
{
trace("GREEN");
currentWires.sGreen = "GREEN";
}
if (currentFrameNumber == 4)
{
trace("BLUE");
currentWires.sBlue = "BLUE";
}
if (currentFrameNumber == 5)
{
trace("YELLOW");
currentWires.sYellow = "YELLOW";
}
if (currentFrameNumber == 6)
{
trace("WHITE");
currentWires.sWhite = "WHITE";
}
if (currentFrameNumber == 7)
{
trace("PURPLE");
currentWires.sPurple = "PURPLE";
}
if (currentFrameNumber == 8)
{
trace("BLACK");
currentWires.sBlack = "BLACK";
}
}
this doesn't work at all. I know I Am missing something crucial. Please any help would be appreciated thanks!
****************UPDATE****************
I have my array of Movie clips like so aClockArray = [playScreen.wire_5, playScreen.wire_6, playScreen.wire_7, playScreen.wire_8];
in my last post I finally figure out how to randomize the array with no repeat like so:
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1);
//nWire = randomNumber(2, 8);
currentWires.gotoAndStop(randomFrame);
}
and above in my frames for loop is where I assign the values to the numbers in the frames array for my hitTest which I try to accomplish like so:
private function wireHitTestFunction():void
{
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
if (redCopper.hitTestObject(currentWires) && currentWires.sRed == "RED")
{
//trace("HIT_ RED");
hasRedWire = false;
redCopper.removeEventListener(MouseEvent.MOUSE_DOWN, redWireFunction);
redWire.removeEventListener(MouseEvent.MOUSE_UP, redWireFunction);
trace("HIT");
}
if (blueCopper.hitTestObject(currentWires) && currentWires.sBlue == "BLUE")
{
//trace("HIT_BLUE");
hasBlueWire = false;
blueCopper.removeEventListener(MouseEvent.MOUSE_DOWN, blueWireFunction);
blueWire.removeEventListener(MouseEvent.MOUSE_UP, blueWireFunction);
trace("HIT");
}
I cant seem to figure this out lost in code haha. I probably have it set up really badly.
basically the game is I have 7 colored wires on the stage that the user can drag and place inside the correct color slot. It was working fine until I had added the var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1); I had to change things around. It was working fine when my original code was like so:
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
//var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1);
nWire = randomNumber(2, 8);
currentWires.gotoAndStop(nWire);
//If any of the Wires lands on 2,3,etc.. Assign Color for Hit Test
if (nWire == 2)
{
trace("2_RED");
currentWires.sRed = "RED";
}
if (nWire == 3)
{
trace("GREEN");
currentWires.sGreen = "GREEN";
}
if (nWire == 4)
{
trace("BLUE");
currentWires.sBlue = "BLUE";
}
if (nWire == 5)
{
trace("YELLOW");
currentWires.sYellow = "YELLOW";
}
if (nWire == 6)
{
trace("WHITE");
currentWires.sWhite = "WHITE";
}
if (nWire == 7)
{
trace("PURPLE");
currentWires.sPurple = "PURPLE";
}
if (nWire == 8)
{
trace("BLACK");
currentWires.sBlack = "BLACK";
}
}
I'm not sure exactly what issue you're seeing, and it's hard to know exactly what's going on without seeing the entire code, but I'll take a stab at it...
rather than currentWire.sRed = "RED";
use a single variable to represent the current color, like so:
currentWire.color = "RED";
then..
if (redCopper.hitTestObject(currentWires) && currentWires.color== "RED")
{
//trace("HIT_ RED");
hasRedWire = false;
redCopper.removeEventListener(MouseEvent.MOUSE_DOWN, redWireFunction);
redWire.removeEventListener(MouseEvent.MOUSE_UP, redWireFunction);
trace("HIT");
}
if (blueCopper.hitTestObject(currentWires) && currentWires.color== "BLUE")
{
//trace("HIT_BLUE");
hasBlueWire = false;
blueCopper.removeEventListener(MouseEvent.MOUSE_DOWN, blueWireFunction);
blueWire.removeEventListener(MouseEvent.MOUSE_UP, blueWireFunction);
trace("HIT");
}

flex array filter duplicates

i'm urgently looking for a solution to delete all duplicates from an array in Flex.
I need to filter out all duplicates in the filteredData array.
The indexOf doesn't do the trick here, i believe because objects are being loaded into the array.
Thanks in advance
var columnArray:Array = ['ingenre']; //Datagrid column names to filter on
var songArray:Array = ['id']; //Datagrid column names to filter on
var gridDataProvider:ArrayCollection = PhotoData; //Name of datagrid's dataprovider. In this case e.g. databases
var dataGridName:String = 'dgUserRequest'; //Name of the datagrid you are filtering by
 
//Do not edit code past this point
var filteredData:Array = [];
var added:Boolean=false;
var i:int;
var j:int;
var filtertxt: String;
var matchtxt:String;
 
// Loop Through Grid
for(i=0; i < gridDataProvider.length; i++){
added = false;
 
//Loop through grid column
for(j=0; j<columnArray.length; j++){
if(gridDataProvider[i][columnArray[j]]!=null){
//Grab datagrid cell contents, trim it, and convert to lowercase for comparison.
var filterString:String = gridDataProvider[i][columnArray[j]].toString().toLowerCase();
var songIdString:String = gridDataProvider[i][songArray[j]].toString().toLowerCase();
//Compare the datagrid string(filterString) to the user typed string(filterText).
if(!added){
// loop through the Array & check if there is a match.
for (var k:int = 0;k < filterText.length; k++)
{
filtertxt = filterString.toLowerCase();
matchtxt = filterText[k].toLowerCase();
//if(filterString.toLowerCase() == filterText[k].toLowerCase()){
if(filtertxt.search(matchtxt) >= 0){
if (cmd_classic.selected == true)
{
trace(filteredData.indexOf(songIdString));
if(filteredData.indexOf(songIdString) < 0)
{
if ((filtertxt.search("class") == -1) && (filtertxt.search("baroque") == -1))
{
if (filteredData.indexOf(songIdString) == -1)
{
filteredData.push(gridDataProvider[i]);
added = true;
}
}
else
{
break;
}
}
}
else
{
if (filteredData.lastIndexOf(songIdString) <= 0)
{
filteredData.push(gridDataProvider[i]);
added = true;
}
}
}
}
}else{
//Do nothing, break out.
break;
}
}
}
}
Flex doesn't really have a Set class that I'm aware of. But what I've done in the past when I need to get a list of unique values from a list is to create a new Dictionary. Loop through the list using the values I want to dedupe as the key and getting the key set when I'm finished.

AS3 - Remove spaces from an array for word game

I'm building a word search game using the following AS3 code. My problem is I need to have spaces in my array of words, so that I can have things like states names, but I need the spaces removed before the words go into the puzzle.
The other concern is also that when a person selects a word from the puzzle will it still match the word in the list even though the word in the list still has a space.
I've struggled with this for a few days now and could use some help.
I've pasted all appropriate code below, I believe. Thanks.
Rich
// words and grid
private var wordList:Array;
private var usedWords:Array;
private var grid:Array;
// sprites
private var letterSprites:Sprite;
private var wordsSprite:Sprite;
wordList = ("New York,New Jersey,South Carolina,North Carolina").split(",");
// set up the sprites
gameSprite = new Sprite();
addChild(gameSprite);
letterSprites = new Sprite();
gameSprite.addChild(letterSprites);
wordsSprite = new Sprite();
gameSprite.addChild(wordsSprite);
// array of letters
var letters:Array = placeLetters();
// create word list fields and sprites
for(var i:int=0;i<usedWords.length;i++) {
var newWord:TextField = new TextField();
newWord.defaultTextFormat = letterFormatForList;
if(i < 20){ // first list
newWord.x = listXposition;
newWord.y = i*spacingForList+listYposition;
} else { // second list
newWord.x = listXposition + 130;
newWord.y = i*spacingForList+listYposition - (20 * 19);
}
newWord.width = 135;
newWord.height = spacingForList;
newWord.text = usedWords[i];
newWord.selectable = false;
wordsSprite.addChild(newWord);
}
// set game state
dragMode = "none";
numFound = 0;
}
// place the words in a grid of letters
public function placeLetters():Array {
// create empty grid
var letters:Array = new Array();
for(var x:int=0;x<puzzleSize;x++) {
letters[x] = new Array();
for(var y:int=0;y<puzzleSize;y++) {
letters[x][y] = "*";
}
}
// make copy of word list
var wordListCopy:Array = wordList.concat();
usedWords = new Array();
// make 1000 attempts to add words
var repeatTimes:int = 1000;
repeatLoop:while (wordListCopy.length > wordsLeft) {
if (repeatTimes-- <= 0) break;
// pick a random word, location and direction
var wordNum:int = Math.floor(Math.random()*wordListCopy.length);
var word:String = wordListCopy[wordNum].toUpperCase();
x = Math.floor(Math.random()*puzzleSize);
y = Math.floor(Math.random()*puzzleSize);
var dx:int = Math.floor(Math.random()*3)-1;
var dy:int = Math.floor(Math.random()*3)-1;
if ((dx == 0) && (dy == 0)) continue repeatLoop;
// check each spot in grid to see if word fits
letterLoop:for (var j:int=0;j<word.length;j++) {
if ((x+dx*j < 0) || (y+dy*j < 0) || (x+dx*j >= puzzleSize) || (y+dy*j >= puzzleSize)) continue repeatLoop;
var thisLetter:String = letters[x+dx*j][y+dy*j];
if ((thisLetter != "*") && (thisLetter != word.charAt(j))) continue repeatLoop;
}
// insert word into grid
insertLoop:for (j=0;j<word.length;j++) {
letters[x+dx*j][y+dy*j] = word.charAt(j);
}
// remove word from list
wordListCopy.splice(wordNum,1);
usedWords.push(word);
}
// fill rest of grid with random letters
for(x=0;x<puzzleSize;x++) {
for(y=0;y<puzzleSize;y++) {
if (letters[x][y] == "*") {
letters[x][y] = String.fromCharCode(65+Math.floor(Math.random()*26));
}
}
}
return letters;
}
// player clicks down on a letter to start
public function clickLetter(event:MouseEvent) {
var letter:String = event.currentTarget.getChildAt(0).text;
startPoint = findGridPoint(event.currentTarget);
dragMode = "drag";
}
// player dragging over letters
public function overLetter(event:MouseEvent) {
if (dragMode == "drag") {
endPoint = findGridPoint(event.currentTarget);
// if valid range, show outline
outlineSprite.graphics.clear();
if (isValidRange(startPoint,endPoint)) {
drawOutline(outlineSprite,startPoint,endPoint,0xCCCCCC);
}
}
}
// mouse released
public function mouseRelease(event:MouseEvent) {
if (dragMode == "drag") {
dragMode = "none";
outlineSprite.graphics.clear();
// get word and check it
if (isValidRange(startPoint,endPoint)) {
var word = getSelectedWord();
checkWord(word);
}
}
}
// when a letter is clicked, find and return the x and y location
public function findGridPoint(letterSprite:Object):Point {
// loop through all sprites and find this one
for(var x:int=0;x<puzzleSize;x++) {
for(var y:int=0;y<puzzleSize;y++) {
if (grid[x][y] == letterSprite) {
return new Point(x,y);
}
}
}
return null;
}
// determine if range is in the same row, column, or a 45 degree diagonal
public function isValidRange(p1,p2:Point):Boolean {
if (p1.x == p2.x) return true;
if (p1.y == p2.y) return true;
if (Math.abs(p2.x-p1.x) == Math.abs(p2.y-p1.y)) return true;
return false;
}
// draw a thick line from one location to another
public function drawOutline(s:Sprite,p1,p2:Point,c:Number) {
var off:Point = new Point(offset.x+spacing/2, offset.y+spacing/2);
s.graphics.lineStyle(outlineSize,c);
s.graphics.moveTo(p1.x*spacing+off.x ,p1.y*spacing+off.y-3);
s.graphics.lineTo(p2.x*spacing+off.x ,p2.y*spacing+off.y-3);
}
// find selected letters based on start and end points
public function getSelectedWord():String {
// determine dx and dy of selection, and word length
var dx = endPoint.x-startPoint.x;
var dy = endPoint.y-startPoint.y;
var wordLength:Number = Math.max(Math.abs(dx),Math.abs(dy))+1;
// get each character of selection
var word:String = "";
for(var i:int=0;i<wordLength;i++) {
var x = startPoint.x;
if (dx < 0) x -= i;
if (dx > 0) x += i;
var y = startPoint.y;
if (dy < 0) y -= i;
if (dy > 0) y += i;
word += grid[x][y].getChildAt(0).text;
}
return word;
}
// check word against word list
public function checkWord(word:String) {
// loop through words
for(var i:int=0;i<usedWords.length;i++) {
// compare word
if (word == usedWords[i].toUpperCase()) {
foundWord(word);
}
// compare word reversed
var reverseWord:String = word.split("").reverse().join("");
if (reverseWord == usedWords[i].toUpperCase()) {
foundWord(reverseWord);
}
}
}
// word found, remove from list, make outline permanent
public function foundWord(word:String) {
sndSuccess=new success_sound();
sndSuccessChannel=sndSuccess.play(200);
so.data.totalWordsFound = so.data.totalWordsFound + 1;
so.flush();
// draw outline in permanent sprite
drawOutline(oldOutlineSprite,startPoint,endPoint,0xDDDDDD);
// find text field and set it to gray
for(var i:int=0;i<wordsSprite.numChildren;i++) {
if (TextField(wordsSprite.getChildAt(i)).text.toUpperCase() == word) {
TextField(wordsSprite.getChildAt(i)).textColor = 0x777777;
}
}
// see if all have been found
numFound++;
if (numFound == usedWords.length) {
if (so.data.difficulty == "Easy") {
so.data.easyWon = so.data.easyWon + 1;
}
if (so.data.difficulty == "Medium") {
so.data.mediumWon = so.data.mediumWon + 1;
}
if (so.data.difficulty == "Hard") {
so.data.hardWon = so.data.hardWon + 1;
}
so.flush();
endGame();
}
}
I'm hesitant to post an answer as I'm not really sure what's going on, but hopefully this info will help:
Keep your words in the arrays with spaces, that's a good idea. When you want to check against the words in your game, just convert both words to the same format using a function. eg:
var wordList:Array = ("New York,New Jersey,South Carolina,North Carolina").split(",");
var selectedWord:String = "NEWYORK";
// minWord converts all words to the same format of no spaces and all lower case.
function minWord(word:String):String {
return word.replace(/\s/g, "").toLowerCase();
}
// this loop checks all the words from your array against the selectedWord.
for each(var word:String in wordList) {
trace(minWord(word) + " == " + minWord(selectedWord) + "; ", minWord(word) == minWord(selectedWord));
}
Hope that helps!

Sorting an array to avoid neighboring items having duplicate attributes

I have an array of objects. Each object has a color attribute which could be "red", "blue", "yellow", "green", "orange" or "purple". There are 20-30 objects in the array so colors repeat. My goal is to sort the array so that no colors are next to each other. Distribution of colors is not exactly even but close.
This is what I have so far. It checks the next and previous object for a color match and if it finds a match it moves it to the end of the array.
private function sortColors():void
{
var getNext:uint;
var getPrev:uint;
var maxCount:uint = colorArray.length;
for (var i:uint = 0; i < maxCount; i++) {
var cur:ValueObject = colorArray[i];
(i == maxCount-1) ? getNext = 0 : getNext = i+1;
(i == 0) ? getPrev = maxCount-1 : getPrev = i-1;
var next:ValueObject = colorArray[getNext];
var prev:ValueObject = colorArray[getPrev];
if (cur.color == next.color) {
var move:ValueObject = colorArray[getNext];
colorArray.splice(getNext, 1);
colorArray.push(move);
}
if (cur.color == prev.color) {
var move:ValueObject = colorArray[getPrev];
colorArray.splice(getPrev, 1);
colorArray.push(move);
}
}
}
This works OK but if there is more of a certain color they end up repeating at the end. I could add something to the end to throw those back into the mix but I feel like there must be a better way. Someone enlighten me.
Try:
var colorObjects:Array = [/* list of objects with colors - populated below*/];
var jumbled:Array = [];
var lastColor:String = "";
function getDifferentTile():void
{
if(lastColor.length == 0)
{
jumbled.push(colorObjects.pop());
lastColor = jumbled[0].mycolor;
}
else
{
var i:Object;
for each(i in colorObjects)
{
var repeat:uint = 0;
if(i.mycolor != lastColor)
{
jumbled.push(i);
lastColor = i.mycolor;
colorObjects.splice(colorObjects.indexOf(i), 1);
return;
} else {
repeat++;
}
if (repeat > 0 && repeat == colorObjects.length) {
jumbled.push(i);
colorObjects.splice(colorObjects.indexOf(i), 1);
return;
}
}
}
}
// list of random colors
var colors:Array = ["0x000000","0x444444","0xFFFFFF","0xFF00FF"];
// prepare random array for test
var i:uint = 0;
for(i; i<100; i++)
{
var obj:Object =
{
mycolor: colors[uint(Math.random()*colors.length)]
};
colorObjects.push(obj);
}
// fill the jumble array until the original listing is empty
while(colorObjects.length > 0)
{
getDifferentTile();
}
// output jumbled
var j:Object;
for each(j in jumbled)
{
trace(j.mycolor);
}

Resources