I'm using an autocomplete for my flash app. The autocomplete uses an external text file.
When I'm typing the first word of the sentence, it display all the sentences that begins with this word.
Is it possible to display all sentence that have this word (and not just the begining of the sentence) ?
Exemple :
I've got two phrases : "I'm going to school" and " I'm going to look for him".
I would like to be able to type "school" and that it displays the first sentence.
Do you know how I can do that ?
For now, I have to type "I'm going to s" in order to display the first sentence.
Here's my code :
urlLoader.load(new URLRequest("test.txt"));
urlLoader.addEventListener(Event.COMPLETE, loadComplete);
inputField.addEventListener(KeyboardEvent.KEY_UP, suggest);
function loadComplete(e:Event):void
{
suggestions = e.target.data.split(",");
}
function suggest(e:KeyboardEvent):void
{
suggested = [];
for (var i:int = 0; i < textfields.length; i++)
{
removeChild(textfields[i]);
}
textfields = [];
for (var j:int = 0; j < suggestions.length; j++)
{
if (suggestions[j].indexOf(inputField.text.toLowerCase()) == 0)
{
var term:TextField = new TextField();
term.width = 300;
term.height = 20;
term.x = 70;
term.y = (20 * suggested.length) + 314;
term.border = true;
term.borderColor = 0x353535;
term.background = true;
term.backgroundColor = 0xFF9900;
term.textColor = 0x4C311D;
term.defaultTextFormat = format;
term.addEventListener(MouseEvent.MOUSE_UP, useWord);
term.addEventListener(MouseEvent.MOUSE_OVER, hover);
term.addEventListener(MouseEvent.MOUSE_OUT, out);
term.addEventListener(MouseEvent.CLICK, tellMe);
addChild(term);
textfields.push(term);
suggested.push(suggestions[j]);
term.text = suggestions[j];
}
}
if (inputField.length == 0)
{
suggested = [];
for (var k:int = 0; k < textfields.length; k++)
{
removeChild(textfields[k]);
}
textfields = [];
}
if(e.keyCode == Keyboard.DOWN && currentSelection < textfields.length-1)
{
currentSelection++;
textfields[currentSelection].textColor = 0x4C311D;
}
if(e.keyCode == Keyboard.UP && currentSelection > 0)
{
currentSelection--;
textfields[currentSelection].textColor = 0x4C311D;
}
if(e.keyCode == Keyboard.ENTER)
{
inputField.text = textfields[currentSelection].text;
suggested = [];
for (var l:int = 0; l < textfields.length; l++)
{
removeChild(textfields[l]);
}
textfields = [];
currentSelection = 0;
}
}
function useWord(e:MouseEvent):void
{
inputField.text = e.target.text;
suggested = [];
for (var i:int = 0; i < textfields.length; i++)
{
removeChild(textfields[i]);
}
textfields = [];
}
Thank you
Change the condition from:
suggestions[j].indexOf(inputField.text.toLowerCase()) == 0
to
suggestions[j].indexOf(inputField.text.toLowerCase()) != -1
Related
I have generated a maze using depth first search - recursive backtracker algorithm. I also want to solve, but not getting idea about how to start solving my maze.
I am using p5.js to create my maze, and want to solve my already generated maze.
This is my javascript code for generating maze. You might want to add p5.js cdn in your html file if you want to run this code.
var cols, rows;
var w = 40;
var grid = [];
var current;
var stack = [];
function setup() {
createCanvas(400,400);
cols = floor(width/w);
rows = floor(height/w);
frameRate(5);
for (var j = 0; j<rows; j++){
for (var i = 0; i < cols; i++) {
var cell = new Cell(i,j);
grid.push(cell);
}
}
current = grid[0];
}
function draw(){
background(51);
for (var i = 0; i<grid.length; i++){
grid[i].show();
}
current.visited = true;
current.highlight();
var next = current.checkNeighbours();
if (next) {
next.visited = true;
stack.push(current);
removeWalls(current,next);
current = next;
}
else if(stack.length > 0){
current = stack.pop();
}
}
function index(i,j){
if (i < 0 || j < 0 || i > cols-1 || j > rows-1) {
return -1;
}
return i + j * cols;
}
function Cell(i,j){
this.i = i;
this.j = j;
this.walls = [true,true,true,true];
this.visited = false;
this.checkNeighbours = function(){
var neighbours = [];
var top = grid[index(i, j-1)];
var right = grid[index(i+1, j)];
var bottom = grid[index(i, j+1)];
var left = grid[index(i-1, j)];
if (top && !top.visited){
neighbours.push(top);
}
if (right && !right.visited){
neighbours.push(right);
}
if (bottom && !bottom.visited){
neighbours.push(bottom);
}
if (left && !left.visited){
neighbours.push(left);
}
if (neighbours.length > 0){
var r = floor(random(0, neighbours.length));
return neighbours[r];
}
else{
return undefined;
}
}
this.highlight = function(){
x = this.i*w;
y = this.j*w;
noStroke();
fill(0,0,255,200);
rect(x,y,w,w);
}
this.show = function(){
x = this.i*w;
y = this.j*w;
stroke(255);
if (this.walls[0]){
line(x ,y ,x+w ,y);
}
if (this.walls[1]){
line(x+w ,y ,x+w ,y+w);
}
if (this.walls[2]){
line(x+w ,y+w ,x ,y+w);
}
if (this.walls[3]){
line(x ,y+w ,x ,y)
}
if (this.visited) {
noStroke();
fill(255,0,255,100);
rect(x,y,w,w);
}
}
}
function removeWalls(a,b){
var x = a.i - b.i;
if (x === 1){
a.walls[3] = false;
b.walls[1] = false;
}
else if (x === -1){
a.walls[1] = false;
b.walls[3] = false;
}
var y = a.j - b.j;
if (y === 1){
a.walls[0] = false;
b.walls[2] = false;
}
else if (y === -1){
a.walls[2] = false;
b.walls[0] = false;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>
There are many algorithmsfor solving mazes. One simple way to solve mazes created with the recursive backtracker algorithm is to keep track of the solution as the maze is being generated.
Make the first cell the starting cell and push it onto the solution stack
Make the last cell the goal cell
While the solution stack does not contain the goal cell
if the next neighbor is un-visited push it onto the solution stack
if a cell has no next neighbor pop the solution stack as we are backtracking
When the goal cell is pushed onto the solution stack mark the solution complete
Adapting the questions code so that it also implements the solution algorithm we have:
var cols, rows;
var w = 40;
var grid = [];
var current;
var stack = [];
var solution = [];
var goal;
var solutionComplete;
function setup() {
createCanvas(400,400);
cols = floor(width/w);
rows = floor(height/w);
frameRate(5);
for (var j = 0; j<rows; j++){
for (var i = 0; i < cols; i++) {
var cell = new Cell(i,j);
grid.push(cell);
}
}
current = grid[0];
grid[grid.length - 1].goal = true;
solution.push(grid[0]);
}
function draw(){
background(51);
for (var i = 0; i<grid.length; i++){
grid[i].show();
}
current.visited = true;
current.highlight();
var next = current.checkNeighbours();
if (next) {
if (!next.visited){
if (!solutionComplete){
solution.push(next);
if (next.goal){
solutionComplete = true;
}
}
}
next.visited = true;
stack.push(current);
removeWalls(current,next);
current = next;
}
else if(stack.length > 0){
current = stack.pop();
if (!solutionComplete){
solution.pop();
}
}
if (solutionComplete){
for (let i = 0; i < solution.length; i++){
solution[i].solutionCell = true;
}
}
}
function index(i,j){
if (i < 0 || j < 0 || i > cols-1 || j > rows-1) {
return -1;
}
return i + j * cols;
}
function Cell(i,j){
this.i = i;
this.j = j;
this.walls = [true,true,true,true];
this.visited = false;
this.goal = false;
this.solutionCell = false;
this.checkNeighbours = function(){
var neighbours = [];
var top = grid[index(i, j-1)];
var right = grid[index(i+1, j)];
var bottom = grid[index(i, j+1)];
var left = grid[index(i-1, j)];
if (top && !top.visited){
neighbours.push(top);
}
if (right && !right.visited){
neighbours.push(right);
}
if (bottom && !bottom.visited){
neighbours.push(bottom);
}
if (left && !left.visited){
neighbours.push(left);
}
if (neighbours.length > 0){
var r = floor(random(0, neighbours.length));
return neighbours[r];
}
else{
return undefined;
}
}
this.highlight = function(){
x = this.i*w;
y = this.j*w;
noStroke();
fill(0,0,255,200);
rect(x,y,w,w);
}
this.show = function(){
x = this.i*w;
y = this.j*w;
stroke(255);
if (this.walls[0]){
line(x ,y ,x+w ,y);
}
if (this.walls[1]){
line(x+w ,y ,x+w ,y+w);
}
if (this.walls[2]){
line(x+w ,y+w ,x ,y+w);
}
if (this.walls[3]){
line(x ,y+w ,x ,y)
}
if (this.goal){
noStroke();
fill(0,255,0,100);
rect(x,y,w,w);
}
else if (this.solutionCell){
noStroke();
fill(255,0,0,100);
rect(x,y,w,w);
}else if(this.visited) {
noStroke();
fill(255,0,255,100);
rect(x,y,w,w);
}
}
}
function removeWalls(a,b){
var x = a.i - b.i;
if (x === 1){
a.walls[3] = false;
b.walls[1] = false;
}
else if (x === -1){
a.walls[1] = false;
b.walls[3] = false;
}
var y = a.j - b.j;
if (y === 1){
a.walls[0] = false;
b.walls[2] = false;
}
else if (y === -1){
a.walls[2] = false;
b.walls[0] = false;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
It would not be difficult to break the maze generation and solution implementations apart so that the maze is completely generated before the solution is determined but unless there is a restriction that forces us to solve a completed maze it makes sense to build the solution along with the maze.
Sorry about this this is very related but coding train a coding youtuber made a maze generating algorithm, but i don't know if it used depth first search
I have an array with movieclips that I place on the stage. I want to use the keyboard arrow keys to change alpha of each movieclip separately, as if you are navigating trough them ( I hope this makes sence).
So far I can only highlight them all at once using the UP/DOWN arrow.My goal is to loop trough them with highlight and downlight using alpha property.
This is my code:
import flash.events.KeyboardEvent;
import flash.events.Event;
var num1: Number = 262;
var aantal: Number = 8;
function Main() {
var BTN_arr: Array = new Array();
var houder: Number = 1;
var aantal2: uint = BTN_arr.length;
var nextBTN: uint;
var currentBTN: uint;
for (var i = 0; i < aantal; i++) {
var myBTN: BTNBg = new BTNBg();
myBTN.name = "btn" + i;
BTN_arr.push(myBTN);
addChild(myBTN);
myBTN.alpha = .45;
myBTN.x = 40;
myBTN.y = num1;
num1 += 90;
}
BTN_arr[0].alpha = 1;
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e: KeyboardEvent): void {
if (e.keyCode == Keyboard.DOWN) {
for (var i = 0; i < BTN_arr.length; i++) {
BTN_arr[i].alpha = 1;
}
}
trace("down");
if (e.keyCode == Keyboard.UP) {
for (var j = 0; j < BTN_arr.length; j++) {
BTN_arr[j].alpha = .45;
}
trace("up");
//MyBTN.alpha = 1;
}
}
}
Main();
var position:int = 0;
function updateHighlight() : void{
BTN_arr[position].alpha = 1; //highlight new one
}
function myKeyDown(e: KeyboardEvent): void {
if (e.keyCode == Keyboard.DOWN) {
trace("down");
if(position > 0){
BTN_arr[position].alpha = .45; //unhighlight current
position--;
updateHighlight();
}
}
if (e.keyCode == Keyboard.UP) {
trace("up");
if(position < BTN_arr.length - 1){ //is not the last one
BTN_arr[position].alpha = .45; //unhighlight current
position++;
updateHighlight();
}
}
}
To do what you want, you don't need to use a for loop every time to set buttons alphas, so you can use a var to set the current button and you set alpha just to it, like this :
var current_button:int = 0;
var sens:int = 0; // -1 : up, 1 : down
stage.addEventListener(Event.ENTER_FRAME, _onEnterFrame)
function _onEnterFrame(e:Event):void {
if(sens != 0){
BTN_arr[current_button].alpha = .45;
if(0 <= current_button + sens && current_button + sens < BTN_arr.length) current_button += sens;
// if you want to pass from the last button to the first one and vice versa, you can enable these 3 lines and disable the 1st if
//current_button += sens;
//if(current_button < 0) current_button = BTN_arr.length - 1;
//else if(current_button >= BTN_arr.length) current_button = 0;
BTN_arr[current_button].alpha = 1;
sens = 0;
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
function _onKeyDown(e: KeyboardEvent): void {
if (e.keyCode == Keyboard.DOWN) {
sens = 1;
} else if (e.keyCode == Keyboard.UP) {
sens = -1;
}
}
Which will give you something like this, and like this for the 2nd case (with 3 commented lines enabled).
Hope that can help.
I have the following scenario:
if (event.status == AMFResultEvent.SUCCESS) {
var lev1:uint = 0;
var lev2:uint = 0;
var lev3:uint = 0;
var lev4:uint = 0;
var lev5:uint = 0;
var lev6:uint = 0;
for (var i:int = 0; i < event.result.length; i++) {
if (mainLevel == "1") {
lev1++;
}
if (mainLevel == "2") {
lev2++;
}
if (mainLevel == "3") {
lev3++;
}
if (mainLevel == "4") {
lev4++;
}
if (mainLevel == "5") {
lev5++;
}
if (mainLevel == "6") {
lev6++;
}
}
for (var j:int = 1; j < 7; j++) {
_row = new StatisticsRow(event.result[j], this);
_rowsPlace.addChild(_row);
_row.y = (_row.height +1) * j;
_row.codeLevel.htmlText = j; // works as it should
// need to access variables lev1 - lev6, called by something like "lev"+j here:
_row.amount.htmlText =
}
// traces correct amounts of mainLevels from the i loop:
trace ("level 1: " + lev1);
trace ("level 2: " + lev2);
trace ("level 3: " + lev3);
trace ("level 4: " + lev4);
trace ("level 5: " + lev5);
trace ("level 6: " + lev6);
}
I'm missing something obvious here, as the ["lev"]+j doen't work. How can I dynamically acces the lev1 - lev6 in the j-loop? As the code comment at the bottoms shows, this traces as expected.
Thanks in advance!
You can access them with brackets, string concatenation, and the this keyword. Here's an example of how you would use bracket notation in a loop:
for (var i:int = 0; i <= 6; i++) {
var currLev = this["lev"+i];
// do stuff to currLev
}
Thanks for answering guys!
I had a lousy approach to my problem anyway, and should have used an array right away:
var mainLevels:Array = new Array();
for (var n:int = 1; n < 7; n++) {
mainLevels[n] = 0;
}
if (event.status == AMFResultEvent.SUCCESS) {
for (var i:int = 0; i < event.result.length; i++) {
var data = event.result[i];
var correctCode:String = data["correct"];
var mainLevelFound:uint = uint(correctCode.substr(0, 1));
for (var k:int = 1; k < 7; k++) {
if (k == mainLevelFound) {
mainLevels[k]++;
}
}
}
for (var j:int = 1; j < 7; j++) {
_row = new StatisticsRow(event.result[j], this);
_rowsPlace.addChild(_row);
_row.y = (_row.height +1) * j;
_row.codeLevel.htmlText = j;
// Now this works as a reference to mainLevels[*] created above!
_row.amount.htmlText = mainLevels[j];
}
Thanks again for your effort :)
mBlocks is a 2-dimensional array of Block objects. Every time my application runs, it runs the InitGridNumbers function. Sometimes, it will get stuck in an infinite loop. Other times, it builds and runs without issues.
public function InitGridNumbers():void
{
var tempRow:Array;
var tempColumn:Array;
var tempNum:int;
for (var i:int = 0; i < mNumRows; i++)
{
tempRow = GetRow(i);
for (var j:int = 0; j < mNumColumns; j++)
{
// if number is unassigned
if (tempRow[j] == 0)
{
var cantMoveOn:Boolean = true;
while (cantMoveOn)
{
tempNum = Math.random() * mNumColumns + 1;
if (!CheckRow(i, tempNum) && !CheckColumn(j, tempNum))
cantMoveOn = false;
}
mBlocks[i][j].SetNumber(tempNum);
}
}
}
}
public function CheckRow(rowNum:int, checkNum:int):Boolean
{
var tempRow:Array = GetRow(rowNum);
for (var i:int = 0; i < mNumColumns; i++)
{
if (checkNum == tempRow[i])
return true;
}
return false;
}
public function CheckColumn(columnNum:int, checkNum:int):Boolean
{
var tempColumn:Array = GetColumn(columnNum);
for (var i:int = 0; i < mNumColumns; i++)
{
if (checkNum == tempColumn[i])
return true;
}
return false;
}
public function GetRow(rowNum:int):Array
{
var rowArray:Array = new Array(mNumRows);
for (var i:int = 0; i < mNumRows; i++)
rowArray[i] = mBlocks[rowNum][i].mNumber;
return rowArray;
}
public function GetColumn(columnNum:int):Array
{
var columnArray:Array = new Array(mNumColumns);
for (var i:int = 0; i < mNumColumns; i++)
columnArray[i] = mBlocks[i][columnNum].mNumber;
return columnArray;
}
To begin with, checkColumn, getColumn and getRow methods are wrong. To get a row, you should copy numColumns items and to get a column, you should copy numRows items. In other words, if there are r rows and c columns, there would be c items per each row and r items per each column.
public function checkColumn(columnNum:int, checkNum:int):Boolean
{
var tempColumn:Array = getColumn(columnNum);
for (var i:int = 0; i < mNumRows; i++)
{
if (checkNum == tempColumn[i])
return true;
}
return false;
}
public function getRow(rowNum:int):Array
{
var rowArray:Array = new Array();//needn't specify length in advance.
for (var i:int = 0; i < mNumColumns; i++)
rowArray[i] = mBlocks[rowNum][i].mNumber;
return rowArray;
}
public function getColumn(columnNum:int):Array
{
var columnArray:Array = new Array();
for (var i:int = 0; i < mNumRows; i++)
columnArray[i] = mBlocks[i][columnNum].mNumber;
return columnArray;
}
while (cantMoveOn)
{
//call Math.floor
tempNum = Math.floor(Math.random() * mNumColumns) + 1;
if (!checkRow(i, tempNum) && !checkColumn(j, tempNum))
cantMoveOn = false;
}
It looks like you're checking for a number that is not present in the current row and column. It's hard to say without knowing more details, but can you think of a scenario where this would be impossible?
For example, if there are four columns and five rows, the tempNum would always be between one and four. Now if the number of rows is five and the corresponding column already has all numbers up to four, the if statement would never evaluate to true and hence you'd end up in an infinite loop
0 1 2 3
1
2
3
4
in case grid is a square, how about this:
0 1 2 3
4
0
0
How do you loop through all the childs in a DisplayObjectContainer in as3? I would like a syntax like this:
for each(var displayObject:DisplayObject in displayObjectContainer )
{
displayObject.x += 10;
displayObject.y += 10;
}
Not sure if for each works, but this works.
for (var i:int = 0; i<myObj.numChildren; i++)
{
trace(myObj.getChildAt(i));
}
something like this maybe?
function getChildren(target:DisplayObjectContainer):Array {
var count:uint = target.numChildren;
var ret:Array = [];
for (var i:int = 0; i < count; i++)
ret.push(target.getChildAt(0));
return ret;
}
and then
for each (var child:Array in getChildren(displayObjectContainer)) {
//....
}
greetz
back2dos
You can use following recursive function to iterate through all children of any DisplayObjectContainer class.
function getChildren(dsObject:DisplayObjectContainer, iDepth:int = 0):void
{
var i:int = 0;
var sDummyTabs:String = "";
var dsoChild:DisplayObject;
for (i ; i < iDepth ; i++)
sDummyTabs += "\t";
trace(sDummyTabs + dsObject);
for (i = 0; i < dsObject.numChildren ; ++i)
{
dsoChild = dsObject.getChildAt(i);
if (dsoChild is DisplayObjectContainer && 0 < DisplayObjectContainer(dsoChild).numChildren)
getChildren(dsoChild as DisplayObjectContainer,++iDepth);
else
trace(sDummyTabs + "\t" + dsoChild);
}
}
It will display all children in hierarchical manner exactly as DisplayList tree.
My two cents.
public static function traceDisplayList(displayObject:DisplayObject, maxDepth:int = 100, skipClass:Class = null, levelSpace:String = " ", currentDepth:int = 0):void
{
if (skipClass != null) if (displayObject is skipClass) return;
trace(levelSpace + displayObject.name); // or any function that clean instance name
if (displayObject is DisplayObjectContainer && currentDepth < maxDepth)
{
for (var i:int = 0; i < DisplayObjectContainer(displayObject).numChildren; i++)
{
traceDisplayList(DisplayObjectContainer(displayObject).getChildAt(i), maxDepth, skipClass, levelSpace + " ", currentDepth + 1);
}
}
}