2012-05-30 93 views
2

我有一個奇怪的問題,谷歌和SO搜索無法幫助。這可能是一件非常簡單的事情,但我一直在顛簸幾個小時,並且無法把它趕出去。C函數意外地改變了值

我正在做C使用Ncurses俄羅斯方塊(使用Ubuntu)。

我的主函數調用updatePiece()函數,同時傳入指向追蹤活動塊狀態的結構的指針以及鍵盤輸入緩衝區。

的結構:

struct piece {                 
    struct coords pos;               
    char currentMap[4][MAPSIZEX][MAPSIZEY];          
    int type;                 
    int rotation;                
    int leftColumn;                
    int rightColumn;                
    int bottomRow;                
}; 

的updatePiece功能:

void updatePiece(struct piece* piece, int input) {        
    switch(input) {                
     case KEY_UP:                
      ++piece->rotation;             
      if(piece->rotation == 4)            
       piece->rotation = 0;            
      getBoundary(piece);             
      break;                
     case KEY_RIGHT:               
      if(piece->pos.x + piece->rightColumn != WELLSIZEX)     
       ++piece->pos.x;             
      break;                
     case KEY_LEFT:               
      if(piece->pos.x + piece->leftColumn != 0)       
       --piece->pos.x;             
      break;                
     case 'p':                
      ++piece->type;              
      selectMap(piece);             
      getBoundary(piece);             
      break;                
    }                   

    if(piece->pos.y + piece->bottomRow >= WELLSIZEY)        
     piece->pos.y = 0;              
    ++piece->pos.y;                
} 

酷,因此函數移動件左右,旋轉等我最終會使用RAND()來選擇一個新一旦當前作品成爲'死亡'等,但現在我正在檢測'p'被輸入並使用它來隨意增加計數器。

但是,這件作品看起來只會旋轉一次。使用mvprintw()告訴我piece-> type的內容似乎不會改變。

所以我跳進gdb來了解發生了什麼。起初,一切都順其自然。在stdin中檢測到'p',piece-> type確實增加,然後調用selectMap()函數。這是有趣的事情發生的地方。

void selectMap(struct piece* piece) {           
    switch(piece->type) {              
     // T Piece                
     case 0:                 
      strcpy(piece->currentMap[0][0], "....");        
      strcpy(piece->currentMap[0][1], ".X..");        
      strcpy(piece->currentMap[0][2], "XXX.");        
      strcpy(piece->currentMap[0][3], "....");        
      strcpy(piece->currentMap[1][0], "....");        
      strcpy(piece->currentMap[1][1], ".X..");        
      strcpy(piece->currentMap[1][2], ".XX.");        
      strcpy(piece->currentMap[1][3], ".X..");        
      strcpy(piece->currentMap[2][0], "....");        
      strcpy(piece->currentMap[2][1], "....");        
      strcpy(piece->currentMap[2][2], "XXX.");        
      strcpy(piece->currentMap[2][3], ".X..");        
      strcpy(piece->currentMap[3][0], "....");        
      strcpy(piece->currentMap[3][1], ".X..");        
      strcpy(piece->currentMap[3][2], "XX..");        
      strcpy(piece->currentMap[3][3], ".X..");        
      return;                
     // J Piece                
     case 1:                 
      strcpy(piece->currentMap[0][0], "....");        
      strcpy(piece->currentMap[0][1], ".X..");        
      strcpy(piece->currentMap[0][2], ".X..");        
      strcpy(piece->currentMap[0][3], "XX..");        
      strcpy(piece->currentMap[1][0], "....");        
      strcpy(piece->currentMap[1][1], "X...");        
      strcpy(piece->currentMap[1][2], "XXX.");        
      strcpy(piece->currentMap[1][3], "....");        
      strcpy(piece->currentMap[2][0], "....");        
      strcpy(piece->currentMap[2][1], ".XX.");        
      strcpy(piece->currentMap[2][2], ".X..");        
      strcpy(piece->currentMap[2][3], ".X..");        
      strcpy(piece->currentMap[3][0], "....");        
      strcpy(piece->currentMap[3][1], "....");        
      strcpy(piece->currentMap[3][2], "XXX.");        
      strcpy(piece->currentMap[3][3], "..X.");        
      return; 

      <REST OF FUNCTION OMITTED> 
    } 
} 

該函數改變currentPiece char數組以匹配當前件的類型。一切都複製得很好,但一旦函數退出piece-> type設置爲0.

