buscaminas en c++ [Solucionado]

Hola, estoy haciendo el programita del buscaminas para C++, compila y funciona bién, pero al terminar, al salir del método main me da error de segmentación, por lo que sé debe ser un error al liberar la memoria, no se me ocurre otra. Pero sigo sin entenderlo, a ver si alguien me puede explicar qué ocurre (El programa está pensado para ejecutar bajo consola win32, desarrollado con el editor CodeBlocks):

#include <iostream>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <cstdlib>
#include <unistd.h>
#include <ctype.h>

using namespace std;

struct Tshell{
       int x;
       int y;
       int n; //nomber of bombs for the neighbors
       bool bomb;
       bool display;
       bool mark;
};

struct Ttable{
       int n_bombs;
       int hight;
       int width;
       struct Tshell** v;
       int bombsDisc;
};

void DrawnTable(struct Ttable table)
{
    int k;
    system("cls");

    cout<<"    ";
     for(k=0;k<table.width;k++)
        cout<<k+1<<" ";
     cout<<endl<<"   ";
     for (k=0;k<table.width*2-1;k++)
         cout<<"-";
     cout<<endl;

     for(int i=0;i<table.hight; i++)
     {
            if(i<9)
                cout<<" ";
             cout<<i+1<<" |";
             for(int j=0; j<table.width; j++){
                     if(table.v[j][i].display==true)
                        cout<<table.v[j][i].n;
                     else{
                        if(table.v[j][i].mark==true)
                            cout<<"M";
                        else
                            cout<<" ";
                     }
                     cout<<"|";
             }
             cout<<endl;
    }
     cout<<"   ";
     for (int k=0;k<table.width*2-1;k++)
         cout<<"-";

     cout<<endl;
     int n=table.n_bombs-table.bombsDisc;
     cout<<"Bombs remaining: "<<n<<endl;
}

void Mark(struct Ttable &table, char* in)
{
     int x,y;
     table.bombsDisc++;
     char * inn=&in[1];
     char *aux;
     aux=strtok(inn,"-");
     x = atoi(aux);
     aux=strtok(NULL,"-");
     y = atoi(aux);
     //cout<<x<<" "<<y<<in<<endl;
     if(table.v[x-1][y-1].mark==false)
        table.v[x-1][y-1].mark=true;
     else{
        table.v[x-1][y-1].mark=false;
        table.bombsDisc--;
     }
}

void Explote(struct Ttable table,int x, int y)
{
    //set the self shell to display
    table.v[x][y].display=true;

    //Exploting left side
    if(x>0)
    {
        if(table.v[x-1][y].n==0 && table.v[x-1][y].display==false)
            Explote(table, x-1, y);
        else
            table.v[x-1][y].display=true;

    }
    //Exploting right side
    if(x<table.width-1)
    {
        if(table.v[x+1][y].n==0 && table.v[x+1][y].display==false)
            Explote(table, x+1, y);
        else
            table.v[x+1][y].display=true;

    }
       //Exploting up side
    if(y>0)
    {
        if(table.v[x][y-1].n==0 && table.v[x][y-1].display==false)
            Explote(table, x, y-1);
        else
            table.v[x][y-1].display=true;

    }
    //Exploting down side
    if(y<table.hight-1)
    {
        if(table.v[x][y+1].n==0 && table.v[x][y+1].display==false)
            Explote(table, x, y+1);
        else
            table.v[x][y+1].display=true;
    }
       //Exploting left-up side
    if(x>0 && y>0)
    {
        if(table.v[x-1][y-1].n==0 && table.v[x-1][y-1].display==false)
            Explote(table, x-1, y-1);
        else
            table.v[x-1][y-1].display=true;

    }
       //Exploting right-up side
    if(x<table.width-1 && y>0)
    {
        if(table.v[x+1][y-1].n==0 && table.v[x+1][y-1].display==false)
            Explote(table, x+1, y-1);
        else
            table.v[x+1][y-1].display=true;
    }
       //Exploting right-down side
    if(x<table.width-1 && y<table.hight-1)
    {
        if(table.v[x+1][y+1].n==0 && table.v[x+1][y+1].display==false)
            Explote(table, x+1, y+1);
        else
            table.v[x+1][y+1].display=true;
    }
       //Exploting left-down side
    if(x>0 && y<table.hight-1)
    {
        if(table.v[x-1][y+1].n==0 && table.v[x-1][y+1].display==false)
            Explote(table, x-1, y+1);
        else
            table.v[x-1][y+1].display=true;
    }
}

