#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <conio.h>
#include <stdlib.h>
char gcText[] = " 1LJTSZ#";
struct tetris {
int _pool[][], (*pool)[], tmap[][][];
int x, y, s, st, t;
}gt; void trsInit() {
int sp[][] = {{,},{,,,},{,,,},
{,,,},{,},{,},{,},{-}};
int *p, i, j, b;
for (p = sp[]; *p >= ; ++p) if ( *p == ) *p = p[-];
gt.pool = &gt._pool[];
for (j = ; j < ; ++j)
for (i = ; i < ; ++i)
for (b = ; b < ; ++b)
gt.tmap[j+][i][b] = (sp[j][i] & ) * (j + ),
sp[j][i] >>= ;
memset(gt._pool, -, sizeof(gt._pool));
for (i = ; i < ; ++i)
memset(&gt.pool[i], , sizeof(int[]));
return ;
} int trsCopy(int sp[], int x, int y, int c) {
int i, cx, cy;
for (i = ; i < ; ++i) if (sp[i]) {
cx = x + (i & ), cy = y + (i >> );
if (gt.pool[cx][cy])
{
if (c == )
gt.pool[cx][cy] = ;
else
return ;
} if (c==) gt.pool[cx][cy] = sp[i];
}
return ;
} int trsScene() {
int x, y = ;
COORD pos = {};
gt.s = rand() % + , gt.st = gt.t = ;
gt.x = , gt.y = ;
for (--gt.t; ; Sleep(), --gt.t) {
int k = ;
while (kbhit()) {
k = getch();
if (k == ) return ;
if (k == 'A' || k == 'a') {
if (trsCopy(gt.tmap[gt.s][gt.st], gt.x-, gt.y, )) --gt.x;
} else if (k == 'D' || k == 'd') {
if (trsCopy(gt.tmap[gt.s][gt.st], gt.x+, gt.y, )) ++gt.x;
} else if (k == 'W' || k == 'w') {
if (trsCopy(gt.tmap[gt.s][(gt.st+) % ], gt.x, gt.y, ))
gt.st = (gt.st+) % ;
}
}
if (k == 'S' || k == 's' || gt.t < ) {
if (trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y+, ))++gt.y,gt.t=;
else {
trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, );
for (--y; y > ; --y) {
for (x = ; gt.pool[x][y] > ; ++x);
if (gt.pool[x][y] < )
for (k = y++; k > ; --k)
for (x = ; gt.pool[x][] >= ; ++x)
gt.pool[x][k] = gt.pool[x][k-];
}
return ;
}
}
trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, );
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
for (y = ; gt.pool[][y] >= ; ++y,putchar()) {
for (x = ; gt.pool[x][] >= ; ++x) {
putchar(gcText[gt.pool[x][y]]);
}
}
trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, );
}
} int main() {
srand((unsigned)time(NULL));
for (trsInit(); trsScene(); );
return ;
}

