Unsolvable maze generator using randomized Kruskal's algorithm - path-finding

I have a pathfinding game and I want to generate a maze using randomized Kruskal's algorithm. I am using a rank-based disjoint set to detect cycles. Specifically, I am using this implementation.
However, it turns out that the mazes could not be solved at all. Which leads me to believe that something is wrong with my implementation logic.
function generateKruskals(grid)
{
grid = initWalls(grid);
let MST = {};
for(let i = 0; i < NUM_ROWS; i++)
{
for(let j = 0; j < NUM_COLS; j++)
{
let node = grid[i][j];
if(!node.isStart && !node.isFinish)
{
let entry = makeSet();
entry.data = node;
MST[[i, j]] = entry;
}
}
}
while(Object.keys(MST).length > 0)
{
let keys = Object.keys(MST);
let nodeKey = keys[Math.floor(Math.random() * keys.length)];
let nodeSet = MST[nodeKey];
let node = nodeSet.data;
let neighbors = getNeighborWalls(grid, node);
if (neighbors.length > 0){
let neighbor = neighbors[Math.floor(Math.random() * neighbors.length)];
let neighborNodeset = MST[[neighbor.row, neighbor.col]];
if (neighborNodeset !== undefined)
{
if (find(nodeSet) !== find(neighborNodeset)) tearDownWall(neighborNodeset.data);
union(nodeSet, neighborNodeset);
}
}
delete MST[nodeKey];
}
return grid;
}
Here is what the unsolvable maze looks like.
UPDATE: include the getNeighborWalls implementation.
export function getNeighborWalls(grid, node) {
let neighbors = [];
try {
let leftNeighbor = grid[node.row][node.col - 1];
if (isNodeAWall(leftNeighbor)) neighbors.push(leftNeighbor);
} catch (err) {}
try {
let rightNeighbor = grid[node.row][node.col + 1];
if (isNodeAWall(rightNeighbor)) neighbors.push(rightNeighbor);
} catch (err) {}
try {
let topNeighbor = grid[node.row - 1][node.col];
if (isNodeAWall(topNeighbor)) neighbors.push(topNeighbor);
} catch (err) {}
try {
let bottomNeighbor = grid[node.row + 1][node.col];
if (isNodeAWall(bottomNeighbor)) neighbors.push(bottomNeighbor);
} catch (err) {}
return neighbors;
}

Related

Select symbol definition path

I need to view the segments and handles of the path that defines a SymbolItem. It is a related issue to this one but in reverse (I want the behavior displayed on that jsfiddle).
As per the following example, I can view the bounding box of the SymbolItem, but I cannot select the path itself in order to view its segments/handles. What am I missing?
function onMouseDown(event) {
project.activeLayer.selected = false;
// Check whether there is something on that position already. If there isn't:
// Add a circle centered around the position of the mouse:
if (event.item === null) {
var circle = new Path.Circle(new Point(0, 0), 10);
circle.fillColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
var circleSymbol = new SymbolDefinition(circle);
multiply(circleSymbol, event.point);
}
// If there is an item at that position, select the item.
else {
event.item.selected = true;
}
}
function multiply(item, location) {
for (var i = 0; i < 10; i++) {
var next = item.place(location);
next.position.x = next.position.x + 20 * i;
}
}
Using SymbolDefinition/SymbolItem prevent you from changing properties of each symbol items.
The only thing you can do in this case is select all symbols which share a common definition.
To achieve what you want, you have to use Path directly.
Here is a sketch showing the solution.
function onMouseDown(event) {
project.activeLayer.selected = false;
if (event.item === null) {
var circle = new Path.Circle(new Point(0, 0), 10);
circle.fillColor = Color.random();
// just pass the circle instead of making a symbol definition
multiply(circle, event.point);
}
else {
event.item.selected = true;
}
}
function multiply(item, location) {
for (var i = 0; i < 10; i++) {
// use passed item for first iteration, then use a clone
var next = i === 0 ? item : item.clone();
next.position = location + [20 * i, 0];
}
}

Iterating over basic “for” loop using Handlebars.js

