2017-03-24 1 views
-1

Je tente de faire une version C du jeu Snake pour mes devoirs. J'ai implémenté tous les mécanismes nécessaires au jeu mais j'ai un problème avec l'allocation de mémoire dynamique. Mon «serpent» est stocké dans un tableau comme une liste de pièces de corps et leur emplacement. Si le serpent mange le fruit, j'essaye de changer la longueur du serpent et d'ajouter un autre morceau de corps au tableau. Comme je ne connais pas la taille finale du serpent, j'essaye d'allonger le tableau en utilisant realloc. Voici mon code. Note: cela fonctionne pour 14 itérations avant de provoquer un SIGABRT.SIGABRT lors de l'utilisation de realloc()

#include <stdio.h> 
#include <stdlib.h> 
void moveSnake(int *snakeLength,int direction, int **tableSnake, int extend); 
int checkItems(int **tableSnake, int **items, int itemsSize); 
int selfdestruct(int **tableSnake); 

/* TEST INPUT DATA: 
9 
-5 4 2 
-3 4 1 
-2 4 1 
0 4 2 
1 3 3 
-2 2 1 
0 2 1 
-7 1 1 
-5 1 3 
15 
*/ 

int main() { 
    int xHead = 0; 
    int yHead = 0; 
    int snakeLength = 1; 
    int direction = 1; 

    // creates the snake table 


    int **tableSnake; 
    tableSnake = (int **) calloc(1,1 * sizeof (int *)); 

    for (int i = 0; i < 1; i++) { 
     tableSnake[i] = (int *) calloc(3,3 * sizeof (int)); 
    } 

    tableSnake[0][0] = 0; 
    tableSnake[0][1] = 0; 
    tableSnake[0][2] = 1; 


    // reads all the variables 
    int noItems; 
    scanf("%d", &noItems); 

    int **items; 
    items = (int **) malloc(noItems * sizeof (int *)); 

    for (int i = 0; i < noItems; i++) { 
     items[i] = (int *) malloc(3 * sizeof (int)); 
    } 

    for (int i = 0; i < noItems; i++) { 
     scanf("%d", &items[i][0]); 
     scanf("%d", &items[i][1]); 
     scanf("%d", &items[i][2]); 
    } 


    int noSteps; 
    scanf("%d", &noSteps); 

    // start of run 

    /* 
    * legend: 
    * direction: 1 - up, 2 - down, 3 - left, 4 - right 
    * typesOfItems: 5 - fruit, 6 - turn left, 7 - turn right 
    */ 

    int itemHead = 0; 
    int extend = 0; 

    for (int i = 0; i < noSteps; i++) { 
     moveSnake(&snakeLength,direction,tableSnake,extend); 
     extend = 0; 
     itemHead = checkItems(tableSnake, items, noItems); 

     if(itemHead == -1){ 
      if(selfdestruct(tableSnake) == 1){ 
       snakeLength = 0; 
       break; 
      }; 
     } 
     if (itemHead == 1) { 
      extend = 1; 
     } else if (itemHead == 2) { 
      if(direction == 1){ 
       direction = 3; 
      }else if(direction == 2){ 
       direction = 4; 
      }else if(direction = 3){ 
       direction = 2; 
      }else{ 
       direction = 1; 
      } 
     } else if (itemHead == 3) { 
      if(direction == 1){ 
       direction = 4; 
      }else if(direction == 2){ 
       direction = 3; 
      }else if(direction = 3){ 
       direction = 1; 
      }else{ 
       direction = 2; 
      } 
     } 
    } 
    printf("%d %d %d", snakeLength, tableSnake[0][0], tableSnake[0][1]); 

    return (EXIT_SUCCESS); 
} 

void moveSnake(int *snakeLength,int direction, int **tableSnake, int extend){ 
    int tempX = tableSnake[0][0]; 
    int tempY = tableSnake[0][1]; 
    int tempDirection = tableSnake[0][2]; 

    int tempXTail = tableSnake[*snakeLength -1][0]; 
    int tempYTail = tableSnake[*snakeLength -1][1]; 
    int tempDirectionTail = tableSnake[*snakeLength -1][2]; 

    int tempRep[3] = {tempXTail,tempYTail,tempDirectionTail}; 
    if(direction == 1){ 
     tempY++; 
    }else if(direction == 2){ 
     tempY--; 
    }else if(direction == 3){ 
     tempX--; 
    }else if(direction == 4){ 
     tempX++; 
    } 

    int *temp; 
    temp = malloc(3 * sizeof(int)); 
    for(int i = 0; i < *snakeLength; i++){ 
     temp = tableSnake[i]; 
     tableSnake[i][0] = tempX; 
     tableSnake[i][1] = tempY; 
     tableSnake[i][2] = tempDirection; 
     tempX = temp[0]; 
     tempY = temp[1]; 
     tempDirection = temp[2]; 
    } 
    if(extend == 1){ 
     // this is where the error occurs 
     *snakeLength = *snakeLength +1; 
     tableSnake = realloc(tableSnake, *snakeLength * sizeof(int)); 
     tableSnake[*snakeLength-1] = tempRep; 
    } 

} 

int checkItems(int **tableSnake, int **items, int itemsSize){ 
    int *item; 
    item = malloc(3 * sizeof(int)); 
    int itemX; 
    int itemY; 
    int headX = tableSnake[0][0]; 
    int headY = tableSnake[0][1]; 

    for(int i = 0; i < itemsSize; i++){ 
     item = items[i]; 
     itemX = item[0]; 
     itemY = item[1]; 
     if(itemX == headX && itemY == headY){ 
      return item[2]; 
     } 
    } 
    return -1; 
} 

int selfdestruct(int **tableSnake){ 
    int tempX = tableSnake[0][0]; 
    int tempY = tableSnake[0][1]; 
    int lengthTable = sizeof(tableSnake)/sizeof(tableSnake[0]); 

    for(int i = 1; i < lengthTable; i++){ 
     if(tempX == tableSnake[i][0]){ 
      if(tempY == tableSnake[i][1]){ 
       return 1; 
      } 
     } 
    } 
    return 0; 
} 
+0

vous avez des fuites de mémoire: 'item = malloc (3 * sizeof (int));' –

+0

autre problème: 'temp = malloc (3 * sizeof (int)); pour (int i = 0; i <* snakeLength; i ++) { temp = tableSnake [i]; TableSnake [i] [0] = tempX; tableSnake [i] [1] = tempY; TableSnake [i] [2] = tempDirection; tempX = temp [0]; tempY = temp [1]; tempDirection = temp [2]; } 'Le contenu de' temp' est globalement non initialisé la première fois. –

+0

@JohnnyMopp Ce serait la solution simple mais mes instructions de devoirs indiquent que le terrain de jeu devrait être la taille 2.000.000x2.000.000 qui est beaucoup trop grande pour tenir dans la mémoire – Muzgar15

Répondre

0

Si je mets ces deux lignes ensemble, un problème devrait être évident?

tableSnake = (int **) calloc(1,1 * sizeof (int *)); 

...

tableSnake = realloc(tableSnake, *snakeLength * sizeof(int)); 

et vous n'êtes pas allouer de la mémoire pour le nouvel élément tableSnake, mais il en montrant une variable locale ...

tableSnake[*snakeLength-1] = tempRep; 

. ..qui sera automatiquement libéré lorsque vous quittez cette fonction.

0

L'effet de:

tableSnake = realloc(tableSnake, *snakeLength * sizeof(int)); 

..does ne se propagent en dehors de la fonction moveSnake(). Une solution est de retour « tableSnake » à la suite

int ** moveSnake(int *snakeLength,int direction, int **tableSnake, int extend){ 
     ... 
     return tablesnake; 
    ); 

... 

tableSnake=moveSnake(&snakeLength,direction,tableSnake,extend); 

Cette question serait probablement même pas surgi si vous aviez nommé les vars plus clairement, par exemple « localSnake » pour le paramètre. Essayez très difficile de ne pas donner plus d'un var le même nom :)