2017-02-15 127 views
0

昨天我剛開始一個新項目(roguelike)。這是我的第一個,我一直在遇到同樣的錯誤。試圖實現滾動地圖後,我運行該程序,但每當按下某個鍵時,Visual Studio都會顯示一個消息框,指出存在訪問衝突讀取位置。C中的PDCurses(保持顯示「訪問衝突讀取位置」)

下面的代碼:

#include "curses.h" 
#include <stdlib.h> 

#define MAX_HEIGHT 16 
#define MAX_WIDTH 21 

typedef struct tile 
{ 
    char *tile; 
    bool passable; 
}tile; 

typedef struct player 
{ 
    int xpos; 
    int ypos; 
    int dx; 
    int dy; 
}player; 

tile tileArray[] = { 
    {".",TRUE}, 
    {"#",FALSE}, 
    {"+",FALSE}, 
    {"/",TRUE} 
}; 

int mapArray[15][21] = { 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 
    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } 

}; 

typedef struct camPos 
{ 
    int y; 
    int x; 
}camPos; 

void initSetup(); 
player *actorSetup(); 
void refreshScreenMap(); 
void handleInput(); 
void drawScreenMap(); 
void interactionOpen(); 
bool isPassable(int y, int x); 
void startupScreen(); 

player *user; 
camPos cam; 

int main() 
{ 
    initSetup(); 

    user = actorSetup(); 
    cam.y = 2; 
    cam.x = 2; 

    startupScreen(); 

    while (TRUE) 
    { 
     drawScreenMap(); 
     refreshScreenMap(); 
     handleInput(); 
     clear(); 
    } 
    endwin(); 
    return 0; 
} 

void initSetup() 
{ 
    initscr(); 
    noecho(); 
    raw(); 
    keypad(stdscr,TRUE); 
} 

player *actorSetup() 
{ 
    player *newactor; 
    newactor = malloc(sizeof(player)); 
    newactor->xpos = 10; 
    newactor->ypos = 10; 
    return newactor; 
} 

void handleInput() 
{ 
    char button = getch(); 
    switch (button) 
    { 
     case 's': 
      user->dy++; 
      break; 
     case 'w': 
      user->dy--; 
      break; 
     case 'a': 
      user->dx--; 
      break; 
     case 'd': 
      user->dx++; 
      break; 
     case 'o': 
      interactionOpen(user); 
      break; 
    } 
    if (isPassable(user->ypos + user->dy, user->xpos + user->dx)) 
    { 
     user->ypos += user->dy; 
     user->xpos += user->dx; 
    } 
    else 
    { 
     user->dx = 0; 
     user->dy = 0; 
    } 
} 

void refreshScreenMap() 
{ 
    mvprintw(6, 8, "@"); 
    cam.x += user->dx; 
    cam.y += user->dy; 
} 

void drawScreenMap() 
{ 
    for (int y = 1; y < 12; y++) 
    { 
     move(y,1); 
     for (int x = 1; x < 16; x++) 
     { 
      mvprintw(y, x, tileArray[mapArray[cam.y + y][cam.x + x]].tile); 
     } 
    } 
} 

void interactionOpen() 
{ 
    if (mapArray[user->ypos + 1][user->xpos] == 2) 
    { 
     mapArray[user->ypos + 1][user->xpos] = 3; 
    } 
    else if (mapArray[user->ypos - 1][user->xpos] == 2) 
    { 
     mapArray[user->ypos - 1][user->xpos] = 3; 
    } 
    else if (mapArray[user->ypos][user->xpos + 1] == 2) 
    { 
     mapArray[user->ypos][user->xpos + 1] = 3; 
    } 
    else if (mapArray[user->ypos][user->xpos - 1] == 2) 
    { 
     mapArray[user->ypos][user->xpos - 1] = 3; 
    } 
    else if (mapArray[user->ypos + 1][user->xpos] == 3) 
    { 
     mapArray[user->ypos + 1][user->xpos] = 2; 
    } 
    else if (mapArray[user->ypos - 1][user->xpos] == 3) 
    { 
     mapArray[user->ypos - 1][user->xpos] = 2; 
    } 
    else if (mapArray[user->ypos][user->xpos + 1] == 3) 
    { 
     mapArray[user->ypos][user->xpos + 1] = 2; 
    } 
    else if (mapArray[user->ypos][user->xpos - 1] == 3) 
    { 
     mapArray[user->ypos][user->xpos - 1] = 2; 
    } 
} 

