Решение проблемы Лабиринт с Backtrack

0

У меня есть проект, который получает лабиринт через txt файл, и я должен его решить. Единственными трудными спецификациями для его решения являются: Никакой другой двумерный массив (No Copy, No Bool).

Поэтому я использую стеки и backtracking, чтобы решить эту проблему. Я использую два стека, один для копирования посещенных комнат, а другой - для копирования пути. Но дело в том, что когда я вернусь к основной функции, два стека только получили последнюю позицию, которую они получили в лабиринте. Так что моя проблема, просто последняя позиция в моих стопках.

Когда я нахожусь в функции Backtracking Function, есть еще одна функция, которая проверяет, был ли я раньше в этой позиции, я тестирую стек, о котором я упоминал ранее, и работает отлично (стек, который сохраняет посещаемые комнаты), я напечатал все значения этого стека,

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

bool path(ColaD* colaDG, Node* temp, PileD* pileDG)
{
    if (temp->row == colaDG->end->row && temp->col == colaDG->end->col)
        return true;
    if (check(pileDG, temp) || mat[temp->row][temp->col] == 1)
    {
        // call check function
        return false;
    }
    pileDG->push(*temp);
    if (temp->row != 0)
    {
        temp->row -= 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->row += 1;
    }
    if (temp->row != n - 1)
    {
        temp->row += 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->row -= 1;
    }
    if (temp->col != 0)
    {
        temp->col -= 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->col += 1;
    }
    if (temp->col != m - 1)
    {
        temp->col += 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->col -= 1;
    }
    return false;
}
bool check(PileD* pileDG, Node* temp)
{
    // Function to check visited rooms
    bool flag = false;
    Node * recor;
    recor = new Node();
    recor = pileDG->top;
    while (recor != NULL)
    {
        if (recor->row == temp->row && recor->col == temp->col)
        {
            // if already here, return true
            flag = true;
            break;
        }
        else
            recor = recor->pre;
    }
    return flag;
}

Я знаю, но я не знаю, как это сделать.

Я думаю об использовании графика для его решения, но я не знаю, как реализовать график вообще. Извините за мой английский, я не являюсь носителем английского языка. Я попытался изменить некоторые слова на код, потому что некоторые слова были на испанском языке. Любая помощь будет большой. И извините за весь код в файле.cpp, я просто тестирую, настоящий проект будет другим.

Полный код:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

int n=0,m=0;
int **mat;

class Node{
public:
        Node(){pre=NULL;}
        int row;
        int col;
        Node *pre;
};

class ColaD{
   public:
        ColaD(){fin=fte=end=NULL;}
        void push(Nodo xdato);
        void pop();
        Node *fte,*fin,*end;
};
void ColaD::push(Node xdato){
     Node *nuevo;
     nuevo = new Node();
     if(nuevo){
          (*nuevo)= xdato;
          nuevo->pre = NULL;
          if(!fte)
             fte = nuevo;
          else
             fin->pre=nuevo;
          fin = nuevo;
     }
}
void ColaD::pop(){
     Node *elim; 
     if(fte){
        elim = fte;
        if(fte==fin)
           fte = fin = NULL;
        else
            fte = fte->pre;
        delete(elim);
     }
}
class PileD{
   public:
        PileD(){tope=NULL;}
        void push(Node xdato);
        void pop();
        Node *tope;
};
void PilaD::push(Node xdato){
        Node *nuevo;
        nuevo = new Node;
        if(nuevo){
          (*nuevo)=xdato;
          nuevo->pre=tope;
          tope=nuevo;
        }
}
void PileD::pop(){
        Node *aux;
        if(tope){
          aux=tope;
          tope=tope->pre;
          free(aux);    
        }
}

void tamMat(); //read the size of the maze given by a txt file
void loadM(); //once i know the size, and the bi dimensional is created I set the values to de bi dimensional A.
void printM(); //Just check the values
bool path(ColaD *colaDG,Node *temp,PileD *pileDG); 
bool check(PileD *pileDG,Node *temp);


int main(int argc, char const *argv[])
{
        ColaD *colaDG;
        Node *inicio;
        PileD *pileDG;
        tamMat();  //Read the size
        mat = new int*[n];
        for(int i=0;i<n;i++)
         mat[i]=new int[m];

    loadM(); //Set values given from the file
    colaDG = new ColaD();
    pileDG = new PileD();
    inicio = new Node();
    inicio->row=0;  //Proyect says, the start of the maze is in the first row of the maze
    for(int j=0;j<m;j++)
        if(mat[0][j]!=1){
                inicio->col=j; //Found the position in the row
                break;
            }
    colaDG->end = new Nodo();
    colaDG->end->row=n-1; //End position is in the last row
    for(int j=0;j<m;j++)
        if(mat[n-1][j]!=1){
                colaDG->end->col=j; //Found the position
                break;
            }
        bool b = path(colaDG,inicio,pilaDG); //call my backtrack function
        getchar();
        /* CODE TO CHECK visited Rooms
        Nodo *temp = new Nodo();
        temp=pileDG->tope;
        while(temp!=NULL){
            cout << temp->row <<" "<<temp->col << endl;
            getchar();
            temp->pre;                         
        }
        */
        getchar();

        return 0;
}

void tamMat(){ 
        fstream inFile;
        int num;
        n=m=0;
        inFile.open("mat.txt",ios::in);
        string line;

        getline(inFile,line);
        stringstream temp(line);
        while(temp>> num)
                m++;
        n++;
        while(getline(inFile,line))
                n++;
        inFile.close();
}
void loadM(){
        fstream inFile;
        inFile.open("mat.txt",ios::in);
        for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                        inFile >> mat[i][j];
        inFile.close();
}

