Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/438.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使此函数递归/运行,直到不满足要求为止?_Javascript_Recursion - Fatal编程技术网

Javascript 如何使此函数递归/运行,直到不满足要求为止?

Javascript 如何使此函数递归/运行,直到不满足要求为止?,javascript,recursion,Javascript,Recursion,到目前为止,我只能在每个if语句之后硬编码相同的代码段,这只需要更改getAdjacentCells(id)的参数。我没办法重复这一部分。我认为这可以递归地完成,但我不知道怎么做 编辑:我最初键入isCellEmpty得到一个对象数组:[{topLeft:null},{topCenter:“cell-1-2”},{topRight:“cell-1-3”},{Middleft:null},{middleRight:“cell-2-3”},而实际上它是一个单独的对象:{topLeft:null,to

到目前为止,我只能在每个if语句之后硬编码相同的代码段,这只需要更改getAdjacentCells(id)的参数。我没办法重复这一部分。我认为这可以递归地完成,但我不知道怎么做

编辑:我最初键入isCellEmpty得到一个对象数组:[{topLeft:null},{topCenter:“cell-1-2”},{topRight:“cell-1-3”},{Middleft:null},{middleRight:“cell-2-3”},而实际上它是一个单独的对象:{topLeft:null,topCenter:“cell-1-2”,topRight:“cell-1-3”,Middleft:null,middleRight:“cell-2-3”}

//获取一个如下所示的对象:{topLeft:null,topCenter:“cell-1-2”,topRight:“cell-1-3”,Middleft:null,middleRight:“cell-2-3”}
函数为空(邻接单元){
Object.values(邻接单元格).forEach(id=>{
//检查存储在对象值中的ID是否不等于null
如果(id!==null){
板[getBoardPosition(id)]。打开=真;
//getAdjacentCells()将返回类似于函数作为参数的对象数组或整数数组
//如果getAdjacentCells(id)返回一个数字,则使用该id向HTML元素添加一个div
if(typeof(getAdjacentCells(id))=“number”){
//删除所有其他div,以防止重复
$(“#”+id).empty();
//附加一个空div
$(“#”+id);
//从这里开始:如果getAdjacentCells(id)返回一个对象,则对其中的每个id执行与上面相同的操作
}else if(typeof(getAdjacentCells(id))=“object”){
Object.values(getAdjacentCells(id)).forEach(id2=>{
如果(id2!==null){
板[getBoardPosition(id2)]。打开=真;
if(typeof(getAdjacentCells(id2))=“number”){
$(“#”+id2).empty();
$(“#”+id2);
//这里重复:
}else if(typeof(getAdjacentCells(id2))=“对象”){
... 
}
}
})
}
}
});
}

您可以使用从
getAdjacentCells
获得的值进行递归调用。但是,请确保对同一
id
只调用一次
getAdjacentCells
。现在重复同一个电话效率很低

另请参见代码中的一些其他建议

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
    }
}

递归在这里应该工作得很好:最基本的方法是使用
id2
调用自己的方法。但是,假设
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));
  }
函数setCellState(id,已访问){
如果(id==null){
返回;
}
如果(已访问===未定义){
已访问=新集合();
}
如果(访问过。有(id)){
返回;
}
已访问。添加(id);
板[getBoardPosition(id)]。打开=真;
//getAdjacentCells()将返回类似于函数作为参数的对象数组或整数数组
设adjacentCells=getAdjacentCells(id);
//如果getAdjacentCells(id)返回一个数字,则使用该id向HTML元素添加一个div
if(类型(相邻单元格)=“数量”){
//删除所有其他div,以防止重复
$(“#”+id).empty()
//附加一个空div
.附加(“”);
}else if(typeof(邻接单元格)=“对象”){
forEach(id2=>setCellState(id2,已访问));
}

我随意更改了方法名称,使其更能代表方法的实际功能。我还将其更改为从单个单元格的ID开始,因为这简化了递归,并允许围绕
getAdjacentCells
的行为进行注释,以提供更好的上下文。

函数名称似乎暗示它应该返回一个布尔值,但你没有真正返回任何东西?这是故意的吗?不,它唯一做的事情是将板中id的“opened”键设置为true,添加一个div并重复。感谢帮助,但当我尝试它时,我在编辑器(VSCode)和控制台上都出现语法错误。这是导致它的部分:else if(typeof)(邻接单元格))==“对象”)我刚才有太多的右括号。如果(typeof(邻接单元格)==“对象”),请将其更改为
。谢谢,但我得到了“邻接单元格不适用”当我尝试时。但是您在代码注释中写道getAdjacentCells返回一个数组或整数。那么这是其他问题吗?为了避免此类问题,提供可以运行的代码会很有帮助,因此包括该函数的定义。请参阅我的答案的补充,并解释为什么会发生这种情况。嘿,谢谢您的时间。我实际上,在键入代码时犯了一个错误,我认为getAdjacentCells()的“object”数据类型返回的是一个包含单个键的对象数组,而实际上它是一个包含多个键的单个对象。不过,您猜对了,使用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
    }
}
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));
  }