2

私はグーグルとSO検索が助けることができない奇妙な問題を抱えています。それはおそらく本当に単純なことですが、私は数時間スラッシングしていて、それを理解することができません。

Ncursesを使用して(Ubuntuを使用して)Cでテトリスを処理しています。

私のメイン関数は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」が入力されていることを検出しています。それを使用して、カウンターを自由にインクリメントします。

ただし、ピースは1回だけ回転するように見えます。mvprintw()を使用すると、piece->typeの内容は変更されていないように見えます。

そこで、何が起こっているのかを知るためにgdbに飛び込みました。最初はすべてが泳ぎます。'p'はstdinで検出され、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文字配列を変更します。すべてが正常にコピーされますが、関数が終了するとすぐにpiece->typeが0に設定されます。

理由はわかりません。ピースは参照によって渡されるため、スコープの問題にはなりません。スイッチまたは一連のif/elsesを使用しても効果はありません。breakまたはreturnを使用しても効果はありません。

それはおそらく本当に単純でばかげたものですが、独学のコーダーとして私は困惑しています。

助けていただければ幸いです。コード全体は次のとおりです(自由に批評してください!):

#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;
}
4

2 に答える 2

5

使用しています

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

分野。

同時にあなたはやっています

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

そしてそのようなもの。

strcpy()は、ターミネータがゼロであるため、実際には5バイト(4バイトではない)を書き込みます。

currentMapの直後に「type」フィールドがあるため、そこにゼロが表示されます(「type」の最初のバイトが上書きされます)。

piece-> currentMap [i] [j]にmemcpy()を使用するか、4バイト以上を割り当てます。

于 2012-05-30T12:20:01.553 に答える
1

MAPSIZEY4ですが、これらの配列のそれぞれに5文字をコピーしています(文字列".X.."strcpy()コピーすると、表示される4文字とヌルターミネータがコピーされます)。

最後のヌルターミネータがtype値の最初のバイトを上書きしている可能性があります。リトルエンディアンのマシンを使用している場合は、の最下位バイトtypeをゼロに設定します。

于 2012-05-30T12:22:04.173 に答える