[原创]贡献一个蛋疼的俄罗斯方块小游戏
时间:2010-07-28
来源:互联网
本帖最后由 dave_cn 于 2010-07-28 20:20 编辑
我在Ubuntu 10.04下测试过,可以正常运行。不过界面让人蛋疼。
代码用到了NCURSES库。编译的时候链一下ncurses库就可以了,如:
cc -Wall -O2 -o c01 file.c -lncurses
界面:
还请各位多多指教。
复制代码
我在Ubuntu 10.04下测试过,可以正常运行。不过界面让人蛋疼。

代码用到了NCURSES库。编译的时候链一下ncurses库就可以了,如:
cc -Wall -O2 -o c01 file.c -lncurses
界面:

还请各位多多指教。
- /***************************************
- *
- * TETRIS
- *
- * author: dave
- * date : 2010/07/28
- *
- ***************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <ncurses.h>
-
- #define TETRADS_LEN 4
- #define GAMEWIN_YLEN 20
- #define GAMEWIN_XLEN 10
- #define GAMEWIN_Y 1
- #define GAMEWIN_X 2
- #define INFOWIN_YLEN 10
- #define INFOWIN_XLEN 10
- #define INFOWIN_Y GAMEWIN_Y
- #define INFOWIN_X (GAMEWIN_X + GAMEWIN_XLEN*2 + 5)
- #define PIC_BLOCK '#'
- #define PIC_NULL ' '
-
- #define _X(x) ((x)*2)
-
- #define BASEWIN \
- WINDOW *win; \
- void (*init)(); \
- void (*show)();
-
- #define EXCHANGE_XY(_pos) \
- do { \
- (_pos).x = (_pos).y + (_pos).x; \
- (_pos).y = (_pos).x - (_pos).y; \
- (_pos).x -= (_pos).y; \
- } while (0)
-
- #define EXCHANGE_2Y(_pos) \
- (_pos).y = 2 - (_pos).y
-
- #define COPY_TETRADS(_dest, _src) \
- memcpy(&(_dest), &(_src), sizeof(Tetrads))
-
- #define TETRISNEW(_p, _t) \
- do { \
- (_p) = (_t*)malloc(sizeof(_t)); \
- (_p)->init = init##_t; \
- (_p)->show = show##_t; \
- } while (0)
-
- #define TETRISDEL(_p) \
- do { \
- delwin(_p->win); \
- free(_p); \
- } while (0)
-
- /* 俄罗斯方块的7种方块(Tetromino) */
- typedef enum {
- TETRADS_S = 0,
- TETRADS_Z,
- TETRADS_L,
- TETRADS_J,
- TETRADS_O,
- TETRADS_T,
- TETRADS_I,
-
- TETRADS_MAX
- } ETetrads;
-
- typedef enum {
- DIR_UP = 0,
- DIR_DOWN,
- DIR_LEFT,
- DIR_RIGHT,
-
- DIR_MAX
- } EDirction;
-
- typedef enum {
- TETRIS_STATE_NEW,
- TETRIS_STATE_MOVE,
- TETRIS_STATE_STOP,
-
- TETRIS_STATE_MAX,
- } ETetrisState;
-
- typedef struct {
- int y;
- int x;
- } Point;
-
- typedef struct {
- ETetrads type;
- Point blocks[TETRADS_LEN];
- } Tetrads;
-
- /*** BEGIN : 界面显示 ***/ /* 将界面显示与数据处理分离 */
- typedef struct _BaseWin {
- /**
- * WINDOW *win;
- * void (*init)();
- * void (*show)();
- */
- BASEWIN
- } BaseWin;
-
- typedef struct _GameWin {
- /**
- * WINDOW *win;
- * void (*init)();
- * void (*show)();
- */
- BASEWIN
-
- char background[GAMEWIN_YLEN][GAMEWIN_XLEN];
- char matrix[GAMEWIN_YLEN][GAMEWIN_XLEN];
- int level;
- Point pos;
- Tetrads curTetrads;
- } GameWin;
-
- typedef struct _InfoWin {
- /**
- * WINDOW *win;
- * void (*init)();
- * void (*show)();
- */
- BASEWIN
-
- int score;
- int level;
- Tetrads nextTetrads;
- } InfoWin;
-
- void tetrisPrint(WINDOW *win, Point pos, Point block, char chr);
-
- void initGameWin(GameWin* _self)
- {
- _self->win = newwin(GAMEWIN_YLEN + 2, _X(GAMEWIN_XLEN) + 1, GAMEWIN_Y, GAMEWIN_X);
- box(_self->win, 0, 0);
- mvwprintw(_self->win, 0, (_X(GAMEWIN_XLEN) + 2)/2 - 3, "TETRIS");
- wrefresh(_self->win);
-
- memset(_self->background, PIC_NULL, GAMEWIN_YLEN * GAMEWIN_XLEN);
- memset(_self->matrix, PIC_NULL, GAMEWIN_YLEN * GAMEWIN_XLEN);
-
- _self->pos = (Point){1, GAMEWIN_XLEN/2};
- _self->level = 0;
- }
-
- void initInfoWin(InfoWin* _self)
- {
- _self->win = newwin(INFOWIN_YLEN, _X(GAMEWIN_XLEN), INFOWIN_Y, INFOWIN_X);
- box(_self->win, 0, 0);
- mvwprintw(_self->win, 0, _X(GAMEWIN_XLEN)/2 - 2, "INFO");
- mvwprintw(_self->win, 7, 2, "SCORE: 0");
- mvwprintw(_self->win, 8, 2, "LEVEL: 0");
- wrefresh(_self->win);
-
- _self->score = 0;
- _self->level = 0;
- }
-
- void showGameWin(GameWin* _self)
- {
- int y = 0;
- int x = 0;
-
- for (y = 0; y < GAMEWIN_YLEN; ++y)
- for (x = 0; x < GAMEWIN_XLEN; ++x)
- tetrisPrint(_self->win, (Point){0, 0}, (Point){y, x}, (_self->background)[y][x]);
-
- for (y = 0; y < GAMEWIN_YLEN; ++y)
- for (x = 0; x < GAMEWIN_XLEN; ++x)
- tetrisPrint(_self->win, (Point){0, 0}, (Point){y, x}, (_self->matrix)[y][x]);
-
- for (x = 0; x < TETRADS_LEN; ++x)
- tetrisPrint(_self->win, (Point){(_self->pos).y, (_self->pos).x}, (_self->curTetrads).blocks[x], PIC_BLOCK);
-
- wrefresh(_self->win);
- }
-
- void showInfoWin(InfoWin* _self)
- {
- int i = 0;
-
- mvwprintw(_self->win, 2, _X(INFOWIN_XLEN/2 - 2), " ");
- mvwprintw(_self->win, 3, _X(INFOWIN_XLEN/2 - 2), " ");
- mvwprintw(_self->win, 4, _X(INFOWIN_XLEN/2 - 2), " ");
- mvwprintw(_self->win, 5, _X(INFOWIN_XLEN/2 - 2), " ");
- mvwprintw(_self->win, 6, _X(INFOWIN_XLEN/2 - 2), " ");
-
- for (i = 0; i < TETRADS_LEN; ++i)
- tetrisPrint(_self->win, (Point){2, INFOWIN_XLEN/2 - 2}, _self->nextTetrads.blocks[i], PIC_BLOCK);
-
- mvwprintw(_self->win, INFOWIN_YLEN - 3, 2, "SCORE: %d", _self->score);
- mvwprintw(_self->win, INFOWIN_YLEN - 2, 2, "LEVEL: %d", _self->level);
-
- wrefresh(_self->win);
- }
- /*** END : 界面显示 ***/
-
- /*** 函数声明 ***/
- void newTetrads(Tetrads *tetrads);
- void initTetrads(Tetrads *tetrads);
- void spinTetrads(Tetrads *tetrads);
- int runTetris(GameWin *gwin);
- int checkBorder(GameWin *gwin);
- int checkStop(GameWin *gwin);
- int checkOver(GameWin *gwin);
- int checkClean(GameWin *gwin);
- void refreshMatrix(GameWin *gwin);
- int genRandom(int max);
-
- int main()
- {
- /* init ncurses screen */
- initscr();
- raw();
- noecho();
- keypad(stdscr, TRUE);
- curs_set(0);
- refresh();
-
- /* 初始化界面 */
- GameWin *gwin;
- InfoWin *iwin;
-
- TETRISNEW(gwin, GameWin);
- TETRISNEW(iwin, InfoWin);
-
- gwin->init(gwin);
- iwin->init(iwin);
-
- /* Tetris的处理使用简单的状态机实现 */
- int f_end = 0;
- int state = TETRIS_STATE_NEW;
-
- newTetrads(&(iwin->nextTetrads));
-
- while (!f_end) {
- switch (state) {
- case TETRIS_STATE_NEW:
- COPY_TETRADS(gwin->curTetrads, iwin->nextTetrads);
- gwin->pos = (Point){1, 4};
- newTetrads(&(iwin->nextTetrads));
-
- iwin->show(iwin);
-
- state = TETRIS_STATE_MOVE;
- break;
-
- case TETRIS_STATE_MOVE:
- gwin->show(gwin);
-
- switch (runTetris(gwin)) {
- case -1:
- goto END;
- break;
- case 0:
- break;
- case 1:
- state = TETRIS_STATE_STOP;
- break;
- default:
- break;
- }
-
- break;
-
- case TETRIS_STATE_STOP:
- refreshMatrix(gwin);
- iwin->score = checkClean(gwin);
- state = TETRIS_STATE_NEW;
- break;
-
- default :
- f_end = 1;
- break;
- }
- }
-
- END:
- mvwprintw(gwin->win, GAMEWIN_YLEN/2 - 2, 5, "GAME OVER!!!");
- mvwprintw(gwin->win, GAMEWIN_YLEN/2, 4, "Press any key");
- mvwprintw(gwin->win, GAMEWIN_YLEN/2 + 1, 6, "to quit...");
- wrefresh(gwin->win);
-
- getch();
-
- TETRISDEL(iwin);
- TETRISDEL(gwin);
- endwin();
-
- return 0;
- }
-
- void tetrisPrint(WINDOW *win, Point pos, Point block, char chr)
- {
- mvwaddch(win, pos.y + block.y + 1, (pos.x + block.x) * 2 + 1, chr);
- }
-
- void newTetrads(Tetrads *tetrads)
- {
- tetrads->type = genRandom(TETRADS_MAX);
-
- initTetrads(tetrads);
-
-
- int spin = genRandom(DIR_MAX);
- int i = 0;
- for (; i <= spin; ++i) {
- spinTetrads(tetrads);
- }
- }
-
- void initTetrads(Tetrads *tetrads)
- {
- switch (tetrads->type) {
- case TETRADS_S:
- tetrads->blocks[0] = (Point){2, 0};
- tetrads->blocks[1] = (Point){2, 1};
- tetrads->blocks[2] = (Point){1, 1};
- tetrads->blocks[3] = (Point){1, 2};
- break;
-
- case TETRADS_Z:
- tetrads->blocks[0] = (Point){1, 0};
- tetrads->blocks[1] = (Point){1, 1};
- tetrads->blocks[2] = (Point){2, 1};
- tetrads->blocks[3] = (Point){2, 2};
- break;
-
- case TETRADS_L:
- tetrads->blocks[0] = (Point){2, 0};
- tetrads->blocks[1] = (Point){2, 1};
- tetrads->blocks[2] = (Point){1, 1};
- tetrads->blocks[3] = (Point){0, 1};
- break;
-
- case TETRADS_J:
- tetrads->blocks[0] = (Point){0, 0};
- tetrads->blocks[1] = (Point){1, 0};
- tetrads->blocks[2] = (Point){1, 1};
- tetrads->blocks[3] = (Point){1, 2};
- break;
-
- case TETRADS_O:
- tetrads->blocks[0] = (Point){0, 0};
- tetrads->blocks[1] = (Point){0, 1};
- tetrads->blocks[2] = (Point){1, 0};
- tetrads->blocks[3] = (Point){1, 1};
- break;
-
- case TETRADS_T:
- tetrads->blocks[0] = (Point){0, 1};
- tetrads->blocks[1] = (Point){1, 0};
- tetrads->blocks[2] = (Point){1, 1};
- tetrads->blocks[3] = (Point){1, 2};
- break;
-
- case TETRADS_I:
- tetrads->blocks[0] = (Point){0, 1};
- tetrads->blocks[1] = (Point){1, 1};
- tetrads->blocks[2] = (Point){2, 1};
- tetrads->blocks[3] = (Point){3, 1};
- break;
-
- default:
- break;
- }
- }
-
- /**
- * 旋转Tetrads
- */
- void spinTetrads(Tetrads *tetrads)
- {
- int i = 0;
-
- switch (tetrads->type) {
- case TETRADS_O:
- break;
-
- case TETRADS_I:
- /* x,y互换 */
- for (i = 0; i < TETRADS_LEN; ++i)
- EXCHANGE_XY(tetrads->blocks[i]);
- break;
-
- default:
- for (i = 0; i < TETRADS_LEN; ++i)
- EXCHANGE_XY(tetrads->blocks[i]);
-
- for (i = 0; i < TETRADS_LEN; ++i)
- EXCHANGE_2Y(tetrads->blocks[i]);
-
- break;
- }
- }
-
- /**
- * Return:
- * -1 game over
- * 0 continue
- * 1 stop
- */
- int runTetris(GameWin *gwin)
- {
- int ret = 0;
-
- fd_set fset;
-
- FD_ZERO(&fset);
- FD_SET(0, &fset);
-
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 500000 - 10000 * gwin->level;
-
- int fd = -1;
- if ((fd = select(1, &fset, NULL, NULL, &timeout)) <= 0) {
- ++((gwin->pos).y);
- while (checkStop(gwin) != 0) {
- --((gwin->pos).y);
- ret = 1;
- }
-
- if (ret == 1) {
- if (checkOver(gwin))
- return -1;
-
- return 1;
- }
-
- return 0;
- }
-
- Tetrads tmptetrads;
- char ch;
- int n = 0;
- switch (ch = getch()) {
- case 'w':
- COPY_TETRADS(tmptetrads, gwin->curTetrads);
- spinTetrads(&gwin->curTetrads);
-
- while ((n = checkBorder(gwin)) != 0)
- (gwin->pos).x += n;
-
- while (checkStop(gwin) != 0) {
- --((gwin->pos).y);
- ret = 1;
- }
-
- return ret;
-
- case 's':
- ++((gwin->pos).y);
- while (checkStop(gwin) != 0) {
- --((gwin->pos).y);
- ret = 1;
- }
-
- if (ret == 1) {
- if (checkOver(gwin))
- return -1;
-
- return 1;
- }
-
- return 0;
-
- case 'a':
- --((gwin->pos).x);
- while ((n = checkBorder(gwin)) != 0)
- (gwin->pos).x += n;
- break;
-
- case 'd':
- ++((gwin->pos).x);
- while ((n = checkBorder(gwin)) != 0)
- (gwin->pos).x += n;
- break;
-
- default:
- break;
- }
-
- return 0;
- }
-
- /**
- * 检查是否达到边线
- */
- int checkBorder(GameWin *gwin)
- {
- int i = 0;
- int n = 0;
- for (i = 0; i < TETRADS_LEN; ++i) {
- if ((n = ((gwin->pos).x + (gwin->curTetrads).blocks[i].x)) < 0)
- return -n;
-
- if ((n = ((gwin->pos).x + (gwin->curTetrads).blocks[i].x)) > GAMEWIN_XLEN - 1)
- return GAMEWIN_XLEN - 1 - n;
- }
-
- return 0;
- }
-
- /**
- * 检查是否停止
- */
- int checkStop(GameWin *gwin)
- {
- int i = 0;
- for (i = 0; i < TETRADS_LEN; ++i)
- if (gwin->matrix[(gwin->pos).y + (gwin->curTetrads).blocks[i].y][(gwin->pos).x + (gwin->curTetrads).blocks[i].x] == PIC_BLOCK
- || ((gwin->pos).y + (gwin->curTetrads).blocks[i].y) >= GAMEWIN_YLEN)
- return 1;
-
- return 0;
- }
-
- /**
- * 检查是否游戏结束
- */
- int checkOver(GameWin *gwin)
- {
- int i = 0;
- for (i = 0; i < TETRADS_LEN; ++i)
- if ((gwin->pos).y <= 0)
- return 1;
-
- return 0;
- }
-
- /**
- * 检查是否需要清楚一行
- */
- int checkClean(GameWin *gwin)
- {
- char bline[GAMEWIN_XLEN];
- memset(bline, PIC_BLOCK, GAMEWIN_XLEN);
-
- int i = 0;
- int num = 0;
- int score = 0;
- for (i = 0; i < TETRADS_LEN; ++i) {
- num = (gwin->pos).y + (gwin->curTetrads).blocks[i].y;
- if (strncmp(gwin->matrix[num], bline, GAMEWIN_XLEN) == 0) {
- score += 10;
- for (; num > 0; --num)
- memcpy(gwin->matrix[num], gwin->matrix[num-1], GAMEWIN_XLEN);
- }
- }
-
- return score;
- }
-
- void refreshMatrix(GameWin *gwin)
- {
- int i = 0;
- for (i = 0; i < TETRADS_LEN; ++i)
- gwin->matrix[(gwin->pos).y + (gwin->curTetrads).blocks[i].y][(gwin->pos).x + (gwin->curTetrads).blocks[i].x] = PIC_BLOCK;
- }
-
- /**
- * 返回0~max-1的一个随机数
- */
- int genRandom(int max)
- {
- srandom((int)time(NULL));
- return (random() % max);
- }
作者: dave_cn 发布时间: 2010-07-28
不错,支持。
不过用printf也可以的
不过用printf也可以的

作者: okocha-jay 发布时间: 2010-07-28
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28