void printM(){
        for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
           if(mat[i][j]!=1)
                         cout << " ";
           else
             cout << mat[i][j];
           cout << " ";
        }
                cout << endl;
        }
}
bool path(ColaD *colaDG,Node *temp,PileD *pileDG){

    if(temp->row==colaDG->end->row && temp->col==colaDG->end->col) return true;
    if(check(pileDG,temp) || mat[temp->row][temp->col]==1){
          return false;      
    }
    pileDG->insertar(*temp);
    if(temp->row!=0){
         temp->row-=1;
         colaDG->insertar(*temp);            
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->row+=1;
    }
    if(temp->row!=n-1){
         temp->row+=1;
         colaDG->insertar(*temp);
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->row-=1;          
    }
    if(temp->col!=0){
         temp->col-=1;
         colaDG->insertar(*temp);
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->col+=1;    
    }
    if(temp->col!=m-1){     
         temp->col+=1;
         colaDG->insertar(*temp);
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->col-=1;       
    }
    return false;
}
bool check(PileD *pileDG,Node *temp){
     bool flag=false;
     Node *recor;
     recor = new Node();
     recor = pileDG->tope;
     while(recor!=NULL){
          if(recor->row==temp->row && recor->col==temp->col){
              flag=true;
              break;
          }
          else
              recor=recor->pre;
     }
     return flag;
}

Файл Maze mat.txt.

0 0 0 1 1 1 1 1 1 1
1 1 0 1 0 5 1 1 0 1
1 1 6 1 7 1 1 1 0 1
1 1 0 1 0 1 0 0 0 1
1 0 9 0 0 1 0 1 0 1
1 8 1 1 0 1 6 1 0 1
1 0 1 1 0 1 0 1 5 1
1 0 1 1 0 1 0 1 0 1
1 0 0 1 0 0 0 1 7 1
1 1 1 1 1 1 1 1 0 1
1=Walls / 0=Free Space / Other numbers = Bonus
  • 0
    Похоже, что некоторые вопросы очень похожи на ваши в соответствующем столбце в правой части страницы ... вот первый ... не уверен, помогает ли это, но, видя, что пара имеет одинаковый заголовок, один связан с есть ваш ответ.
Теги:
stack
backtracking
maze

2 ответа

0
Лучший ответ

Есть много проблем с вашим кодом, некоторые из них важны, некоторые из них - проблемы с эффективностью. Основная проблема, которую я вижу сейчас, заключается не в коде анализа, а в коде диагностики.

Посмотрите на часть в комментарии:

    /* CODE TO CHECK visited Rooms */
    Nodo *temp = new Nodo();
    temp=pileDG->tope;
    while(temp!=NULL){
        cout << temp->row <<" "<<temp->col << endl;
        getchar();
        temp->pre;
    }

Последняя строка перед закрывающей скобкой

        temp->pre;

Он просто считывает поле pre из *temp объекта, но не использует это значение - temp переменная не изменяется, поэтому программа остается в цикле навсегда, снова и снова печатать одну и ту же часть данных.

Я полагаю

        temp = temp->pre;

это то, что вы имели в виду.

В любом случае такие циклы легче писать и читать, если вы используете for вместо while:

    /* CODE TO CHECK visited Rooms */
    for( Nodo *temp=pileDG->tope; temp!=NULL; temp=temp->pre){
        cout << temp->row <<" "<<temp->col << endl;
        getchar();
    }

После его замены вы, возможно, увидите (некоторые) другие проблемы с кодом. Например, вы можете найти слишком много "посещенных" позиций в напечатанном виде.

  • 0
    О боже, я не могу поверить, что это была моя ошибка, я чувствую себя таким нубом ... Я прочитал ваш прошлый ответ, просто у него не было времени, чтобы ответить. Работает сейчас, спасибо за ваше время, и я знаю, что у моего кода есть некоторые (или много) проблемы с эффективностью, я все еще новичок в этом сумасшедшем мире. Теперь я могу продолжить свой проект, еще раз спасибо, мой друг.
0

Что происходит в этой части кода?

Node * recor;
recor = new Node();
recor = pileDG->top;

Разве новый узел не потерян навсегда...?

Кажется, вы помещаете каждую новую точку в стек colaDG. Однако я не вижу, где вы удаляете точки, когда вы отскакиваете от тупиковых путей...

  • 0
    Не теряйте вечность, потому что если вы видите код рядом с ним, вы можете проверить, есть ли там, temp = temp-> pre; который является предшественником, основного узла. И если вы перейдете к функции check (), вы можете попробовать напечатать temp-> row и temp-> col; это почти тот же код. И да, мне нужно удалить это, я должен изменить тип стека на список, но в любом случае, я удалил эти коды (где я выталкиваю стек), просто чтобы проверить, выдвигают ли они позицию в стек, но все же нет толкая что-нибудь, только последнюю позицию.
  • 0
    @vitaR, позвольте мне объяснить: первая строка из трех, которые я скопировал выше, объявляет переменную с именем recor для хранения указателя на объект класса Node ; вторая строка создает новый объект Node и сохраняет указатель на этот объект в переменной recor ; третья строка считывает указатель на какой-либо другой объект Node из переменной-члена pileDG->top и сохраняет указатель на ту же самую recor переменной. Таким образом, указатель на вновь созданный объект Node перезаписывается. Поскольку он не был сохранен в каком-либо другом месте, программа больше не может получить доступ к созданному объекту Node - он потерян.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню