2016-01-21 114 views
0

我使用雙向鏈接列表編寫經典的Snake遊戲,並編寫了一個函數,該函數創建一個指針,爲結構分配所需空間,然後分配內存給列表中的下一個指針等等。最後,指向第一個元素的指針由函數返回,並且可以分配給主函數中的頭指針。初始化for循環中的雙向鏈接導致崩潰

當開始遊戲時,我希望蛇的長度爲3,所以我在函數中使用了三個malloc,並使用了指針,指針 - >下一個,指針 - >下一個 - >下一個等,並且一切正常。

由於很多步驟都在這個過程中,我認爲把所有這一切到一個for循環這樣的重複:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct snake snake; 
struct snake { 
    int x; /* x coordinate */ 
    int y; /* y coordinate */ 
    snake *previous; 
    snake *next; 
}; 

snake *initSnake(void) { 
    snake *pointer, *tmp1, *tmp2 = NULL; 
    /* three iterations, so the snake will have a length of three */ 
    for(int i = 0; i<3; i++, tmp1 = tmp1->next) { 
     if(NULL == (tmp1 = (snake*)malloc(sizeof(snake)))) { 
      return NULL; 
     } 
     /* coordinates */ 
     tmp1->x = 20; 
     tmp1->y = 10 + i; 
     /* first previous points to NULL */ 
     tmp1->previous = tmp2; 
     /* temporarily store last pointer to be used for next previous pointer */ 
     tmp2 = tmp1; 
     if(0 == i) { 
      /* store first pointer so it can be returned */ 
      pointer = tmp1; 
     } 

    } 
    /* the last next pointer has to point to NULL */ 
    tmp1 = NULL; 
    /* now return the pointer to the first element in list */ 
    return pointer; 
} 


int main() { 
    /* pointer to first element in list */ 
    snake *head = NULL; 

    if(NULL == (head = initSnake())) { 
     fprintf(stderr, "Not enough memory!\n"); 
     return EXIT_FAILURE; 
    } 
    /* here everything works fine */ 
    printf("%d\n", head->y); 
    printf("%d\n", head->previous); 
    /* when trying to acces the content of the next element, the program crashes... */ 
    printf("%d\n", head->next->x); 
    /* pause */ 
    getchar(); 
} 

的問題是,當我嘗試訪問的第二個元素主要功能內的列表,遊戲崩潰。我懷疑在for循環中 tmp1 = tmp1->next有什麼問題,我不能真正訪問下一個指針,但我不完全確定。

你能幫我嗎?

+0

可能設置tmp1->未來= NULL會有所幫助,或撥打釋放calloc代替的malloc。並且不要強制malloc的返回值。 – bruceg

+0

@bruceg爲什麼不投放malloc的返回?我很少看到它,但我的教授在做C講座時堅持要這樣做。 – user1662035

+0

http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – bruceg

回答

0

你要最後下一個指針設置爲NULL:

/* the last next pointer has to point to NULL */ 
tmp1->next = NULL; // -> next ! 

因爲tmp1是一個局部變量,將其設置爲只返回時,將沒有任何效果之前NULL。

編輯:

哎呀,也不for循環做tmp1 = tmp1->next的:因爲它沒有設置此刻的你嘗試執行此操作。您需要下一個與以前一起設置:

/* first previous points to NULL */ 
    tmp1->previous = tmp2; 
    if (tmp2) 
     tmp2->next = tmp1; 

Online demo

+0

但tmp1已經是列表中的最後一個' - >下一個指針',因爲我將'tmp1'設置爲' tmp1-> next',然後離開循環。 – user1662035

+0

此刻你做了tmp1 = tmp1-> next,你從未設置過下一個值。看到我的編輯 – Christophe

+0

實際上你的雙鏈表只有單鏈接... – Christophe

1

你有很多暗示,你真的不知道如何記憶,變量&指針的工作失誤。例如在for循環結束時做tmp1 = tmp1->next,緊接着tmp1 = (snake*)malloc(sizeof(snake))覆蓋tmp1,並使之前的操作變得毫無意義。代碼中的其他地方也有類似的操作。

要清理一下,試試這個:

snake *initSnake(void) { 
    snake *head, **current, *prev; 

    /* three iterations, so the snake will have a length of three */ 
    for(int i = 0, prev = NULL, current = &head; i<3; i++) { 
     if(NULL == (*current = malloc(sizeof(snake)))) { 
      return NULL; /* note that if this happens midway 
        through allocation, nothing gets freed */ 
     } 
     /* coordinates */ 
     (*current)->x = 20; 
     (*current)->y = 10 + i; 
     /* next, previous pointers */ 
     (*current)->next = NULL; 
     (*current)->previous = prev; 
     prev = *current; 
     current = &current->next; 
    } 

    /* now return the pointer to the first element in list */ 
    return head; 
}