我不知道爲什麼。件是通過引用傳遞的,所以它不應該是範圍問題。使用一個開關或一堆if/elses不起作用。使用中斷或返回不起作用。

這可能是一些非常簡單和愚蠢的事情,但作爲一個自學的編碼器,它讓我難住了。

任何幫助表示讚賞。整個代碼如下(隨意批評!):

#include <ncurses.h> 
#include <stdlib.h> 
#include <string.h> 

#define WELLSIZEX 10 
#define WELLSIZEY 20 
#define MAPSIZEX 4 
#define MAPSIZEY 4 
#define DELAY  100000 

struct coords { 
    int x; 
    int y; 
}; 

struct piece { 
    struct coords pos; 
    char currentMap[4][MAPSIZEX][MAPSIZEY]; 
    int type; 
    int rotation; 
    int leftColumn; 
    int rightColumn; 
    int bottomRow; 
}; 


void selectMap(struct piece* piece) { 
    switch(piece->type) { 
     // T Piece 
     case 0: 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".X.."); 
      strcpy(piece->currentMap[0][2], "XXX."); 
      strcpy(piece->currentMap[0][3], "...."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], ".X.."); 
      strcpy(piece->currentMap[1][2], ".XX."); 
      strcpy(piece->currentMap[1][3], ".X.."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], "...."); 
      strcpy(piece->currentMap[2][2], "XXX."); 
      strcpy(piece->currentMap[2][3], ".X.."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], ".X.."); 
      strcpy(piece->currentMap[3][2], "XX.."); 
      strcpy(piece->currentMap[3][3], ".X.."); 
      return; 
     // J Piece 
     case 1: 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".X.."); 
      strcpy(piece->currentMap[0][2], ".X.."); 
      strcpy(piece->currentMap[0][3], "XX.."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], "X..."); 
      strcpy(piece->currentMap[1][2], "XXX."); 
      strcpy(piece->currentMap[1][3], "...."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], ".XX."); 
      strcpy(piece->currentMap[2][2], ".X.."); 
      strcpy(piece->currentMap[2][3], ".X.."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], "...."); 
      strcpy(piece->currentMap[3][2], "XXX."); 
      strcpy(piece->currentMap[3][3], "..X."); 
      return; 
     // L Piece 
     case 2: 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".X.."); 
      strcpy(piece->currentMap[0][2], ".X.."); 
      strcpy(piece->currentMap[0][3], ".XX."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], "...."); 
      strcpy(piece->currentMap[1][2], "XXX."); 
      strcpy(piece->currentMap[1][3], "X..."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], "XX.."); 
      strcpy(piece->currentMap[2][2], ".X.."); 
      strcpy(piece->currentMap[2][3], ".X.."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], "..X."); 
      strcpy(piece->currentMap[3][2], "XXX."); 
      strcpy(piece->currentMap[3][3], "...."); 
      return; 
     // O Piece 
     case 3: 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".XX."); 
      strcpy(piece->currentMap[0][2], ".XX."); 
      strcpy(piece->currentMap[0][3], "...."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], ".XX."); 
      strcpy(piece->currentMap[1][2], ".XX."); 
      strcpy(piece->currentMap[1][3], "...."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], ".XX."); 
      strcpy(piece->currentMap[2][2], ".XX."); 
      strcpy(piece->currentMap[2][3], "...."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], ".XX."); 
      strcpy(piece->currentMap[3][2], ".XX."); 
      strcpy(piece->currentMap[3][3], "...."); 
      return; 
     // I Piece 
     case 4: 
      strcpy(piece->currentMap[0][0], ".X.."); 
      strcpy(piece->currentMap[0][1], ".X.."); 
      strcpy(piece->currentMap[0][2], ".X.."); 
      strcpy(piece->currentMap[0][3], ".X.."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], "...."); 
      strcpy(piece->currentMap[1][2], "XXXX"); 
      strcpy(piece->currentMap[1][3], "...."); 
      strcpy(piece->currentMap[2][0], ".X.."); 
      strcpy(piece->currentMap[2][1], ".X.."); 
      strcpy(piece->currentMap[2][2], ".X.."); 
      strcpy(piece->currentMap[2][3], ".X.."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], "...."); 
      strcpy(piece->currentMap[3][2], "XXXX"); 
      strcpy(piece->currentMap[3][3], "...."); 
      return; 
     // S Piece 
     case 5: 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".XX."); 
      strcpy(piece->currentMap[0][2], "XX.."); 
      strcpy(piece->currentMap[0][3], "...."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], "X..."); 
      strcpy(piece->currentMap[1][2], "XX.."); 
      strcpy(piece->currentMap[1][3], ".X.."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], ".XX."); 
      strcpy(piece->currentMap[2][2], "XX.."); 
      strcpy(piece->currentMap[2][3], "...."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], "X..."); 
      strcpy(piece->currentMap[3][2], "XX.."); 
      strcpy(piece->currentMap[3][3], ".X.."); 
      return; 
     // Z Piece 
     case 6: 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], "XX.."); 
      strcpy(piece->currentMap[0][2], ".XX."); 
      strcpy(piece->currentMap[0][3], "...."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], ".X.."); 
      strcpy(piece->currentMap[1][2], "XX.."); 
      strcpy(piece->currentMap[1][3], "X..."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], "XX.."); 
      strcpy(piece->currentMap[2][2], ".XX."); 
      strcpy(piece->currentMap[2][3], "...."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], ".X.."); 
      strcpy(piece->currentMap[3][2], "XX.."); 
      strcpy(piece->currentMap[3][3], "X..."); 
      return; 
     } 