精美版

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <windows.h> #ifdef _MSC_VER // M$的编译器要给予特殊照顾
#if _MSC_VER <= 1200 // VC6及以下版本
#error 你是不是还在用VC6?!
#else // VC6以上版本
#if _MSC_VER >= 1600 // 据说VC10及以上版本有stdint.h了
#include <stdint.h>
#else // VC10以下版本,自己定义int8_t和uint16_t
typedef signed char int8_t;
typedef unsigned short uint16_t;
#endif
#ifndef __cplusplus // 据说VC都没有stdbool.h,不用C++编译,自己定义bool
typedef int bool;
#define true 1
#define false 0
#endif
#endif
#else // 其他的编译器都好说
#include <stdint.h>
#ifndef __cplusplus // 不用C++编译,需要stdbool.h里的bool
#include <stdbool.h>
#endif
#endif // =============================================================================
// 7种方块的4旋转状态(4位为一行)
static const uint16_t gs_uTetrisTable[][] = { { 0x00F0U, 0x2222U, 0x00F0U,
0x2222U }, // I型
{ 0x0072U, 0x0262U, 0x0270U, 0x0232U }, // T型
{ 0x0223U, 0x0074U, 0x0622U, 0x0170U }, // L型
{ 0x0226U, 0x0470U, 0x0322U, 0x0071U }, // J型
{ 0x0063U, 0x0264U, 0x0063U, 0x0264U }, // Z型
{ 0x006CU, 0x0462U, 0x006CU, 0x0462U }, // S型
{ 0x0660U, 0x0660U, 0x0660U, 0x0660U } // O型
}; // =============================================================================
// 初始状态的游戏池
// 每个元素表示游戏池的一行,下标大的是游戏池底部
// 两端各置2个1,底部2全置为1,便于进行碰撞检测
// 这样一来游戏池的宽度为12列
// 如果想要传统的10列,只需多填两个1即可(0xE007),当然显示相关部分也要随之改动
// 当某个元素为0xFFFFU时,说明该行已被填满
// 顶部4行用于给方块,不显示出来
// 再除去底部2行,显示出来的游戏池高度为22行
static const uint16_t gs_uInitialTetrisPool[] = { 0xC003U, 0xC003U, 0xC003U,
0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,
0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,
0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xFFFFU,
0xFFFFU }; #define COL_BEGIN 2
#define COL_END 14
#define ROW_BEGIN 4
#define ROW_END 26 // =============================================================================
typedef struct TetrisManager // 这个结构体存储游戏相关数据
{
uint16_t pool[]; // 游戏池
int8_t x; // 当前方块x坐标,此处坐标为方块左上角坐标
int8_t y; // 当前方块y坐标
int8_t type[]; // 当前、下一个和下下一个方块类型
int8_t orientation[]; // 当前、下一个和下下一个方块旋转状态
unsigned score; // 得分
unsigned erasedCount[]; // 消行数
unsigned erasedTotal; // 消行总数
unsigned tetrisCount[]; // 各方块数
unsigned tetrisTotal; // 方块总数
bool dead; // 挂
} TetrisManager; // =============================================================================
typedef struct TetrisControl // 这个结构体存储控制相关数据
{
bool pause; // 暂停
bool clockwise; // 旋转方向:顺时针为true
int8_t direction; // 移动方向:0向左移动 1向右移动
// 游戏池内每格的颜色
// 由于此版本是彩色的,仅用游戏池数据无法存储颜色信息
// 当然,如果只实现单色版的,就没必要用这个数组了
int8_t color[][];
} TetrisControl; HANDLE g_hConsoleOutput; // 控制台输出句柄 // =============================================================================
// 函数声明
// 如果使用全局变量方式实现,就没必要传参了
void initGame(TetrisManager *manager, TetrisControl *control); // 初始化游戏
void restartGame(TetrisManager *manager, TetrisControl *control); // 重新开始游戏
void giveTetris(TetrisManager *manager); // 给一个方块
bool checkCollision(const TetrisManager *manager); // 碰撞检测
void insertTetris(TetrisManager *manager); // 插入方块
void removeTetris(TetrisManager *manager); // 移除方块
void horzMoveTetris(TetrisManager *manager, TetrisControl *control); // 水平移动方块
void moveDownTetris(TetrisManager *manager, TetrisControl *control); // 向下移动方块
void rotateTetris(TetrisManager *manager, TetrisControl *control); // 旋转方块
void dropDownTetris(TetrisManager *manager, TetrisControl *control); // 方块直接落地
bool checkErasing(TetrisManager *manager, TetrisControl *control); // 消行检测
void keydownControl(TetrisManager *manager, TetrisControl *control, int key); // 键按下
void setPoolColor(const TetrisManager *manager, TetrisControl *control); // 设置颜色
void gotoxyWithFullwidth(short x, short y); // 以全角定位
void printPoolBorder(); // 显示游戏池边界
void printTetrisPool(const TetrisManager *manager, const TetrisControl *control); // 显示游戏池
void printCurrentTetris(const TetrisManager *manager,
const TetrisControl *control); // 显示当前方块
void printNextTetris(const TetrisManager *manager); // 显示下一个和下下一个方块
void printScore(const TetrisManager *manager); // 显示得分信息
void runGame(TetrisManager *manager, TetrisControl *control); // 运行游戏
void printPrompting(); // 显示提示信息
bool ifPlayAgain(); // 再来一次 // =============================================================================
// 出处:http://www.oschina.net/code/snippet_255612_16922
// 主函数
int main() {
TetrisManager tetrisManager;
TetrisControl tetrisControl; initGame(&tetrisManager, &tetrisControl); // 初始化游戏
do {
printPrompting(); // 显示提示信息
printPoolBorder(); // 显示游戏池边界
runGame(&tetrisManager, &tetrisControl); // 运行游戏
if (ifPlayAgain()) // 再来一次
{
SetConsoleTextAttribute(g_hConsoleOutput, 0x7);
system("cls"); // 清屏
restartGame(&tetrisManager, &tetrisControl); // 重新开始游戏
} else {
break;
}
} while ();
gotoxyWithFullwidth(, );
CloseHandle(g_hConsoleOutput);
return ;
} // =============================================================================
// 初始化游戏
void initGame(TetrisManager *manager, TetrisControl *control) {
CONSOLE_CURSOR_INFO cursorInfo = { , FALSE }; // 光标信息 g_hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); // 获取控制台输出句柄
SetConsoleCursorInfo(g_hConsoleOutput, &cursorInfo); // 设置光标隐藏
SetConsoleTitleA("俄罗斯方块"); restartGame(manager, control);
} // =============================================================================
// 重新开始游戏
void restartGame(TetrisManager *manager, TetrisControl *control) {
memset(manager, , sizeof(TetrisManager)); // 全部置0 // 初始化游戏池
memcpy(manager->pool, gs_uInitialTetrisPool, sizeof(uint16_t[]));
srand((unsigned) time(NULL )); // 设置随机种子 manager->type[] = rand() % ; // 下一个
manager->orientation[] = rand() & ; manager->type[] = rand() % ; // 下下一个
manager->orientation[] = rand() & ; memset(control, , sizeof(TetrisControl)); // 全部置0 giveTetris(manager); // 给下一个方块
setPoolColor(manager, control); // 设置颜色
} // =============================================================================
// 给一个方块
void giveTetris(TetrisManager *manager) {
uint16_t tetris; manager->type[] = manager->type[]; // 下一个方块置为当前
manager->orientation[] = manager->orientation[]; manager->type[] = manager->type[]; // 下下一个置方块为下一个
manager->orientation[] = manager->orientation[]; manager->type[] = rand() % ; // 随机生成下下一个方块
manager->orientation[] = rand() & ; tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]]; // 当前方块 // 设置当前方块y坐标,保证刚给出时只显示方块最下面一行
// 这种实现使得玩家可以以很快的速度将方块落在不显示出来的顶部4行内
if (tetris & 0xF000) {
manager->y = ;
} else {
manager->y = (tetris & 0xFF00) ? : ;
}
manager->x = ; // 设置当前方块x坐标 if (checkCollision(manager)) // 检测到碰撞
{
manager->dead = true; // 标记游戏结束
} else // 未检测到碰撞
{
insertTetris(manager); // 将当前方块加入游戏池
} ++manager->tetrisTotal; // 方块总数
++manager->tetrisCount[manager->type[]]; // 相应方块数 printNextTetris(manager); // 显示下一个方块
printScore(manager); // 显示得分信息
} // =============================================================================
// 碰撞检测
bool checkCollision(const TetrisManager *manager) {
// 当前方块
uint16_t tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]];
uint16_t dest = ; // 获取当前方块在游戏池中的区域:
// 游戏池坐标x y处小方格信息,按低到高存放在16位无符号数中
dest |= (((manager->pool[manager->y + ] >> manager->x) << 0x0) & 0x000F);
dest |= (((manager->pool[manager->y + ] >> manager->x) << 0x4) & 0x00F0);
dest |= (((manager->pool[manager->y + ] >> manager->x) << 0x8) & 0x0F00);
dest |= (((manager->pool[manager->y + ] >> manager->x) << 0xC) & 0xF000); // 若当前方块与目标区域存在重叠(碰撞),则位与的结果不为0
return ((dest & tetris) != );
} // =============================================================================
// 插入方块
void insertTetris(TetrisManager *manager) {
// 当前方块
uint16_t tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]]; // 当前方块每4位取出,位或到游戏池相应位置,即完成插入方块
manager->pool[manager->y + ] |= (((tetris >> 0x0) & 0x000F) << manager->x);
manager->pool[manager->y + ] |= (((tetris >> 0x4) & 0x000F) << manager->x);
manager->pool[manager->y + ] |= (((tetris >> 0x8) & 0x000F) << manager->x);
manager->pool[manager->y + ] |= (((tetris >> 0xC) & 0x000F) << manager->x);
} // =============================================================================
// 移除方块
void removeTetris(TetrisManager *manager) {
// 当前方块
uint16_t tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]]; // 当前方块每4位取出,按位取反后位与到游戏池相应位置,即完成移除方块
manager->pool[manager->y + ] &=
~(((tetris >> 0x0) & 0x000F) << manager->x);
manager->pool[manager->y + ] &=
~(((tetris >> 0x4) & 0x000F) << manager->x);
manager->pool[manager->y + ] &=
~(((tetris >> 0x8) & 0x000F) << manager->x);
manager->pool[manager->y + ] &=
~(((tetris >> 0xC) & 0x000F) << manager->x);
} // =============================================================================
// 设置颜色
void setPoolColor(const TetrisManager *manager, TetrisControl *control) {
// 由于显示游戏池时,先要在游戏池里判断某一方格有方块才显示相应方格的颜色
// 这里只作设置即可,没必要清除
// 当移动方块或给一个方块时调用 int8_t i, x, y; // 当前方块
uint16_t tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]]; for (i = ; i < ; ++i) {
y = (i >> ) + manager->y; // 待设置的列
if (y > ROW_END) // 超过底部限制
{
break;
}
x = (i & ) + manager->x; // 待设置的行
if ((tetris >> i) & ) // 检测的到小方格属于当前方块区域
{
control->color[y][x] = (manager->type[] | ); // 设置颜色
}
}
} // =============================================================================
// 旋转方块
void rotateTetris(TetrisManager *manager, TetrisControl *control) {
int8_t ori = manager->orientation[]; // 记录原旋转状态 removeTetris(manager); // 移走当前方块 // 顺/逆时针旋转
manager->orientation[] =
(control->clockwise) ? ((ori + ) & ) : ((ori + ) & ); if (checkCollision(manager)) // 检测到碰撞
{
manager->orientation[] = ori; // 恢复为原旋转状态
insertTetris(manager); // 放入当前方块。由于状态没改变,不需要设置颜色
} else {
insertTetris(manager); // 放入当前方块
setPoolColor(manager, control); // 设置颜色
printCurrentTetris(manager, control); // 显示当前方块
}
} // =============================================================================
// 水平移动方块
void horzMoveTetris(TetrisManager *manager, TetrisControl *control) {
int x = manager->x; // 记录原列位置 removeTetris(manager); // 移走当前方块
control->direction == ? (--manager->x) : (++manager->x); // 左/右移动 if (checkCollision(manager)) // 检测到碰撞
{
manager->x = x; // 恢复为原列位置
insertTetris(manager); // 放入当前方块。由于位置没改变,不需要设置颜色
} else {
insertTetris(manager); // 放入当前方块
setPoolColor(manager, control); // 设置颜色
printCurrentTetris(manager, control); // 显示当前方块
}
} // =============================================================================
// 向下移动方块
void moveDownTetris(TetrisManager *manager, TetrisControl *control) {
int8_t y = manager->y; // 记录原行位置 removeTetris(manager); // 移走当前方块
++manager->y; // 向下移动 if (checkCollision(manager)) // 检测到碰撞
{
manager->y = y; // 恢复为原行位置
insertTetris(manager); // 放入当前方块。由于位置没改变,不需要设置颜色
if (checkErasing(manager, control)) // 检测到消行
{
printTetrisPool(manager, control); // 显示游戏池
}
} else {
insertTetris(manager); // 放入当前方块
setPoolColor(manager, control); // 设置颜色
printCurrentTetris(manager, control); // 显示当前方块
}
} // =============================================================================
// 方块直接落地
void dropDownTetris(TetrisManager *manager, TetrisControl *control) {
removeTetris(manager); // 移走当前方块
for (; manager->y < ROW_END; ++manager->y) // 从上往下
{
if (checkCollision(manager)) // 检测到碰撞
{
break;
}
}
--manager->y; // 上移一格当然没有碰撞 insertTetris(manager); // 放入当前方块
setPoolColor(manager, control); // 设置颜色 checkErasing(manager, control); // 检测消行
printTetrisPool(manager, control); // 显示游戏池
} // =============================================================================
// 消行检测
bool checkErasing(TetrisManager *manager, TetrisControl *control) {
static const unsigned scores[] = { , , , , }; // 消行得分
int8_t count = ;
int8_t k = , y = manager->y + ; // 从下往上检测 do {
if (y < ROW_END && manager->pool[y] == 0xFFFFU) // 有效区域内且一行已填满
{
++count;
// 消除一行方块
memmove(manager->pool + , manager->pool, sizeof(uint16_t) * y);
// 颜色数组的元素随之移动
memmove(control->color[], control->color[],
sizeof(int8_t[]) * y);
} else {
--y;
++k;
}
} while (y >= manager->y && k < ); manager->erasedTotal += count; // 消行总数
manager->score += scores[count]; // 得分 if (count > ) {
++manager->erasedCount[count - ]; // 消行
} giveTetris(manager); // 给下一个方块
setPoolColor(manager, control); // 设置颜色 return (count > );
} // =============================================================================
// 键按下
void keydownControl(TetrisManager *manager, TetrisControl *control, int key) {
if (key == ) // 暂停/解除暂停
{
control->pause = !control->pause;
} if (control->pause) // 暂停状态,不作处理
{
return;
} switch (key) {
case 'w':
case 'W':
case '':
case : // 上
control->clockwise = true; // 顺时针旋转
rotateTetris(manager, control); // 旋转方块
break;
case 'a':
case 'A':
case '':
case : // 左
control->direction = ; // 向左移动
horzMoveTetris(manager, control); // 水平移动方块
break;
case 'd':
case 'D':
case '':
case : // 右
control->direction = ; // 向右移动
horzMoveTetris(manager, control); // 水平移动方块
break;
case 's':
case 'S':
case '':
case : // 下
moveDownTetris(manager, control); // 向下移动方块
break;
case ' ': // 直接落地
dropDownTetris(manager, control);
break;
case '': // 反转
control->clockwise = false; // 逆时针旋转
rotateTetris(manager, control); // 旋转方块
break;
default:
break;
}
} // =============================================================================
// 以全角定位
void gotoxyWithFullwidth(short x, short y) {
static COORD cd; cd.X = (short) (x << );
cd.Y = y;
SetConsoleCursorPosition(g_hConsoleOutput, cd);
} // =============================================================================
// 显示游戏池边界
void printPoolBorder() {
int8_t y; SetConsoleTextAttribute(g_hConsoleOutput, 0xF0);
for (y = ROW_BEGIN; y < ROW_END; ++y) // 不显示顶部4行和底部2行
{
gotoxyWithFullwidth(, y - );
printf("%2s", "");
gotoxyWithFullwidth(, y - );
printf("%2s", "");
} gotoxyWithFullwidth(, y - ); // 底部边界
printf("%28s", "");
} // 定位到游戏池中的方格
#define gotoxyInPool(x, y) gotoxyWithFullwidth(x + 9, y - 3) // =============================================================================
// 显示游戏池
void printTetrisPool(const TetrisManager *manager, const TetrisControl *control) {
int8_t x, y; for (y = ROW_BEGIN; y < ROW_END; ++y) // 不显示顶部4行和底部2行
{
gotoxyInPool(, y);
// 定点到游戏池中的方格
for (x = COL_BEGIN; x < COL_END; ++x) // 不显示左右边界
{
if ((manager->pool[y] >> x) & ) // 游戏池该方格有方块
{
// 用相应颜色,显示一个实心方块
SetConsoleTextAttribute(g_hConsoleOutput, control->color[y][x]);
printf("■");
} else // 没有方块,显示空白
{
SetConsoleTextAttribute(g_hConsoleOutput, );
printf("%2s", "");
}
}
}
} // =============================================================================
// 显示当前方块
void printCurrentTetris(const TetrisManager *manager,
const TetrisControl *control) {
int8_t x, y; // 显示当前方块是在移动后调用的,为擦去移动前的方块,需要扩展显示区域
// 由于不可能向上移动,故不需要向下扩展
y = (manager->y > ROW_BEGIN) ? (manager->y - ) : ROW_BEGIN; // 向上扩展一格
for (; y < ROW_END && y < manager->y + ; ++y) {
x = (manager->x > COL_BEGIN) ? (manager->x - ) : COL_BEGIN; // 向左扩展一格
for (; x < COL_END && x < manager->x + ; ++x) // 向右扩展一格
{
gotoxyInPool(x, y);
// 定点到游戏池中的方格
if ((manager->pool[y] >> x) & ) // 游戏池该方格有方块
{
// 用相应颜色,显示一个实心方块
SetConsoleTextAttribute(g_hConsoleOutput, control->color[y][x]);
printf("■");
} else // 没有方块,显示空白
{
SetConsoleTextAttribute(g_hConsoleOutput, );
printf("%2s", "");
}
}
}
} // =============================================================================
// 显示下一个和下下一个方块
void printNextTetris(const TetrisManager *manager) {
int8_t i;
uint16_t tetris; // 边框
SetConsoleTextAttribute(g_hConsoleOutput, 0xF);
gotoxyWithFullwidth(, );
printf("┏━━━━┳━━━━┓");
gotoxyWithFullwidth(, );
printf("┃%8s┃%8s┃", "", "");
gotoxyWithFullwidth(, );
printf("┃%8s┃%8s┃", "", "");
gotoxyWithFullwidth(, );
printf("┃%8s┃%8s┃", "", "");
gotoxyWithFullwidth(, );
printf("┃%8s┃%8s┃", "", "");
gotoxyWithFullwidth(, );
printf("┗━━━━┻━━━━┛"); // 下一个,用相应颜色显示
tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]];
SetConsoleTextAttribute(g_hConsoleOutput, manager->type[] | );
for (i = ; i < ; ++i) {
gotoxyWithFullwidth((i & ) + , (i >> ) + );
((tetris >> i) & ) ? printf("■") : printf("%2s", "");
} // 下下一个,不显示彩色
tetris = gs_uTetrisTable[manager->type[]][manager->orientation[]];
SetConsoleTextAttribute(g_hConsoleOutput, );
for (i = ; i < ; ++i) {
gotoxyWithFullwidth((i & ) + , (i >> ) + );
((tetris >> i) & ) ? printf("■") : printf("%2s", "");
}
} // =============================================================================
// 显示得分信息
void printScore(const TetrisManager *manager) {
static const char *tetrisName = "ITLJZSO";
int8_t i; SetConsoleTextAttribute(g_hConsoleOutput, 0xE); gotoxyWithFullwidth(, );
printf("■得分:%u", manager->score); gotoxyWithFullwidth(, );
printf("■消行总数:%u", manager->erasedTotal);
for (i = ; i < ; ++i) {
gotoxyWithFullwidth(, + i);
printf("□消%d:%u", i + , manager->erasedCount[i]);
} gotoxyWithFullwidth(, );
printf("■方块总数:%u", manager->tetrisTotal); for (i = ; i < ; ++i) {
gotoxyWithFullwidth(, + i);
printf("□%c形:%u", tetrisName[i], manager->tetrisCount[i]);
}
} // =============================================================================
// 显示提示信息
void printPrompting() {
SetConsoleTextAttribute(g_hConsoleOutput, 0xB);
gotoxyWithFullwidth(, );
printf("■控制:");
gotoxyWithFullwidth(, );
printf("□向左移动:← A 4");
gotoxyWithFullwidth(, );
printf("□向右移动:→ D 6");
gotoxyWithFullwidth(, );
printf("□向下移动:↓ S 2");
gotoxyWithFullwidth(, );
printf("□顺时针转:↑ W 8");
gotoxyWithFullwidth(, );
printf("□逆时针转:0");
gotoxyWithFullwidth(, );
printf("□直接落地:空格");
gotoxyWithFullwidth(, );
printf("□暂停游戏:回车");
gotoxyWithFullwidth(, );
printf("■By: wohaaitinciu 12.12.29");
} // =============================================================================
// 运行游戏
void runGame(TetrisManager *manager, TetrisControl *control) {
clock_t clockLast, clockNow; clockLast = clock(); // 计时
printTetrisPool(manager, control); // 显示游戏池 while (!manager->dead) // 没挂
{
while (_kbhit()) // 有键按下
{
keydownControl(manager, control, _getch()); // 处理按键
} if (!control->pause) // 未暂停
{
clockNow = clock(); // 计时
// 两次记时的间隔超过0.45秒
if (clockNow - clockLast > 0.45F * CLOCKS_PER_SEC ) {
clockLast = clockNow;
keydownControl(manager, control, ); // 方块往下移
}
}
}
} // =============================================================================
// 再来一次
bool ifPlayAgain() {
int ch; SetConsoleTextAttribute(g_hConsoleOutput, 0xF0);
gotoxyWithFullwidth(, );
printf("游戏结束");
gotoxyWithFullwidth(, );
printf("按Y重玩,按N退出"); do {
ch = _getch();
if (ch == 'Y' || ch == 'y') {
return true;
} else if (ch == 'N' || ch == 'n') {
return false;
}
} while ();
}

