我遇到以下代码的问题。在 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;};
};
};
我的细胞分类
/**
* @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;};
};
答案 0 :(得分:0)
好的,我明白了!我是一个愚蠢的错误,无论这是不是一件好事,我不确定。
问题在于:
在 getOpenNeighbors 函数中,我正在检查单元格是否未定义,如果是,请不要将其添加到可能的邻居数组中。那么未定义的检查写得不正确。我已经定义了这样的细胞:
tc0 = new MyCell(grid.getCell(parentX-1, parentY));
如果给定位置中不存在单元格, grid.getCell(x,y)方法将返回undefined,这正是我想要它做的。
然而,在检查中我做了以确保它没有添加到我写的数组中:
if (tc0 != undefined && !tc0.visited()) neighbors.push(tc0);
很明显 tc0 或我以这种方式创建的任何tc0-x对象都不会被定义。我需要做的是检查我作为参数传递它的对象是否未定义。好吧,我把这个对象当作父类或超级类,所以我所要做的就是使用我的方法 getParent(),一切都会变成hunky-doory。
if (tc0.getParent() != undefined && !tc0.visited()) neighbors.push(tc0);
现在一切正常!不幸的是,迷宫看起来并不像它应该的那样,所以我在拍摄时遇到了一些麻烦,但至少我现在可以前进了。