分享一个蛋疼的俄罗斯方块小游戏
分享一个蛋疼的俄罗斯方块小游戏
- 空间
转载请注明出处。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);
}
分享一个蛋疼的俄罗斯方块小游戏相关推荐
- 分享一个c++连线小游戏
前言 想看正文的请跳过.热衷小游戏的我又回来了!上次准备给飞机大战小游戏升级,发现写的一坨,难维护拓展,吸取上次教训,这次的清爽多啦!(抽时间把飞机大战重写,再加上联机功能吧),分享给感兴趣的小伙伴, ...
- 分享一个好玩的JS小游戏
前言 一个js的忍者小游戏 话不多说 如图所示 简单好玩 打发时间 代码 HTML <!DOCTYPE html> <html lang="en"> < ...
- 开发一个简易的俄罗斯方块小游戏
完整代码如下: import pygame import random import sys# 游戏设置 WINDOW_WIDTH = 400 WINDOW_HEIGHT = 500 GRID_WID ...
- 基于stm32、0.96寸OLED实现的俄罗斯方块小游戏(详细源码注释)
概述:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的俄罗斯方块小游戏.项目源码地址:点击下载. 硬件要求: 普通摇杆,两个电位器和一个开关组成,左右摇动控制一个电 ...
- javascript俄罗斯方块小游戏
任务要求 用javascript实现一个经典的"俄罗斯方块小游戏" 要求:能计分,有不同关卡(速度不同),有高分榜, chrome 30+以上浏览器能正常玩,主流android,i ...
- 3d游戏编程大师技巧 源代码_C/C++编程入门基础系列:俄罗斯方块小游戏制作,直接源代码分享...
这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph( ...
- 回归前端学习第26天-实现俄罗斯方块小游戏9(实现单机版,一个计时带干扰的单机版俄罗斯方块小游戏完成)
最终完善单机版俄罗斯方块小游戏,增加干扰功能--每10秒增加一行 增加干扰功能 game.js中加入addBotLine函数 local.js中加入 增加干扰功能 game.js中加入addBotLi ...
- c++ 小游戏_C/C++编程新手入门基础系列:俄罗斯方块小游戏制作源代码
这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下. 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph ...
- C/C++编程新手入门基础系列:俄罗斯方块小游戏制作源代码
这篇文章主要为大家详细介绍了C语言实现俄罗斯方块小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph( ...
最新文章
- 正面交锋!另类“竞赛”探索大脑的意识起源
- Python实现目录文件的全量和增量备份
- 一种新的穿透防火墙的数据传输技术
- P1101 单词方阵(DFS)
- 操作系统学习之用C语言模拟CLOCK算法
- php 检测 变量是否设置,php如何判断变量是否有设置的函数
- 学python能做什么-学Python后到底能干什么?网友:我太难了
- SQL ALTER TABLE 语句在项目中的使用
- mongodb基础操作
- java上下文的作用_Spring中的应用程序上下文有什么作用? - java
- 有关于FireBug和FirePath安装和使用-学习笔记
- 图解大数据 | Spark机器学习(下)—建模与超参调优
- 基于Unity3D的语音转文字功能的实现
- Win10系统下的MSCOMCT2.OCX, THREED32.OCX等控件安装方法
- c语言kbhit函数头文件,有没有办法在标准C中替换kbhit()和getch()函数?
- vue-pdf 打印文字空白、每一页多一个空白页、电子签章不显示
- sk_buff属性详解
- 下载MySQL并创建桌面数据库_桌面数据库下载_桌面数据库软件最新版下载 - 全方位下载手机版...
- 多平台专业的 OCR 图文精准识别工具!便宜又好用! - 极度扫描
- 「独立思考」的背后是一个残酷的世界
热门文章
- Reporting Services Internal Error(诡异的问题)-【转载】
- (1)vmware安装ubuntu13.10之后无法进入桌面;(2)ubuntu13.10无法显示eclipse的下拉菜单...
- exchange2010 取消OWA内更改密码选项
- 解决hibernate向mysql插入中文乱码问题
- 戴文的Linux内核专题:07内核配置(3)
- win8系统下用VMware虚拟机启动Windows Server 2008报错问题解决方法
- FileSystemObject ADO WScript.Shell
- CISA提醒:UPS联网设备正遭攻击
- exchange2013卸载
- alpine(Go环境)Docker基础镜像制作