我想从矩阵的顶部到底部生成随机路径。
要求:
我考虑过的事情:
所以是的,简单的方法就是制作它并迭代它:
var matrixPaths = [
[0,1,0,0,0,0],
[0,1,1,1,0,0],
[0,0,0,1,0,0],
[0,0,0,1,1,1],
[0,0,0,0,0,1],
[0,0,0,0,0,1]
];
在左边,空格,在右边,它应该生成什么
我的想法是首先创建网格并在每个矩阵条目中添加跨度:
function createMyGrid() {
//create 6x6 matrix
for(var i=1; i<=6; i++) {
matrix[i] = [];
for(var j=1; j<=6; j++) {
var colorIndex = Math.floor(Math.random() * (color.length - 0) + 0);
var $span = $('<span />').attr('class', 'colorSquare').html("[" + i + "][" + j + "]");
$("#grid").append($span);
matrix[i][j] = $span;
}
}
}
然后,在第1行中随机生成第一个路径段。然后对于每个后续行,检查其上方的路径段以进行连接...然后从该块开始生成下一个集:
function createPath() {
var randomColumn = Math.floor(Math.random() * (matrix[1].length - 0) + 0);
matrix[1][randomColumn].data('partOfPath', true);
matrix[1][randomColumn].addClass("red");
for (var row = 2; row <= 6; row++) {
for (var col = 1; col <= 6; col++) {
if (matrix[row-1][col].data('partOfPath')) { //if block above is partOfPath... add a set of items of random # of columns across
addRowPath(row, col);
}
}
}
}
function addRowPath (row, pathCol) { //need to start offset from that row/col position,
var randRowPathLength = Math.floor(Math.random() * (matrix[row].length - 0) + 0);
for (var col = pathCol; col <= randRowPathLength; col++) {
matrix[row][col].addClass("red");
}
}
到目前为止,它添加了初始步骤,然后是下面的行,但随后停止了。
答案 0 :(得分:3)
我想指出的一点是,您应该将数组的范围更改为从零开始,或者修复生成的数字范围。目前,它正在生成一个无效指数范围。既然你的问题并没有集中在那个问题上,我就把它留下了。
这会产生一个可以向下和向后移动的绕组路径,直到它用完有效的移动或到达屏幕的底部。这是http://jsfiddle.net/j6gkzbr5/1/
的JFIDDLEvar colorEn = ["RoyalBlue", "LawnGreen", "red", "orange", "yellow", "black", "white", "MediumOrchid"];
var $color = "null";
var matrix = [];
var list = []
$(document).ready(function () {
createMyGrid();
createPath();
});
function createPath() {
var row = 1;
var randomColumn = Math.floor(Math.random() * (matrix[1].length - 0) + 0);
matrix[1][randomColumn].data('partOfPath', true);
matrix[1][randomColumn].addClass("red");
//Main loop, runs until we reach the final row.
do {
CreateNewFrontier(row, randomColumn);
//list now contains a list of all legal moves to make
var randomNumber = Math.floor((Math.random() * (list.length)));
//Select one at random
row = list[randomNumber][0];
randomColumn = list[randomNumber][1];
//And mark it
MarkPath(row, randomColumn);
} while (row < 6)//This should be matrix.length - 1
}
//This function clears out the previous list of valid moves and generates a new one.
function CreateNewFrontier(row, column) {
list = [];
//Check if each cardinal direction falls within the bounds of the matrix.
//If it does pass that node to the addtofrontier function for further consideration.
//if (row - 1 >= 1) AddToFrontier(row - 1, column);
//Commented out, as we are no longer considering paths that lead up.
if (column + 1 < matrix[row].length) AddToFrontier(row, column + 1);
if (row + 1 < matrix.length) AddToFrontier(row + 1, column);
if (column - 1 >= 1) AddToFrontier(row, column - 1);
}
//This function checks to make sure nodes to be added to the frontier don't violate any restrictions
//Mainly, per the question description, no node can touch more than 2 nodes on any cardinal direction
function AddToFrontier(row, column) {
//First we make sure this node is not already on the path. No backtracking, as it would violate the condition that there be only one continuous path.
if (matrix[row][column].data('partOfPath') != true) {
//Now we need to make sure that this node currently only has 1 neighbor at the most that
//is already on a path, otherwise we will violate the single path condition.
//So count up all marked neighbors...
var markedNeighbors = 0;
if (row - 1 >= 1 && !IsNotMarked(row - 1, column)) {
markedNeighbors++;
}
if (column + 1 < matrix[row].length && !IsNotMarked(row, column + 1)) {
markedNeighbors++;
}
if (row + 1 < matrix.length && !IsNotMarked(row + 1, column)) {
markedNeighbors++;
}
if (column - 1 >= 1 && !IsNotMarked(row, column - 1)) {
markedNeighbors++;
}
//...and if there is only 1, we add the node to the list of possible moves.
if (markedNeighbors < 2) {
var index = list.length;
list[index] = [];
list[index][0] = row;
list[index][1] = column;
}
}
}
//Helper function to mark a node as visited.
function MarkPath(row, column) {
matrix[row][column].data('partOfPath', true);
matrix[row][column].addClass("red");
}
//Helper function to check if a path is marked.
//It looks a little odd because i'm not that familiar with JS and wasn't sure how an uninitialized //variable would return, so i decided to return the opposite.
function IsNotMarked(row, column) {
if (row < 1 || row >= matrix.length) return true;
if (column < 1 || column >= matrix[row].length) return true;
return matrix[row][column].data('partOfPath') != true;
}
function createMyGrid() {
//create 6x6 matrix
for (var i = 1; i <= 6; i++) {
matrix[i] = [];
for (var j = 1; j <= 6; j++) {
var colorIndex = Math.floor(Math.random() * (colorEn.length - 0) + 0);
var $span = $('<span />').attr('class', 'colorSquare').html("[" + i + "][" + j + "]");
$("#grid").append($span);
matrix[i][j] = $span;
}
}
}
function log(word) {
console.log(word);
}
答案 1 :(得分:1)
以下是我如何解决这个问题。
1)准确定义构成有效路径的规则。即将矩阵映射到布尔值的函数。从你的问题我不清楚什么是有效的路径,我也不清楚你还没有。
2)重复生成瓦片的随机排列,直到生成的排列符合有效路径的规则。在当前的处理器上,这将快速工作6x6,但在更大的方块上需要更长时间,例如100×100。
算法解决方案可能是可能的,节省了处理时间,但这在开发时间和代码简单性方面是快速的胜利。还有一个优势,即为您提供统一分布,即每个路径都可能与任何其他路径一样产生。
示例规则集可能是:
如果,路径有效且仅当矩阵满足所有这些条件时才有效:
1)矩阵中的每个图块(两个结束图块除外)必须是四个可能方向中的两个图块的邻居N,S,E,W
2)矩阵中的两个图块(结束图块)必须是四个可能方向N,S,E,W中恰好一个图块的邻居
3)一端瓷砖必须位于顶行,另一端位于底行
答案 2 :(得分:1)
我会使用一种方法生成一个迷宫,这个方法可以提供一个迷宫,从每个点都可以到达彼此。递归回溯器就足够了,易于实现。
在矩阵上生成迷宫后,您必须找到从起点到终点的方法(可以是每个点。您只需要记住,每一个都可以是一个墙)。您可以在帖子底部的链接中找到许多不同的算法。使用递归回溯器生成的迷宫,保证您可以根据需要连接行/列(就像我说的,每个点都相互连接),但不是每个位置都可以是路径(由于需要放置墙)
您从头到尾找到的路径符合您的要求,因此您只需删除不属于该路径的所有内容。
如果您创建自己的堆栈,则可以轻松处理大小约为2Kx2K的矩阵。也许更大。
如需进一步阅读与迷宫相关的所有内容,我推荐此网站 http://www.astrolog.org/labyrnth/algrithm.htm
您可以对迷宫生成器进行一些更改,这样就可以在任何可能的平铺上开始/结束,而不仅仅是每一秒。我能想到的最简单的解决方案就是在50%的情况下生成迷宫,偏移量为1。
答案 3 :(得分:0)
如果您一次只走一步,并且上升被排除在外,在我看来,您需要跟踪的是最后两个动作(除了确定第一步时)。然后算法可以遵循一组规则,从可用选项中随机选择下一个图块。
例如:
If the last two movements were West then South,
East would not be available.
If the last two movements were East then East,
Southeast would not be available.
And so on.
答案 4 :(得分:-2)
此处jsfiddle
制作任何大小的行和列
function yolYap(satir,sutun=0){ //My Create Path Function
if(ilk){ //İlk seçim: First selection
ilk=false;
sutun = Math.floor((Math.random()*6)+1);
matrix[satir][sutun].data('p', true);
matrix[satir][sutun].addClass("red");
yolYap(satir,sutun);
}else{
var xy=[];
var solust=satir>1&&sutun>1?!matrix[satir-1][sutun-1].data("p"):true
var sol=sutun>1?!matrix[satir][sutun-1].data("p"):false
if(sol && solust)//{
xy.push([satir,sutun-1]);//alert("<-");}
var sagust=satir>1&&sutun<matrix[1].length-1?!matrix[satir-1][sutun+1].data("p"):true;
var sag=sutun<matrix[1].length-1?!matrix[satir][sutun+1].data("p"):false;
if(sag && sagust)//{
xy.push([satir,sutun+1]);//alert("->");}
//satir>-1?alert("büyük"):alert("küçük");
xy.push([satir+1,sutun]);
var sec = Math.floor((Math.random()*102)+1)%xy.length;
matrix[xy[sec][0]][xy[sec][1]].data("p", true);
matrix[xy[sec][0]][xy[sec][1]].addClass("red");
//alert(xy.join(" - "));
if(xy[sec][0]<matrix.length-1)
yolYap(xy[sec][0],xy[sec][1]);
else
alert("Finish");
}
}