Rekurencyjny algorytm wyjścia z labiryntu

0

Witam szanowne grono forumowiczów,

        function go(currentPosition = -1) {
            if (!first) {
                console.log('start position: ' + playerPosition);
                currentPosition = playerPosition;
                first = true;
            }

            if (currentPosition === endPosition) {
                // end
                console.log('game over. won');
                return true;
            }

            let possibleWays = getPossibleWays(currentPosition);

            //console.log(possibleWays);

            possibleWays.forEach(element => {
                if (visited.includes(element.field)) {
                    return false;
                }

                if (element.field > 224) {
                    return false;
                }

                visited.push(element.field);

                if (go(element.field)) {
                    return true;
                }

                return false;
            });
        }

Napisałem taki rekurencyjny algorytm wyjścia z labiryntu który działa natomiast nie wiem jak wyciągnąć z tego poprawną ścieżkę, który powinienem się poruszać. Cała funkcja zwraca mi wszystkie odwiedzone pola, nawet te które prowadziły w ślepe uliczki. Czy ktoś może mi pomóc?

0

Wydaje się, że wystarczy zrobić to tak:

                if (go(element.field)) {
                    visited.push(element.field);
                    return true;
                }

Czyli dodajesz do visited tylko te ścieżki, które zwracają true.

0
        function go(currentPosition = -1) {
            if (!first) {
                console.log('start position: ' + playerPosition);
                currentPosition = playerPosition;
                first = true;
            }

            if (currentPosition === endPosition) {
                // end
                console.log('game over. won');
                return true;
            }

            let possibleWays = getPossibleWays(currentPosition);

            //console.log(possibleWays);

            possibleWays.forEach(element => {
                if (visited.includes(element.field)) {
                    return false;
                }

                if (element.field > 224) {
                    return false;
                }

                //visited.push(element.field);

                if (go(element.field)) {
                    visited.push(element.field);
                    return true;                    
                }

                return false;
            });
        }

Firefox zwraca: too much recursion. Jak dodałem logowanie po wejściu w if

        function go(currentPosition = -1) {
            if (!first) {
                console.log('start position: ' + playerPosition);
                currentPosition = playerPosition;
                first = true;
            }

            if (currentPosition === endPosition) {
                // end
                console.log('game over. won');
                return true;
            }

            let possibleWays = getPossibleWays(currentPosition);

            //console.log(possibleWays);

            possibleWays.forEach(element => {
                if (visited.includes(element.field)) {
                    return false;
                }

                if (element.field > 224) {
                    return false;
                }

                visited.push(element.field);

                if (go(element.field)) {
                    console.log('inside');
                    return true;                    
                }

                return false;
            });
        }

To console.log jest zalogowany raz na pozycji końcowej labiryntu (tam gdzie gracz staje na polu oznaczonym jako exit).

0

Prawdopodobnie tak będzie, jeśli labirynt się zapętla.
Warunek:

                if (visited.includes(element.field)) {
                    return false;
                }

komplikuje całą sprawę.
Musisz utworzyć jedną tablicę dla elementów, które przeszedłeś (niech będzie visited).
Oraz drugą z odpowiednią drogą powiedzmy(right_way).
Wtedy "visited.push(element.field);" zostawiasz na swoim miejscu, a do right_way dodajesz prawidłową ścieżkę:

                if (go(element.field)) {
                    right_way.push(element.field);
                    return true;                    
                }

Po tym w right_way powinieneś mieć prawidłową ścieżkę.

0

Niestety dalej to samo. Do tablicy correctPath dodany jest tylko jeden element po wejściu w IF. Tablica visited zawiera wszystkie odwiedzone pola zarówno te prowadzące donikąd jak i te prowadzące do wyjścia. Screen poniżej
screenshot-20200321122231.png

Kod

        function go(currentPosition = -1) {
            if (!first) {
                console.log('start position: ' + playerPosition);
                currentPosition = playerPosition;
                first = true;
            }

            if (currentPosition === endPosition) {
                // end
                console.log('game over. won');
                return true;
            }

            let possibleWays = getPossibleWays(currentPosition);

            //console.log(possibleWays);

            possibleWays.forEach(element => {
                if (visited.includes(element.field)) {
                    return false;
                }

                if (element.field > 224) {
                    return false;
                }

                visited.push(element.field);

                if (go(element.field)) {
                    correctPath.push(element.field);
                    return true;                    
                }

                return false;
            });
        }

EDIT
Zrobiłem jeszcze coś takiego, aby dodawać do tablicy incorrectPath wszystkie pola które wpadły w IFa

                if (visited.includes(element.field)) {
                    incorrectPath.push(element.field);
                    return false;
                }

I może jakoś z tego da się jakoś wyciągnąć poprawną drogę
screenshot-20200321123213.png

Kod z incorrectPath

        function go(currentPosition = -1) {
            if (!first) {
                console.log('start position: ' + playerPosition);
                currentPosition = playerPosition;
                first = true;
            }

            if (currentPosition === endPosition) {
                // end
                console.log('game over. won');
                return true;
            }

            let possibleWays = getPossibleWays(currentPosition);

            //console.log(possibleWays);

            possibleWays.forEach(element => {
                if (visited.includes(element.field)) {
                    incorrectPath.push(element.field);
                    return false;
                }

                if (element.field > 224) {
                    return false;
                }

                visited.push(element.field);

                if (go(element.field)) {
                    correctPath.push(element.field);
                    return true;                    
                }

                return false;
            });
        }
0
 function go(currentPosition = -1) {
            if (!first) {
                console.log('start position: ' + playerPosition);
                console.log('end position: ' + endPosition);
                currentPosition = playerPosition;
                first = true;
            }

            if (currentPosition === endPosition) {
                console.log('game over. won');
                return true;
            }

            let possibleWays = getPossibleWays(currentPosition);

            if (possibleWays[0] !== undefined) {
                if (!visited.includes(possibleWays[0].field)) {
                    visited.push(possibleWays[0].field);
                    if (go(possibleWays[0].field)) {
                        correctPath.push(possibleWays[0]);
                        return true;
                    }
                }
            }

            if (possibleWays[1] !== undefined) {

                if (possibleWays[1].field > 224) {
                    return false;
                }

                if (!visited.includes(possibleWays[1].field)) {
                    visited.push(possibleWays[1].field);
                    if (go(possibleWays[1].field)) {
                        correctPath.push(possibleWays[1]);
                        return true;
                    }
                }
            }

            if (possibleWays[2] !== undefined) {

                if (possibleWays[2].field > 224) {
                    return false;
                }

                if (!visited.includes(possibleWays[2].field)) {
                    visited.push(possibleWays[2].field);
                    if (go(possibleWays[2].field)) {
                        correctPath.push(possibleWays[2]);
                        return true;
                    }
                }
            }

            if (possibleWays[3] !== undefined) {

                if (possibleWays[3].field > 224) {
                    return false;
                }

                if (!visited.includes(possibleWays[3].field)) {
                    visited.push(possibleWays[3].field);
                    if (go(possibleWays[3].field)) {
                        correctPath.push(possibleWays[3]);
                        return true;
                    }
                }
            }

            return false;
        }

Rozwiązanie. Trasa jest w tablicy correctPath.

1 użytkowników online, w tym zalogowanych: 0, gości: 1