C语言俄罗斯方块的更多相关文章

  1. C语言 俄罗斯方块demo

    这是我的第一篇随笔,当然是发我写的第一个游戏啦! 大一(本人现在大二)寒假过完年,在家待着想起放假前计划写一个游戏的,因为本人立志走游戏开发这条路,加上大一上册学了C语言,就想写个游戏练练手.想了很久 ...

  2. C语言 俄罗斯方块的实现1 全局变量

    目录 全局变量 程序的模块化之MVC 关于俄罗斯方块的代码实现要点 使用数组表示背景和方块 方块表示及其初始化 要让游戏动起来 方块自动下落 全局变量 简而言之,定义在函数外的变量,就是全局变量. 所 ...

  3. C语言写的俄罗斯方块

    源:C语言写的俄罗斯方块 2014年最后一天, 任天堂将风靡全球30年的经典游戏<<俄罗斯方块>>下架. 作为全球最畅销的游戏, 其移植版本遍布各个平台. 下面这个是我去年在5 ...

  4. 俄罗斯方块-C语言-详注版

    代码地址如下:http://www.demodashi.com/demo/14818.html 俄罗斯方块-C语言-详注版 概述 本文详述了C语言版俄罗斯方块游戏的原理以及实现方法,对游戏代码进行了详 ...

  5. C语言编程学习开发的俄罗斯方块小游戏

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  6. 【C语言程序设计】小游戏之俄罗斯方块(一)!适合初学者上手、练手!

    俄罗斯方块的核心玩法非常简单,所以制作起来并不是很复杂,我准备先用2篇文字的篇幅详细讲解一下俄罗斯方块的制作方法. 今天咱们算是第一篇,主要讲解俄罗斯方块中如何定义方块,以及如何实现方块的移动.旋转. ...

  7. 【C语言程序设计】小游戏之俄罗斯方块(二)!适合初学者上手、练手!

    第二篇,主要实现俄罗斯方块中的主体部分,包括容器的数据结构以及容器的相关操作,特别是大方块和容器之间的交互逻辑,包括碰撞检测,消除检测等等. 1. 容器的表示 大方块的实现涉及到位运算,而容器同样如此 ...

  8. 俄罗斯方块c/c++语言代码

    /*******************************/ /******Writer: GJ *******/ /******Language: C *******/ /******Date ...

  9. C语言 第一章 C语言简介

    一.C语言介绍 C是一种通用的编程语言,广泛用于系统软件与应用软件的开发.于1969年至1973年间,为了移植与开发UNIX操作系统,由丹尼斯·里奇与肯·汤普逊,以B语言为基础,在贝尔实验室设计.开发 ...

随机推荐

  1. [NOIP2008]双栈排序 【二分图 + 模拟】

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  2. 解题:SCOI 2008 天平

    题面 我们很容易想到差分约束,但是我们建出来图之后好像并不好下手,因为我们只能得到砝码间的大小关系,并不能容易地得到每个砝码的具体重量. 于是我们有了一种神奇的思路:既然得不到具体重量我们就不求具体重 ...

  3. C语言 ------ #undef 的使用

    #undef 是在后面取消以前定义的宏定义 该指令的形式为 #undef 标识符 其中,标识符是一个宏名称.如果标识符当前没有被定义成一个宏名称,那么就会忽略该指令. 一旦定义预处理器标识符,它将保持 ...

  4. 「Linux」VMware安装centos7(一)

    1.点击:创建虚拟机 2.选择:自定义(高级),下一步 3.点击:下一步 4.选择:稍后安装操作系统,下一步 5.选择:操作系统和对应的版本,下一步 6.设置:虚拟机名称和安装位置,下一步 7.设置: ...

  5. Bootstrap 按钮下拉菜单

    向下拉 <div class="dropdown"> <button class="btn btn-default" data-toggle= ...

  6. 基于javaWeb阶段下的Cookie和Session总结

    1. 会话技术   就是用户在使用浏览器浏览界面的时候,去访问多个页面后一次性关闭浏览器,这个过程叫会话,学习会话技术就是在客户端与服务器进行交互的时候为了能更好的保存数据.在java中会话技术只有C ...

  7. Oracl闪回数据命令。

    当数据库操作没有备份,并且误删数据.可闪回任何 当前闪回15分钟前数据库状态.  alter table BASE_APPOINT_LOG enable row movement;flashback  ...

  8. 洛谷 U3357 C2-走楼梯

    https://www.luogu.org/problem/show?pid=U3357 题目背景 在你成功地解决了上一个问题之后,方方方不禁有些气恼,于是他在楼梯上跳来跳去,想要你求出他跳的方案数. ...

  9. 算法专题-STL篇

    这篇文章着重记录c++中STL的用法.主要粗略的介绍其用法,以知识点的形式呈现其功能,不会深入源码分析其工作原理. 排序和检索. sort(a,a+n),对a[0]往后的n个元素(包括a[0])进行排 ...

  10. PhotoSwipe 图片浏览插件使用方法

    一.简介 PhotoSwipe 是专为移动触摸设备设计的相册/画廊.兼容所有iPhone.iPad.黑莓6+,以及桌面浏览器.底层实现基于HTML/CSS/JavaScript,是一款免费开源的相册产 ...