/* 
     if(piece->type == 0) { 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".X.."); 
      strcpy(piece->currentMap[0][2], "XXX."); 
      strcpy(piece->currentMap[0][3], "...."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], ".X.."); 
      strcpy(piece->currentMap[1][2], ".XX."); 
      strcpy(piece->currentMap[1][3], ".X.."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], "...."); 
      strcpy(piece->currentMap[2][2], "XXX."); 
      strcpy(piece->currentMap[2][3], ".X.."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], ".X.."); 
      strcpy(piece->currentMap[3][2], "XX.."); 
      strcpy(piece->currentMap[3][3], ".X.."); 
     } 
     if(piece->type == 1) { 
      strcpy(piece->currentMap[0][0], "...."); 
      strcpy(piece->currentMap[0][1], ".X.."); 
      strcpy(piece->currentMap[0][2], ".X.."); 
      strcpy(piece->currentMap[0][3], "XX.."); 
      strcpy(piece->currentMap[1][0], "...."); 
      strcpy(piece->currentMap[1][1], "X..."); 
      strcpy(piece->currentMap[1][2], "XXX."); 
      strcpy(piece->currentMap[1][3], "...."); 
      strcpy(piece->currentMap[2][0], "...."); 
      strcpy(piece->currentMap[2][1], ".XX."); 
      strcpy(piece->currentMap[2][2], ".X.."); 
      strcpy(piece->currentMap[2][3], ".X.."); 
      strcpy(piece->currentMap[3][0], "...."); 
      strcpy(piece->currentMap[3][1], "...."); 
      strcpy(piece->currentMap[3][2], "XXX."); 
      strcpy(piece->currentMap[3][3], "..X."); 
     } 
*/ 

} 

void inits(struct piece* piece, char wellMap[WELLSIZEX][WELLSIZEY]) { 
    piece->pos.x = piece->pos.y = 1; 
    piece->rotation = 0; 
    piece->type = 0; 
    piece->leftColumn = 0; 
    piece->rightColumn = 2; 
    piece->bottomRow = 2; 

    selectMap(piece); 

    int x, y; 
    for(y = 0; y < WELLSIZEY; ++y) 
     for(x = 0; x < WELLSIZEX; ++x) 
      wellMap[x][y] = '.'; 
} 

void getBoundary(struct piece* piece) { 
    // T Piece 
    if(piece->type == 0) { 
     if(piece->rotation == 0) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 2; 
      return; 
     } 
     if(piece->rotation == 1) { 
      piece->leftColumn = 1; 
      piece->rightColumn = 2; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 2) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 3) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 1; 
      piece->bottomRow = 3; 
      return; 
     } 
    } 
    // J Piece 
    if(piece->type == 1) { 
     if(piece->rotation == 0) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 1; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 1) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 2; 
      return; 
     } 
     if(piece->rotation == 2) { 
      piece->leftColumn = 1; 
      piece->rightColumn = 2; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 3) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 3; 
      return; 
     } 
    } 
    // L Piece 
    if(piece->type == 2) { 
     if(piece->rotation == 0) { 
      piece->leftColumn = 1; 
      piece->rightColumn = 2; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 1) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 2) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 1; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 3) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 2; 
      return; 
     } 
    } 
    // O Piece 
    if(piece->type == 3) { 
     piece->leftColumn = 1; 
     piece->rightColumn = 2; 
     piece->bottomRow = 2; 
     return; 
    } 
    // I Piece 
    if(piece->type == 4) { 
     if(piece->rotation == 0 || piece->rotation == 2) { 
      piece->leftColumn = 1; 
      piece->rightColumn = 1; 
      piece->bottomRow = 3; 
      return; 
     } 
     if(piece->rotation == 1 || piece->rotation == 3) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 3; 
      piece->bottomRow = 2; 
      return; 
     } 
    } 
    // S/Z Piece 
    if(piece->type == 5 || piece->type == 6) { 
     if(piece->rotation == 0 || piece->rotation == 2) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 2; 
      piece->bottomRow = 2; 
      return; 
     } 
     if(piece->rotation == 1 || piece->rotation == 3) { 
      piece->leftColumn = 0; 
      piece->rightColumn = 1; 
      piece->bottomRow = 3; 
      return; 
     } 
    } 
} 