bool Discover(struct Ttable table, char* in)
{
    bool ret=false;
    int x,y;
    char * inn=&in[1];
    x = atoi(strtok(inn,"-"));
    y = atoi(strtok(NULL,"-"));
    x--;y--;

    //first check if the shell contains a bomb
    if(table.v[x][y].bomb==true)
    {
        cout<<"Booom! Game Over, try again"<<endl;
        ret=true;
    }else{
        table.v[x][y].display=true;
        if(table.v[x][y].n==0)
        {
            Explote(table,x,y);
        }
    }

    return ret;
}

void Destructor(struct Ttable table)
{
    for(int i=0;i<table.width;i++){
            delete table.v[i];
            table.v[i]=NULL;
    }

    delete table.v;
    table.v=NULL;

}

void setNumberOfBombs(struct Ttable table)
{
    int i,j,bombs=0;

    for(i=0;i<table.width;i++)
    {
        for(j=0;j<table.hight;j++)
        {
            //bombs=0;
            if(!table.v[i][j].bomb)
            {
                //check for the upper shell
                if(i>0)
                {
                    if(table.v[i-1][j].bomb==true)
                        bombs++;
                }
                //check for the downer shell
                if(i<table.hight-1)
                {
                    if(table.v[i+1][j].bomb==true)
                        bombs++;
                }
                //check for the left shell
                if(j>0)
                {
                    if(table.v[i][j-1].bomb==true)
                        bombs++;
                }
                //check for the right shell
                if(j<table.width-1)
                {
                    if(table.v[i][j+1].bomb==true)
                        bombs++;
                }
                //check for the up-left shell
                if(j>0 && i>0)
                {
                    if(table.v[i-1][j-1].bomb==true)
                        bombs++;
                }
                //check for up-right shell
                if(i>0 && j<table.width-1)
                {
                    if(table.v[i-1][j+1].bomb)
                        bombs++;
                }
                //check for the down-left shell
                if(i<table.hight-1 && j>0)
                {
                    if(table.v[i+1][j-1].bomb)
                        bombs++;
                }
                //check for the down-right shell
                if(i<table.hight-1 && j<table.width-1)
                {
                    if(table.v[i+1][j+1].bomb)
                        bombs++;
                }
                table.v[i][j].n=bombs;
                bombs=0;
            }
        }
    }
}

void Configure(struct Ttable &table)
{
     // argv[1]=="-c"){
   cout<<"Hight:";
   cin>>table.hight;
   cout<<endl<<"Width:";
   cin>>table.width;
   cout<<endl<<"Number of bombs:";
   cin>>table.n_bombs;
   cout<<endl;
}

void Init(struct Ttable &table)
{
    int w,h;
    table.bombsDisc=0;
    w=table.width;
    h=table.hight;
    table.v = new struct Tshell* [w];
    for(int i=0;i<w;i++)
        table.v[i]=new struct Tshell[h];

    for(int i=0; i<table.width; i++)
    {
            for(int j=0; j<table.hight; j++)
            {
                    table.v[i][j].x=i;
                    table.v[i][j].y=j;
                    table.v[i][j].n=0;
                    table.v[i][j].mark=false;
                    table.v[i][j].bomb=false;
                    table.v[i][j].display=false;
            }
    }
    //set the random bombs

    int x,y;

    for(int i=0; i<table.n_bombs; i++){
            x= rand()%table.width;
            y= rand()%table.hight;
            table.v[x][y].bomb=true;
    }

}

bool IsNumber(const char* s)
{
   for (int i = 0; i < strlen(s); i++) {
       if (!isdigit(s[i]))
           return false;
   }

   return true;
}

bool Check(struct Ttable table,char* in)
{
    char * inn=&in[1];
    bool ret=false;
    char* aux;
    int x,y;
    aux = strtok(inn,"-");
    if(!strcmp(in,"conf") || !strcmp(in,"Conf"))//"in=="conf" || in=="Conf")
        return true;

    if(aux!="" && IsNumber(aux))
    {
        x = atoi(aux);
        aux=strtok(NULL,"- ");
        if(aux!="" && IsNumber(aux))
        {
            y = atoi(aux);
            if(x<=table.width && y<=table.hight)
                ret = true;
        }
    }
    return ret;
}

bool Win(struct Ttable table)
{
    bool ret = true;
    for(int i=0;i<table.width;i++)
    {
      for(int j=0;j<table.hight;j++)
      {
          if (!(table.v[i][j].display==true || (table.v[i][j].display=false && table.v[i][j].mark==true)))
            ret=false;
      }
    }
    if(ret && table.bombsDisc==table.n_bombs)
    {

      ret =true;
    }else
        ret = false;
    return ret;

}

