分享一个蛋疼的俄罗斯方块小游戏

  • 空间

转载请注明出处。http://www.cnblogs.com/dave_cn/

我在Ubuntu 10.04下测试过,可以正常运行。不过界面让人蛋疼。

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

sudo apt-get install libncurses5-dev  ubuntu安装ncurses库

/***************************************

*

* 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;

while (checkStop(gwin) != 0) {

++((gwin->pos).x);

ret = 1;

}

break;

case 'd':

++((gwin->pos).x);

while ((n = checkBorder(gwin)) != 0)

(gwin->pos).x += n;

while (checkStop(gwin) != 0) {

--((gwin->pos).x);

ret = 1;

}

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);

}

收藏于 2015-01-12
来自于百度空间
文章有问题?点击这里反馈给我们

分享一个蛋疼的俄罗斯方块小游戏相关推荐

  1. 分享一个c++连线小游戏

    前言 想看正文的请跳过.热衷小游戏的我又回来了!上次准备给飞机大战小游戏升级,发现写的一坨,难维护拓展,吸取上次教训,这次的清爽多啦!(抽时间把飞机大战重写,再加上联机功能吧),分享给感兴趣的小伙伴, ...

  2. 分享一个好玩的JS小游戏

    前言 一个js的忍者小游戏 话不多说 如图所示 简单好玩 打发时间 代码 HTML <!DOCTYPE html> <html lang="en"> < ...

  3. 开发一个简易的俄罗斯方块小游戏

    完整代码如下: import pygame import random import sys# 游戏设置 WINDOW_WIDTH = 400 WINDOW_HEIGHT = 500 GRID_WID ...

  4. 基于stm32、0.96寸OLED实现的俄罗斯方块小游戏(详细源码注释)

    概述:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的俄罗斯方块小游戏.项目源码地址:点击下载. 硬件要求: 普通摇杆,两个电位器和一个开关组成,左右摇动控制一个电 ...

  5. javascript俄罗斯方块小游戏

    任务要求 用javascript实现一个经典的"俄罗斯方块小游戏" 要求:能计分,有不同关卡(速度不同),有高分榜, chrome 30+以上浏览器能正常玩,主流android,i ...

  6. 3d游戏编程大师技巧 源代码_C/C++编程入门基础系列:俄罗斯方块小游戏制作,直接源代码分享...

    这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph( ...

  7. 回归前端学习第26天-实现俄罗斯方块小游戏9(实现单机版,一个计时带干扰的单机版俄罗斯方块小游戏完成)

    最终完善单机版俄罗斯方块小游戏,增加干扰功能--每10秒增加一行 增加干扰功能 game.js中加入addBotLine函数 local.js中加入 增加干扰功能 game.js中加入addBotLi ...

  8. c++ 小游戏_C/C++编程新手入门基础系列:俄罗斯方块小游戏制作源代码

    这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下. 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph ...

  9. C/C++编程新手入门基础系列:俄罗斯方块小游戏制作源代码

    这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph( ...

最新文章

  1. 正面交锋!另类“竞赛”探索大脑的意识起源
  2. Python实现目录文件的全量和增量备份
  3. 一种新的穿透防火墙的数据传输技术
  4. P1101 单词方阵(DFS)
  5. 操作系统学习之用C语言模拟CLOCK算法
  6. php 检测 变量是否设置,php如何判断变量是否有设置的函数
  7. 学python能做什么-学Python后到底能干什么?网友:我太难了
  8. SQL ALTER TABLE 语句在项目中的使用
  9. mongodb基础操作
  10. java上下文的作用_Spring中的应用程序上下文有什么作用? - java
  11. 有关于FireBug和FirePath安装和使用-学习笔记
  12. 图解大数据 | Spark机器学习(下)—建模与超参调优
  13. 基于Unity3D的语音转文字功能的实现
  14. Win10系统下的MSCOMCT2.OCX, THREED32.OCX等控件安装方法
  15. c语言kbhit函数头文件,有没有办法在标准C中替换kbhit()和getch()函数?
  16. vue-pdf 打印文字空白、每一页多一个空白页、电子签章不显示
  17. sk_buff属性详解
  18. 下载MySQL并创建桌面数据库_桌面数据库下载_桌面数据库软件最新版下载 - 全方位下载手机版...
  19. 多平台专业的 OCR 图文精准识别工具!便宜又好用! - 极度扫描
  20. 「独立思考」的背后是一个残酷的世界

热门文章

  1. Reporting Services Internal Error(诡异的问题)-【转载】
  2. (1)vmware安装ubuntu13.10之后无法进入桌面;(2)ubuntu13.10无法显示eclipse的下拉菜单...
  3. exchange2010 取消OWA内更改密码选项
  4. 解决hibernate向mysql插入中文乱码问题
  5. 戴文的Linux内核专题:07内核配置(3)
  6. win8系统下用VMware虚拟机启动Windows Server 2008报错问题解决方法
  7. FileSystemObject ADO WScript.Shell
  8. CISA提醒:UPS联网设备正遭攻击
  9. exchange2013卸载
  10. alpine(Go环境)Docker基础镜像制作