void updatePiece(struct piece* piece, int input) { 
    switch(input) { 
     case KEY_UP: 
      ++piece->rotation; 
      if(piece->rotation == 4) 
       piece->rotation = 0; 
      getBoundary(piece); 
      break; 
     case KEY_RIGHT: 
      if(piece->pos.x + piece->rightColumn != WELLSIZEX) 
       ++piece->pos.x; 
      break; 
     case KEY_LEFT: 
      if(piece->pos.x + piece->leftColumn != 0) 
       --piece->pos.x; 
      break; 
     case 'p': 
      ++piece->type; 
      selectMap(piece); 
      getBoundary(piece); 
      break; 
    } 

    if(piece->pos.y + piece->bottomRow >= WELLSIZEY) 
     piece->pos.y = 0; 
    ++piece->pos.y; 
} 

void drawWell(char wellMap[WELLSIZEX][WELLSIZEY]) { 
    int y, x; 
    for(y = 0; y < WELLSIZEY; ++y) 
     for(x = 0; x < WELLSIZEX; ++x) 
      mvaddch(y, x, wellMap[x][y]); 

    for(y = 0; y < WELLSIZEY; ++y) { 
     mvaddch(y,   0, '|'); 
     mvaddch(y, WELLSIZEX, '|'); 
    } 

    for(x = 0; x <= WELLSIZEX; ++x) { 
     mvaddch(  0, x, '-'); 
     mvaddch(WELLSIZEY, x, '-'); 
    } 
} 

void drawPiece(struct piece piece) { 
    int x, y; 
    for(y = 0; y < MAPSIZEY; ++y) 
     for(x = 0; x < MAPSIZEX; ++x) 
      mvaddch(piece.pos.y + y, piece.pos.x + x, piece.currentMap[piece.rotation][y][x]); 
} 

int main(void) { 
    struct piece piece; 
    char wellMap[WELLSIZEX][WELLSIZEY]; 

    initscr(); 
    cbreak(); 
    curs_set(FALSE); 
    nodelay(stdscr, TRUE); 
    keypad(stdscr, TRUE); 

    inits(&piece, wellMap); 
    while(1) { 
     clear(); 
     /* 
     if(isCollision) { 
      blit(); 
      getNewPiece(); 
      piece.pos.y = 0; 
      piece.pos.x = 3; 
     } 
     */ 
     updatePiece(&piece, getch()); 
     drawWell(wellMap); 
     drawPiece(piece); 
     mvprintw(2, 12, "l %d/dn %d/r %d/pce %d/rot %d", 
       piece.leftColumn, piece.bottomRow, piece.rightColumn, 
       piece.type, piece.rotation); 
     refresh(); 
     usleep(DELAY); 
    } 
    return 0; 
} 

回答

5

您正在使用

char currentMap[4][MAPSIZEX][MAPSIZEY]; 

場。

同時你正在做

strcpy(piece->currentMap[0][0], "...."); 

之類的東西。

由於零終結符,strcpy()實際上會寫入5(不是4)個字節。由於在currentMap之後有'type'字段,所以在那裏得到零('type'中的第一個字節被覆蓋)。

爲piece-> currentMap [i] [j]使用memcpy()或分配超過4個字節。

+0

*弓* 哦,哇。今天我學到了。 – plewh

1

MAPSIZEY4,但要複製5個字符到每個那些陣列(與strcpy()副本的四個字符,你可以看到加空終止複製串".X..")。

這可能是最後的空終結符被改寫type值的第一個字節,如果你有一個小端機器,這將的type最低顯著字節設置爲零。