js L oop Рекурсия - PullRequest
       2

js L oop Рекурсия

1 голос
/ 27 апреля 2020

Я создаю игру тральщика и, желая показать кнопки вокруг пустой кнопки, я попал в проблему. У меня есть следующая функция:

function l_click(event, coordinate_i = event.target.i, coordinate_j = event.target.j)
{
    if(block[coordinate_i][coordinate_j].isBomb === true)
    {
        // lots of irrelevant cocde
    }
    else {
        block[coordinate_i][coordinate_j].src = "blank.png";
        for (var i = coordinate_i - 1; i < coordinate_i + 2; i++) {
            for (var j = coordinate_j - 1; j < coordinate_j + 2; j++) {
                if (coordinate_i < 9 && coordinate_j < 9 && !(block[i][j].isBomb) && !(coordinate_i === i && coordinate_j === j) && block[i][j].src ==="empty-block.png") {
                    if (block[i][j].nearBombsNum === 0) {
                        l_click(event, i, j)
                    }
                    else {
                        block[i][j].src = block[i][j].nearBombsNum + ".png";
                    }
                }
            }
        }
    }
}

То, что я пытаюсь сделать здесь, это превратить изображения в пустые с помощью кнопок доски. В результате я получу sh рекурсию, в которой функция вызывается 8 раз из вложенной функции отца l oop (вызов для каждой кнопки вокруг исходной кнопки, который будет работать так же, как и оригинал, и вызывать кнопки вокруг себя). В результате я получаю, что первый вызов останавливает или продолжает рекурсию, но после первого произведенного вызова l oop не будет работать.

Я хочу, чтобы вызов функции отца продолжал l oop запустить и продолжать вызывать себя, продолжая итерацию l oop.

Текущая ситуация такова, что как только кнопка «попадает» в первый оператор «if», l oop от отца функция не продолжается.

Ответы [ 4 ]

3 голосов
/ 27 апреля 2020

Вам действительно не нужно передавать event в вашей рекурсивной функции, и вам не нужно устанавливать значение параметра по умолчанию для вашей функции. Используйте ваш обработчик событий и передайте значения event.target функции l_click

Вместо вложенного l oop, вы можете создать массив направлений dirs и использовать его для итерации 8 соседей в 8 направление в одном l oop.

Проверьте соседние координаты, чтобы увидеть, находится ли оно в пределах границ . В своем коде вы не проверяете границы. Предположим, вы начинаете с координат [1,1], каждый раз, когда вы вызываете свою функцию, ваш i начинается с coordinate_i - 1, coordinate_j -1, после 1 стека вызовов координаты переходят в [0,0], если ячейка пуста, функция вызывается снова, и затем он начинается с [-1,-1], что нарушает ваш код, потому что block[-1] - это undefined.

Для демонстрации он не будет проверять nearBombsNum, он будет продолжать проверять пустые ячейки и отмечать их как посещенные клетки.

const dirs = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]]

function l_click(coordinate_i, coordinate_j)
{
    if(block[coordinate_i][coordinate_j].isBomb)
    {
        // lots of irrelevant cocde
    }
    else {
        block[coordinate_i][coordinate_j].src = "blank.png";
        //iterate 8 neibors
        for(const [x,y] of dirs){
          //i1,j1 are neibor coordinates
          const i1 = coordinate_i + x, j1 = coordinate_j + y;
          
          //check i1,j1 boundary, proceeds only if cell is not a bomb and empty
          if(i1>=0&&i1<block.length&&j1>=0&&j1<block[i1].length&&!block[i1][j1].isBomb&&block[i1][j1].src === 'empty-block.png'){
            if(block[i1][j1].nearBombsNum === 0)
              l_click(i1, j1)
            else
              block[i1][j1].src = block[i1][j1].nearBombsNum + ".png";
          }
        }
    }
}

//1 is bomb, 2 is visited or clicked cell, 0 is empty
function l_clickDemo(coordinate_i, coordinate_j)
{
    if(demo[coordinate_i][coordinate_j] === 1)
    {
        // lots of irrelevant cocde
    }
    else {
        demo[coordinate_i][coordinate_j] = 2;
        //iterate 8 neibors
        for(const [x,y] of dirs){
          //i1,j1 are neibor coordinates
          const i1 = coordinate_i + x, j1 = coordinate_j + y;
          
          //check i1,j1 boundary, proceeds only if cell is not a bomb and empty
          if(i1>=0&&i1<demo.length&&j1>=0&&j1<demo[i1].length&&demo[i1][j1]!==1&&demo[i1][j1] === 0){
              l_clickDemo(i1, j1)
          }
        }
    }
}

const demo = [[0,1,0,0,0],[0,0,0,1,0],[0,0,1,0,0],[0,0,0,0,0],[0,0,0,0,1]]


l_clickDemo(0,0)

console.log(demo)
0 голосов
/ 27 апреля 2020

Попробуйте заменить:

if (block[i][j].isBomb === false && (coordinate_i === i && coordinate_j === j) != true) {
    l_click(event, i, j)
}

На:

if (!block[i][j].isBomb && !(coordinate_i === i && coordinate_j === j) && block[i][j].src !== "blank.png") {
    l_click(event, i, j)
}
0 голосов
/ 27 апреля 2020

Если вы хотите, чтобы это выполнялось только 8 раз, вы не должны делать это рекурсивным. Для каждой соседней кнопки она будет действовать точно так же, как и для исходной кнопки. Таким образом, вы нажимаете кнопку, и она собирается нажать все кнопки вокруг нее. И для каждого из них, если это не бомба, она нажмет все кнопки вокруг них, включая оригинальную. Таким образом, здесь существует риск бесконечной рекурсии.

Кроме того, она будет рекурсивно углубляться. Таким образом, после обработки кнопки, которую вы нажали, она будет нажимать кнопку слева вверху от нее, кнопку слева вверху от нее, вверху слева от нее и т. Д. c, до тех пор, пока вы не встретите бомба или вы наткнулись на ту, которая не определена в вашем block.

Это ваше намерение? Если нет, может быть, рекурсия - это не то, что вы ищете здесь. Если это так, сначала проверьте, существует ли block[i][j] и уже block[i][j].src "blank.png".

0 голосов
/ 27 апреля 2020

Представьте себе тральочную доску с двумя ячейками, где нет ни одной шахты. Предполагая, что у вас есть код для обработки, выходящий за границы (которого я не вижу здесь), этот код будет повторяться. Нажатие на одну ячейку вызовет l_click на другой. Который будет вызывать l_click на первом, и т. Д. c.

Вы не исключаете клетки, которые уже были проверены в вашем рекурсивном процессе. Вам нужно найти способ сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...