我有一个奇怪的问题,谷歌和搜索无法帮助。这可能是非常简单的事情,但是我已经打了几个小时而且不能坚持下去。
我正在使用Ncurses(使用Ubuntu)在C中使用俄罗斯方块。
我的main函数调用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->类型的内容似乎没有改变。
所以我跳进了gdb,看看发生了什么。一开始一切都在游泳;在stdin检测到'p',piece->类型确实递增,然后调用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-&gt; type就设置为0。
我不知道为什么。 Piece通过引用传递,因此它不应该是范围问题。使用开关或一堆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;
}
答案 0 :(得分:5)
您正在使用
char currentMap[4][MAPSIZEX][MAPSIZEY];
字段。
同时你正在做
strcpy(piece->currentMap[0][0], "....");
和那样的东西。
strcpy()实际上写了5个(不是4个)字节,因为零终止符。
由于你在currentMap之后就有'type'字段,你得到零('type'中的第一个字节被覆盖)。
对于piece-&gt; currentMap [i] [j]使用memcpy()或分配超过4个字节。
答案 1 :(得分:1)
MAPSIZEY
是4
,但您要将5个字符复制到每个数组中(复制字符串".X.."
并strcpy()
复制您可以看到的四个字符加上null终止符)。
最后一个空终止符可能会覆盖type
值的第一个字节,如果你有一个little-endian机器会将type
的最低有效字节设置为零。< / p>