int main(int argc, char** argv){
    //introduction to the game
    cout<<"-----------------MiNeSwEePeR-----------------"<<endl;
    cout<<"Instructions: X and Y are the coordenates for the table game shells"<<endl<<
    "   For pick(discover) a shell use dX-Y"<<endl<<
    "   For mark a shell use mX-Y"<<endl<<"Press Enter to continue"<<endl;
    cin.get();
    //srand(time(0)); //for set the random function

    struct Ttable table = {10,9,9};

    if(argc>2){
                cout<<"Invalid number of input parameters."<<endl;
                return 0;
    }
    if(argv[1]=="--conf"){
        Configure(table);

    }

    //Initialiting the seed
    srand (time(NULL));
    //srand((unsigned)getpid());

    //Initialiting the shells of the table
    Init(table);

    //set the nomber of neightbores shells with bombs for each shell
    setNumberOfBombs(table);
    DrawnTable(table);
    //The game starts
    char* in;char aux[10];
    bool checked=false;
//    bool gameOver=true;
    while(true)
   {

              checked=false;
              cout<<"Input: "<<endl;
              cin>>in;
              strcpy(aux,in);
              if(Check(table,aux))
                    checked=true;

              if(checked && (in[0]=='d' || in[0]=='D')) //discover shell
              {
                             if(Discover(table,in)){ //if the user picks in a boomb halt game
                                Destructor(table);
                                system("pause");
                                return 0;
                             }
              }
              else{
                  if(checked &&(in[0]=='m' || in[0]=='M')) //mark shell
                      Mark(table,in);

                  else
                  {
                    if(!strcmp(in,"conf") || !strcmp(in,"Conf"))
                    {
                            Destructor(table);
                            Configure(table);
                            Init(table);
                            //set the nomber of neightbores shells with bombs for each shell
                            setNumberOfBombs(table);

                    }
                    else
                        cout<<endl<<endl<<"Invalid option. Retry"<<endl<<endl;
                  }

              }
              DrawnTable(table);

              if(Win(table))
              {
                  cout<<"Finished! You win."<<endl;
                  system("pause");
                  return 0;
              }
   }

}

¿Ocurre siempre? ¿Cuando ganas, cuando has marcado una casilla, o no has marcado ninguna? Pon el error que te muestra.

¿entiendo que quieres que te ayudemos con un programa para windows y que está en inglés encima? jat

--> Esdebian. La mayor comunidad de Debian en español

pvaldes escribió:

¿entiendo que quieres que te ayudemos con un programa para windows y que está en inglés encima? jat

--> Esdebian. La mayor comunidad de Debian en español

Será para usarlo con wine, que mal pensado eres eyebrows

jajajaja, gracias por el capote pero sinceramente es para ejecutarlo desde güindows, aunque no por gusto, obviamente es mucho más cómodo desarrollar en c/c++/java desde linux. De todas formas este apartado trata sobre programación en c++ no?

No, no ocurre siempre, al marcar, descubrir casilla...en el desarrollo del juego en general funciona perfectamente.
Ocurre siempre que finalices,ya ganes, pierdas o cierres la aplicación. Depurando línea a línea llego hasta el final, al salir del main, al salir del último corchete, de ahí que piense a que se debe a algún tipo de destructor que debe invocar automáticamente.
Ahí va el ***** error:

Process returned -1073741819 (0xC0000005) execution time: 19,950s

En modo depuración se ve el sementation fault:

Setting breakpoints
Debugger name and version: GNU gdb 6.8
Child process PID: 5200
Program received signal SIGSEGV, Segmentation fault.
In ?? () ()

Lo del inglés no creo que sea para tanto, son cuatro palabrejas. Table: tablero, sheel: casilla, bomb: bomba... de todas formas mis disculpas a quién le suponga un inconveniente :)

Ya lo tengo!! Alguna tontería tenía que ser, no le veía el sentido por ningún lado.
Resulta que inicializaba la variable "in" como

char *in;
//para luego utilizarla sin un tamaño especifico
cin>>in;

En el momento en que la he inicializado con una longitud determinada me ha dejado de dar problemas

char in[10];

Y todo el tiempecito que me he tirado........ es ley de vida :P

vivoconunxino escribió:

Ya lo tengo!! Alguna tontería tenía que ser, no le veía el sentido por ningún lado.
Resulta que inicializaba la variable "in" como

char *in;
//para luego utilizarla sin un tamaño especifico
cin>>in;

En el momento en que la he inicializado con una longitud determinada me ha dejado de dar problemas

char in[10];

Y todo el tiempecito que me he tirado........ es ley de vida :P

Pues marcalo como solucionado.