У меня проблема со следующим кодом.Кажется, он ломается во время рекурсии в функции лабиринта в NewMaze .Я запустил его через firebug и получил следующую ошибку:
parent is undefined: line 97 newmaze_generator.js
[Break On This Error] self.visited = function() {return parent.visited();};
И я понятия не имею, почему она будет неопределенной, если это даже реальная проблема.
Я знаю, что этоспрашивать много, поэтому, пожалуйста, не тратьте свое время, если вы действительно не хотите помочь начинающему программисту javascript.Чтобы упростить задачу, у меня есть весь код на моем веб-сайте, так что вы можете запустить программу, которая в настоящий момент ничего не сделает.
http://level2games.com/games/dungeons/dungeons.html
На заметке сторон этотолько мой второй опыт программирования на javascript, поэтому я мог легко совершить глупую ошибку.
Мой MazeGenerator
function NewMaze(_grid) {
var self = this;
var stack = new Array();
var grid = _grid;
/**
* A recursive depth-first-search style maze generator
*/
self.maze = function() {
var randx = Math.floor(Math.random()*(grid.getWidth()));
var randy = Math.floor(Math.random()*(grid.getHeight()));
var startOfMaze = new MyCell(grid.getCell(randx, randy));
stack.push(startOfMaze);
mazeHelper(startOfMaze);
};
/**
* Internal recursive method used by maze.
* A depth-first-search style algorithm.
* @param mycell current cell
* @returns {Boolean} true once finished
*/
function mazeHelper(myCell) {
var neighbors = myCell.getOpenNeighbors();
myCell.markVisited();
if (neighbors.length > 0) {
var next = Math.floor(Math.random()*(neighbors.length));
var nextCell = neighbors[next];
stack.push(nextCell);
removeWall(myCell, nextCell);
// alert(myCell.getParent().getArrayLocation().getX()+" , "+myCell.getParent().getArrayLocation().getY());
mazeHelper(nextCell);
} else {
alert("else");
if (stack.length == 0) return true;
else mazeHelper(stack.pop());
};
};
/**
* Removes the wall between the given cells
* @param fromCell
* @param toCell
*/
function removeWall(fromCell, toCell) {
var xDif = toCell.getParent().getArrayLocation().getX() - fromCell.getParent().getArrayLocation().getX();
var yDif = toCell.getParent().getArrayLocation().getY() - fromCell.getParent().getArrayLocation().getY();
if (xDif == -1) toCell.seWall = false; // if moving up x axis
if (xDif == 1) fromCell.seWall = false; // if moving down x axis
if (yDif == -1) toCell.swWall = false; // if moving up y axis
if (yDif == 1) fromCell.swWall = false; // if moving down y axis
};
/**
* @returns an instance of 'this' named self.
*/
self.getSelf = function() {return self;};
/**
* Inner class that is an extension of Cell class
* @param cell the parent cell
* @returns {MyCell} instance of 'this' child
*/
function MyCell(cell) {
var self = this;
var parent = cell;
/**
* Marks the referenced cell as visited using the super class's visited method.
*/
self.markVisited = function() {parent.markVisited();};
self.visited = function() {return parent.visited();};
/**
* Creates and returns an array of neighbors that have not been visited.
* @returns {<MyCell>Array} an array of adjacent cells that have not been visited.
*/
self.getOpenNeighbors = function() {
var neighbors = new Array();
var tc0, tc1, tc3, tc4;
var parentX = parent.getArrayLocation().getX();
var parentY = parent.getArrayLocation().getY();
tc0 = new MyCell(grid.getCell(parentX-1, parentY));
tc1 = new MyCell(grid.getCell(parentX+1, parentY));
tc2 = new MyCell(grid.getCell(parentX, parentY-1));
tc3 = new MyCell(grid.getCell(parentX, parentY+1));
if (tc0 != undefined && !tc0.visited()) neighbors.push(tc0);
if (tc1 != undefined && !tc1.visited()) neighbors.push(tc1);
if (tc2 != undefined && !tc2.visited()) neighbors.push(tc2);
if (tc3 != undefined && !tc3.visited()) neighbors.push(tc3);
return neighbors;
};
/**
* @returns an instance of 'this' named self.
*/
self.getSelf = function() {return self;};
/**
* @returns an instance of the 'super' class named parent.
*/
self.getParent = function() {return parent;};
};
};
Мой класс лабиринта
function NewGrid(context, gwidth, gheight) {
var self = this; // stores and instance of 'this'
var ctx = context; // local pointer to the context;
var width = 12; // 12 is the default number of cells wide
var height = 12; // 12 is the default number of cells high
// Public Variables - needed by NewCell class, umm... please don't overwrite
NewGrid.FLOOR_COLOR = "#CABCAF"; // default base color - brown
NewGrid.WALL_COLOR = "#333333"; // default wall color - dark grey
NewGrid.CELL_WIDTH = FINAL_CELL_WIDTH; // 200px is the default width
NewGrid.CELL_HEIGHT = FINAL_CELL_HEIGHT; // 100px is the default height
var cells = new Array(); // 2d array of cells, fully instantiated in constructHelper
contructHelper(gwidth, gheight);
/**
* Internal helper method (pseudo-constructor)
*/
function contructHelper(gwidth, gheight) {
if (gwidth != undefined && gheight != undefined) {
width = gwidth;
height = gheight;
};
// Constructs the 2d array of cells i.e. cells[y] = x[]
cells = new Array(height);
for (var i = 0; i < cells.length; i++) {
cells[i] = new Array(height);
};
gridBuilder();
};
function gridBuilder() {
var offSet = width * NewGrid.CELL_WIDTH / 2;
for (var i = 0; i < cells.length; i++) {
for (var j = cells[i].length - 1; j >= 0; j--) {
var x = (j * NewGrid.CELL_WIDTH / 2) - (i * NewGrid.CELL_WIDTH / 2) + offSet;
var y = (i * NewGrid.CELL_HEIGHT / 2) + (j * NewGrid.CELL_HEIGHT / 2);
cells[i][j] = new NewCell(ctx, new Point(x,y), new Point(i,j));
};
};
};
/**
* @returns the width of the grid
*/
self.getWidth = function() {return width;};
/**
* @returns the height of the grid
*/
self.getHeight = function() {return height;};
/**
* draws the grid to the screen
* @param useViewport true if drawing only a portion
*/
self.drawMe = function(useViewport) {
if (!useViewport) {
// draws the full grid to the canvas
for (var i = 0; i < cells.length; i++) {
for (var j = cells[i].length - 1; j >= 0; j--) {
cells[i][j].drawMe();
};
};
for (var i = 0; i < cells.length; i++) {
for (var j = cells[i].length - 1; j >= 0; j--) {
cells[i][j].drawWalls();
};
};
} else {
// draws only the viewable portion of the grid to the canvas.
// not implemented yet
}
};
self.getCell = function(x,y) {
if (x >= 0 && x < width) {
if (y >= 0 && y < height) {
return cells[x][y].getSelf();
};
};
return undefined;
};
/**
* @returns an instance of 'this' named self.
*/
self.getSelf = function() {return self;};
/**
* Internal class for the viewable portion of the grid
* @param vpwidth (optional) number of cells to be displayed horizontally
* @param vpheight (optional) number of cells to be displayed vertically
*/
function ViewPort(vpwidth, vpheight) {
var self = this;
var width = 4; // 4 is the default number of cells wide
var height = 3; // 3 is the default number of cells high
constructHelper(vpwidth, vpheight);
/**
* Internal helper method (pseudo-constructor)
*/
function contructHelper(vpwidth, vpheight) {
if (vpwidth != undefined && vpheight != undefined) {
width = vpwidth;
height = vpheight;
};
};
/**
* @returns the width of the view port
*/
self.getWidth = function() {return width;};
/**
* @returns the height of the view port
*/
self.getHeight = function() {return height;};
/**
* @returns an instance of 'this' named self.
*/
self.getSelf = function() {return self;};
};
};
My Cell Class
/**
* @param context the context on which to be drawn.
* @param ccorners an array of points representing the 4 corners
* @param cwidth (optional) the number of pixels wide the cell is.
* @param cheight (optional) the number of pixels high the cell is.
*/
function NewCell(context, origin, arrLoc) {
var self = this; // stores and instance of 'this'
var ctx = context; // local pointer to the context;
var corners = new Array(); // an array of points representing the corners in n-e-s-w order
var arrayLoc = arrLoc; // position in the cells array
var wallHeight = 5; // pixels used to draw the wall
self.swWall = true; //determines is a wall is present to the south-west
self.seWall = true; //determines is a wall is present to the south-east
var visited = false; // used by maze generator
contructHelper(origin);
/**
* Internal helper method (pseudo-constructor)
* @param origin is a Point representing the x,y value of the top corner
*/
function contructHelper(origin) {
corners[0] = new Point(origin.getX(), origin.getY()); // 0,0
corners[1] = new Point(origin.getX() + NewGrid.CELL_WIDTH / 2, origin.getY() + NewGrid.CELL_HEIGHT / 2); // 0+100,0+50
corners[2] = new Point(origin.getX(), origin.getY() + NewGrid.CELL_HEIGHT); // 0, 0+100
corners[3] = new Point(origin.getX() - NewGrid.CELL_WIDTH / 2, origin.getY() + NewGrid.CELL_HEIGHT / 2); // 0-100, 0+50
};
/**
* @returns the x,y value of the top corner as a Point
*/
self.getOrigin = function() {return corners[0];};
self.getArrayLocation = function() {return arrayLoc;};
/**
* @returns the x,y value of the center of the cell as a Point
*/
self.getCenter = function() {return new Point(corners[0].getX(), corners[0].getY() + NewGrid.CELL_HEIGHT / 2);};
/**
* draws the cell to the canvas using an array of points
* to from the corners and using (for temporary purposes)
* a floor color and wall color and wall height.
*/
self.drawMe = function() {
ctx.lineWidth = wallHeight;
ctx.fillStyle = NewGrid.FLOOR_COLOR;
ctx.beginPath();
ctx.moveTo(corners[0].getX(),corners[0].getY());
ctx.lineTo(corners[1].getX(),corners[1].getY());
ctx.lineTo(corners[2].getX(),corners[2].getY());
ctx.lineTo(corners[3].getX(),corners[3].getY());
ctx.closePath();
ctx.fill();
};
self.drawWalls = function() {
ctx.strokeStyle = NewGrid.WALL_COLOR;
if (seWall) {
ctx.beginPath();
ctx.moveTo(corners[2].getX(),corners[2].getY());
ctx.lineTo(corners[3].getX(),corners[3].getY());
ctx.closePath();
ctx.stroke();
};
if (swWall) {
ctx.beginPath();
ctx.moveTo(corners[3].getX(),corners[3].getY());
ctx.lineTo(corners[0].getX(),corners[0].getY());
ctx.closePath();
ctx.stroke();
};
};
self.visited = function() {return visited;};
self.markVisited = function() {visited = true;};
/**
* @returns gets the array of the 4 neighboring cells
*/
self.getNeighbors = function() {
return neighbors;
};
/**
* @returns an instance of 'this' named self.
*/
self.getSelf = function() {return self;};
};