[英]How can I make this function recursive/run until the requirements are not met?
As of now, I can only hardcode the same snippet after every if statement, which only needs to have the argument that getAdjacentCells(id) takes changed.到目前为止,我只能在每个 if 语句之后硬编码相同的代码段,只需要更改 getAdjacentCells(id) 需要的参数。 I haven't been able to find a way to repeat this part.
我一直无法找到重复这部分的方法。 I think this can be done recursively, but I don't know how to do it.
我认为这可以递归完成,但我不知道该怎么做。
Edit: I initially typed that isCellEmpty got an array of objects: [{topLeft: null}, {topCenter: "cell-1-2"}, {topRight: "cell-1-3"}, {middleLeft: null}, {middleRight: "cell-2-3"}], when in reality it is a single object: {topLeft: null, topCenter: "cell-1-2", topRight: "cell-1-3", middleLeft: null, middleRight: "cell-2-3"}编辑:我最初输入 isCellEmpty 有一个对象数组:[{topLeft: null}, {topCenter: "cell-1-2"}, {topRight: "cell-1-3"}, {middleLeft: null}, {middleRight: "cell-2-3"}],实际上它是单个 object:{topLeft: null, topCenter: "cell-1-2", topRight: "cell-1-3", middleLeft: Z307A6278EZBDC8DFF929DFF99 , middleRight: "cell-2-3"}
// Gets an object that looks like this: {topLeft: null, topCenter: "cell-1-2", topRight: "cell-1-3", middleLeft: null, middleRight: "cell-2-3"}
function isCellEmpty(adjacentCells) {
Object.values(adjacentCells).forEach(id => {
// Checks that the ids in stored in the object values do not equal null
if (id !== null) {
board[getBoardPosition(id)].opened = true;
// getAdjacentCells() will return either an array of objects similar to the one the function takes as an argument or an integer
// if getAdjacentCells(id) returns a number, add a div to the HTML element with that id
if (typeof (getAdjacentCells(id)) === "number") {
// Removes all other divs, this prevents repetition
$("#" + id).empty();
// Appends an empty div
$("#" + id).append("<div></div>");
// HERE'S WHERE IT STARTS: If getAdjacentCells(id) returns an object, do the same as above with every id in it
} else if (typeof (getAdjacentCells(id)) === "object") {
Object.values(getAdjacentCells(id)).forEach(id2 => {
if (id2 !== null) {
board[getBoardPosition(id2)].opened = true;
if (typeof (getAdjacentCells(id2)) === "number") {
$("#" + id2).empty();
$("#" + id2).append("<div></div>");
// HERE IT REPEATS:
} else if (typeof (getAdjacentCells(id2)) === "object") {
...
}
}
})
}
}
});
}
You can make the recursive call with the value you get from getAdjacentCells
.您可以使用从
getAdjacentCells
获得的值进行递归调用。 Make sure however to call getAdjacentCells
only once for the same id
.但是请确保为相同的
id
只调用一次getAdjacentCells
。 Now it is quite inefficient as you repeat the same call.现在,当您重复相同的调用时,它的效率非常低。
See also some other suggestions in the code.另请参阅代码中的其他一些建议。
function isCellEmpty(adjacentCells) {
// I would move this check here, although not necessary if you prefer it in the loop.
if (typeof adjacentCells === "number") {
$("#" + id).empty().append("<div>"); // You can chain jQuery...
return;
}
for (let id of adjacentCells) { // Just use a for..of loop
if (id === null) continue; // keep IF-ELSE nesting flat.
let cell = board[getBoardPosition(id)];
if (cell.opened) continue; // Add this to avoid circling around
cell.opened = true;
isCellEmpty(getAdjacentCells(id)); // recursive call
}
}
You write in the comments of your code that:您在代码的注释中写道:
getAdjacentCells() will return either an array of objects similar to the one the function takes as an argument or an integer
getAdjacentCells() 将返回类似于 function 作为参数的对象数组或 integer
However, your comments below this answer seem to suggest that this is not (always) the case.但是,您在此答案下方的评论似乎表明情况并非(总是)如此。 It maybe a plain object which would explain why you used
Object.values
to iterate it.它可能是一个普通的 object 可以解释为什么你使用
Object.values
来迭代它。 If this is the case I would urge to change getAdjacentCells
so that it really does return an array.如果是这种情况,我会敦促更改
getAdjacentCells
以便它确实返回一个数组。 Or if that is not possible then use Object.values
like you already did:或者,如果这是不可能的,那么就像你已经做过的那样使用
Object.values
:
function isCellEmpty(adjacentCells) {
// I would move this check here, although not necessary if you prefer it in the loop.
if (typeof adjacentCells === "number") {
$("#" + id).empty().append("<div>"); // You can chain jQuery...
return;
}
for (let id of Object.values(adjacentCells)) { // Just use a for..of loop
if (id === null) continue; // keep IF-ELSE nesting flat.
let cell = board[getBoardPosition(id)];
if (cell.opened) continue; // Add this to avoid circling around
cell.opened = true;
isCellEmpty(getAdjacentCells(id)); // recursive call
}
}
Recursion should work just fine here: at its most basic you'd call your own method with id2
.递归在这里应该可以正常工作:在最基本的情况下,您可以使用
id2
调用您自己的方法。 However, assuming getAdjacentCells
may return cells that you've already visited, you'll end up recursing infinitely unless you're able to track which IDs you've already visited, and pass that in.但是,假设
getAdjacentCells
可能会返回您已经访问过的单元格,那么您最终会无限递归,除非您能够跟踪您已经访问过的 ID 并将其传入。
function setCellState(id, visited) {
if(id === null) {
return;
}
if(visited === undefined) {
visited = new Set();
}
if(visited.has(id)) {
return;
}
visited.add(id);
board[getBoardPosition(id)].opened = true;
// getAdjacentCells() will return either an array of objects similar to the one the function takes as an argument or an integer
let adjacentCells = getAdjacentCells(id);
// if getAdjacentCells(id) returns a number, add a div to the HTML element with that id
if (typeof (adjacentCells) === "number") {
// Removes all other divs, this prevents repetition
$("#" + id).empty()
// Appends an empty div
.append("<div></div>");
} else if (typeof (adjacentCells) === "object") {
Object.values(adjacentCells).forEach(id2 => setCellState(id2, visited));
}
I took the liberty of changing the method name to be more representative of what the method actually does.我冒昧地更改了方法名称以更能代表该方法的实际作用。 I also changed it to start with a single cell's ID, since that simplifies the recursion and that allows the comment around the behavior of
getAdjacentCells
to provide better context.我还将它更改为从单个单元格的 ID 开始,因为这简化了递归,并且允许围绕
getAdjacentCells
行为的注释提供更好的上下文。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.