bool isPassable(int y, int x) 
{ 
    bool pass = tileArray[mapArray[y][x]].passable; 
    if (pass == FALSE) 
    { 
     return FALSE; 
    } 
    else if (y < cam.y || y >= (cam.y + 11)) 
    { 
     return FALSE; 
    } 
    else if (x < cam.x || x >= (cam.x + 15)) 
    { 
     return FALSE; 
    } 
    else 
    { 
     return TRUE; 
    } 
} 

void startupScreen() 
{ 
    mvprintw(10, 20, "________"); 
    mvprintw(11, 20, "\\______ \\ __ __ ____ ____ ____ ____ ____ "); 
    mvprintw(12, 20, " | | \\| | \\/ \\/___\\_/ __ \\/ _ \\/ \\ "); 
    mvprintw(13, 20, " | ` \\ |/ | \\/ /_/ > ___( <_>) | \\ "); 
    mvprintw(14, 20, "/_______ /____/|___| /\\___/\\___ >____/|___|/"); 
    mvprintw(15, 20, "  \\/   \\//_____/  \\/   \\/"); 
    mvprintw(16, 20, "Made by Will Reid"); 
    mvprintw(17, 20, "Press any key to start..."); 
    getch(); 
    clear(); 
} 
+1

哪裏*確切*它崩潰?請使用調試器並告訴我們哪一行會導致段錯誤。 –

+0

Game.exe中0x00221CD5未處理的異常:0xC0000005:訪問衝突讀取位置0xBEE161B4。 (來自Visual Studios的消息)該行是; bool pass = tileArray [mapArray [y] [x]]。 (在函數isPassable中)但是,當我將pass改爲等於TRUE時,斷點移動到; mvprintw(y,x,tileArray [mapArray [cam.y + y] [cam.x + x]]。 (在drawScreenMap函數中)。感謝您看看它! –

+1

只是一個猜測:你可能會在數組中使用不良索引。我建議你創建兩個函數:'int getMapValue(int x,int y);'和'bool setMapValue(int x,int y,int value);'。每當訪問'mapArray'時使用這些函數。然後,您可以添加代碼以確保您的索引在範圍內。如果他們不是,那麼打印一個錯誤。 –

回答

0

的問題是,在isPassable使用的變量cam未初始化。

我使用的valgrind(在Linux上)看到這樣的:

==11010== 1 errors in context 1 of 7: 
==11010== Invalid read of size 8 
==11010== at 0x400B72: drawScreenMap (foo.c:151) 
==11010== by 0x40091E: main (foo.c:77) 
==11010== Address 0x58e8c2a0 is not stack'd, malloc'd or (recently) free'd 
==11010== 
==11010== 
==11010== 7 errors in context 2 of 7: 
==11010== Conditional jump or move depends on uninitialised value(s) 
==11010== at 0x40100E: isPassable (foo.c:203) 
==11010== by 0x400A46: handleInput (foo.c:124) 
==11010== by 0x400928: main (foo.c:79) 
==11010== Uninitialised value was created by a heap allocation 
==11010== at 0x4C28BED: malloc (vg_replace_malloc.c:263) 
==11010== by 0x400974: actorSetup (foo.c:97) 
==11010== by 0x4008F9: main (foo.c:69) 

而且,打開編譯器警告顯示的幾個問題(Visual Studio中有編譯器警告......)。