I’m new to Handlebars.js and just started using it. Most of the examples are based on iterating over an object. I wanted to know how to use handlebars in basic for loop.
Example.
for(i=0 ; i<100 ; i++) {
create li's with i as the value
}
How can this be achieved?
There's nothing in Handlebars for this but you can add your own helpers easily enough.
If you just wanted to do something n times then:
Handlebars.registerHelper('times', function(n, block) {
var accum = '';
for(var i = 0; i < n; ++i)
accum += block.fn(i);
return accum;
});
and
{{#times 10}}
<span>{{this}}</span>
{{/times}}
If you wanted a whole for(;;) loop, then something like this:
Handlebars.registerHelper('for', function(from, to, incr, block) {
var accum = '';
for(var i = from; i < to; i += incr)
accum += block.fn(i);
return accum;
});
and
{{#for 0 10 2}}
<span>{{this}}</span>
{{/for}}
Demo: http://jsfiddle.net/ambiguous/WNbrL/
Top answer here is good, if you want to use last / first / index though you could use the following
Handlebars.registerHelper('times', function(n, block) {
var accum = '';
for(var i = 0; i < n; ++i) {
block.data.index = i;
block.data.first = i === 0;
block.data.last = i === (n - 1);
accum += block.fn(this);
}
return accum;
});
and
{{#times 10}}
<span> {{#first}} {{#index}} {{#last}}</span>
{{/times}}
If you like CoffeeScript
Handlebars.registerHelper "times", (n, block) ->
(block.fn(i) for i in [0...n]).join("")
and
{{#times 10}}
<span>{{this}}</span>
{{/times}}
This snippet will take care of else block in case n comes as dynamic value, and provide #index optional context variable, it will keep the outer context of the execution as well.
/*
* Repeat given markup with given times
* provides #index for the repeated iteraction
*/
Handlebars.registerHelper("repeat", function (times, opts) {
var out = "";
var i;
var data = {};
if ( times ) {
for ( i = 0; i < times; i += 1 ) {
data.index = i;
out += opts.fn(this, {
data: data
});
}
} else {
out = opts.inverse(this);
}
return out;
});
Couple of years late, but there's now each available in Handlebars which allows you to iterate pretty easily over an array of items.
https://handlebarsjs.com/guide/builtin-helpers.html#each

Disable collision for certain event sources in fullcalendar

Hi I want to have an event source which allows overlaying(collision with) other event sources without resizing.
But the other event sources should still be using the normal collision detection and resizing?
Did somebody have the same problem?
Ok I found the solution:
First change the function segCollide(seg1, seg2) in fullcalendar to:
function segsCollide(seg1, seg2) {
if(seg1.allowCollision || seg2.allowCollision)
{
return false
}
else
{
return seg1.end > seg2.start && seg1.start < seg2.end;
}
}
And sliceSegs() to:
function sliceSegs(events, visEventEnds, start, end) {
var segs = [],
i, len=events.length, event,
eventStart, eventEnd,
segStart, segEnd,
isStart, isEnd;
for (i=0; i<len; i++) {
event = events[i];
allowCollision = event.source.allowCollision;
eventStart = event.start;
eventEnd = visEventEnds[i];
if (eventEnd > start && eventStart < end) {
if (eventStart < start) {
segStart = cloneDate(start);
isStart = false;
}else{
segStart = eventStart;
isStart = true;
}
if (eventEnd > end) {
segEnd = cloneDate(end);
isEnd = false;
}else{
segEnd = eventEnd;
isEnd = true;
}
segs.push({
event: event,
start: segStart,
end: segEnd,
allowCollision: allowCollision,
isStart: isStart,
isEnd: isEnd,
msLength: segEnd - segStart
});
}
}
return segs.sort(segCmp);
}

More efficient way to remove an element from an array in Actionscript 3

I have an array of objects. Each object has a property called name. I want to efficiently remove an object with a particular name from the array. Is this the BEST way?
private function RemoveSpoke(Name:String):void {
var Temp:Array=new Array;
for each (var S:Object in Spokes) {
if (S.Name!=Name) {
Temp.push(S);
}
}
Spokes=Temp;
}
If you are willing to spend some memory on a lookup table this will be pretty fast:
private function remove( data:Array, objectTable:Object, name:String):void {
var index:int = data.indexOf( objectTable[name] );
objectTable[name] = null;
data.splice( index, 1 );
}
The test for this looks like this:
private function test():void{
var lookup:Object = {};
var Spokes:Array = [];
for ( var i:int = 0; i < 1000; i++ )
{
var obj:Object = { name: (Math.random()*0xffffff).toString(16), someOtherProperty:"blah" };
if ( lookup[ obj.name ] == null )
{
lookup[ obj.name ] = obj;
Spokes.push( obj );
}
}
var t:int = getTimer();
for ( var i:int = 0; i < 500; i++ )
{
var test:Object = Spokes[int(Math.random()*Spokes.length)];
remove(Spokes,lookup,test.name)
}
trace( getTimer() - t );
}
myArray.splice(myArray.indexOf(myInstance), 1);
The fastest way will be this:
function remove(array: Array, name: String): void {
var n: int = array.length
while(--n > -1) {
if(name == array[n].name) {
array.splice(n, 1)
return
}
}
}
remove([{name: "hi"}], "hi")
You can also remove the return statement if you want to get rid of all alements that match the given predicate.
I don't have data to back it up but my guess is that array.filter might be the fastest.
In general you should prefer the old for-loop over "for each" and "for each in" and use Vector if your elements are of the same type. If performance is really important you should consider using a linked list.
Check out Grant Skinners slides http://gskinner.com/talks/quick/ and Jackson Dunstan's Blog for more infos about optimization.
If you don't mind using the ArrayCollection, which is a wrapper for the Array class, you could do something like this:
private function RemoveSpoke(Name:String, Spokes:Array):Array{
var ac:ArrayCollection = new ArrayCollection(Spokes);
for (var i:int=0, imax:int=ac.length; i<imax; i++) {
if (Spokes[i].hasOwnProperty("Name") && Spokes[i].Name === Name) {
ac.removeItemAt(i);
return ac.source;
}
}
return ac.source;
}
You could also use ArrayCollection with a filterFunction to get a view into the same Array object
Perhaps this technique (optimized splice method by CJ's) will further improve the one proposed by Quasimondo:
http://cjcat.blogspot.com/2010/05/stardust-v11-with-fast-array-splicing_21.html
Here's an efficient function in terms of reusability, allowing you to do more than remove the element. It returns the index, or -1 if not found.
function searchByProp(arr:Array, prop:String, value:Object): int
{
var item:Object;
var n: int = arr.length;
for(var i:int=n;i>0;i--)
{
item = arr[i-1];
if(item.hasOwnProperty(prop))
if( value == item[prop] )
return i-1;
}
return -1;
}

How to access children of children recursively?

I have a Canvas which has many components inside it and those again, have many components inside them.
getChildren() returns only the top level children. What is the best way to retrieve all the children (children of children of children and so on).
Well, I sorta know how to do this by iterating through the children, but the code is really messy. I'd prefer to use a nice recursive function. Has anyone written this before? Or is there a Util class to do this?
private function recuse(display : DisplayObjectContainer) : void {
if(display) {
for (var i : int = 0;i < _display.numChildren;i++) {
var child : DisplayObject = display.getChildAt(i);
trace(child.name);
if(child is DisplayObjectContainer) {
recuse(DisplayObjectContainer(child));
}
}
}
}
Try something likely (note you can return the lists recursively if you want to gather all the references to the top level iteration)
function inspect(object:DisplayObject):void
{
if(object is DisplayObjectContainer)
{
var casted:DisplayObjectContainer = object as DisplayObjectContainer
trace("DisplayObjectContainer ", casted.name)
for(var depth:int = 0; depth < casted.numChildren;depth++)
{
inspect(casted.getChildAt(depth))
}
}else{
trace("DisplayObject", object.name );
}
}
inspect(this)
function theCallbackFunction(obj:DisplayObject):void
{
trace(obj.name);
}
//Visit the children first.
//Deep most objects will be visited first and so on.
//stage is visited at the end.
//Uses recursion
function depthFirst(obj:DisplayObject, func:Function):void
{
if(!(obj instanceof DisplayObjectContainer))
{
func(obj);
return;
}
var p:DisplayObjectContainer = DisplayObjectContainer(obj);
var len:Number = p.numChildren;
for(var i:Number = 0; i < len; i++)
{
var child:DisplayObject = p.getChildAt(i);
depthFirst(child, func);
}
func(obj);
}
//Visit the siblings first.
//stage is visited first, then its children, then the grand children and so on
//No recursion.
function breadthFirst(obj:DisplayObject, func:Function):void
{
var q:Array = [];
q.push(obj);
var p:DisplayObjectContainer;
var i:Number, len:Number;
while(q.length != 0)
{
var child:DisplayObject = queue.shift();
func(child);
if(!(child instanceof DisplayObjectContainer))
continue;
p = DisplayObjectContainer(child);
len = p.numChildren;
for(i = 0; i < len; i++)
q.push(p.getChildAt(i));
}
}
depthFirst(this.stage, theCallbackFunction);
breadthFirst(this.stage, theCallbackFunction);

Resources