C语言俄罗斯方块
#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 = >._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(>.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语言俄罗斯方块的更多相关文章
- C语言 俄罗斯方块demo
这是我的第一篇随笔,当然是发我写的第一个游戏啦! 大一(本人现在大二)寒假过完年,在家待着想起放假前计划写一个游戏的,因为本人立志走游戏开发这条路,加上大一上册学了C语言,就想写个游戏练练手.想了很久 ...
- C语言 俄罗斯方块的实现1 全局变量
目录 全局变量 程序的模块化之MVC 关于俄罗斯方块的代码实现要点 使用数组表示背景和方块 方块表示及其初始化 要让游戏动起来 方块自动下落 全局变量 简而言之,定义在函数外的变量,就是全局变量. 所 ...
- C语言写的俄罗斯方块
源:C语言写的俄罗斯方块 2014年最后一天, 任天堂将风靡全球30年的经典游戏<<俄罗斯方块>>下架. 作为全球最畅销的游戏, 其移植版本遍布各个平台. 下面这个是我去年在5 ...
- 俄罗斯方块-C语言-详注版
代码地址如下:http://www.demodashi.com/demo/14818.html 俄罗斯方块-C语言-详注版 概述 本文详述了C语言版俄罗斯方块游戏的原理以及实现方法,对游戏代码进行了详 ...
- C语言编程学习开发的俄罗斯方块小游戏
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- 【C语言程序设计】小游戏之俄罗斯方块(一)!适合初学者上手、练手!
俄罗斯方块的核心玩法非常简单,所以制作起来并不是很复杂,我准备先用2篇文字的篇幅详细讲解一下俄罗斯方块的制作方法. 今天咱们算是第一篇,主要讲解俄罗斯方块中如何定义方块,以及如何实现方块的移动.旋转. ...
- 【C语言程序设计】小游戏之俄罗斯方块(二)!适合初学者上手、练手!
第二篇,主要实现俄罗斯方块中的主体部分,包括容器的数据结构以及容器的相关操作,特别是大方块和容器之间的交互逻辑,包括碰撞检测,消除检测等等. 1. 容器的表示 大方块的实现涉及到位运算,而容器同样如此 ...
- 俄罗斯方块c/c++语言代码
/*******************************/ /******Writer: GJ *******/ /******Language: C *******/ /******Date ...
- C语言 第一章 C语言简介
一.C语言介绍 C是一种通用的编程语言,广泛用于系统软件与应用软件的开发.于1969年至1973年间,为了移植与开发UNIX操作系统,由丹尼斯·里奇与肯·汤普逊,以B语言为基础,在贝尔实验室设计.开发 ...
随机推荐
- NOIP2015运输计划题解报告
这题在洛谷上可以找到提交 P2680运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航 ...
- excel换行
在excel的单元格中换行 1. windows alt + enter 2. mac command + alt + enter
- 【数据结构】【平衡树】treap
之前写treap的传送门 之前写的那个太毒瘤了,这次放一个更毒瘤的指针版上来 #include<cstdio> #include<iostream> #define rg re ...
- Linux系统之路——如何在CentOS7.2安装R和RStudio(Server)
使用ubuntu的小伙伴们直接使用命令sudo apt-get install r-base-dev或者r-base搞定.然而对于使用centos的我却一直卡在安装这一步,十分的悲催,只有羡慕的份,但 ...
- Python --Redis Hash操作
一.Redis Hash操作 Redis 数据库hash数据类型是一个string类型的key和value的映射表,适用于存储对象.Redis 中每个 hash 可以存储 232 - 1 键值对(40 ...
- maven创建spring项目之后,启动报错java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
出错情景:maven中已经加载了spring的核心包,但是项目启动时,报错: org.apache.catalina.core.StandardContext listenerStart严重: Err ...
- OpenCV---开闭操作
一:开操作(先腐蚀后膨胀) 特点:消除噪点,去除小的干扰块,而不影响原来的图像 import cv2 as cv import numpy as np def camp(val1,val2): pv ...
- HTML常用标签-手打抄录-来自-烟雨飘零-拜谢
HTML常用标签及其全称 <a href="#">a 超级链接(anchor)</a> <abbr title="abbreviati ...
- 全国排名的问题(linq 的连表查询 等同于sql的left join)
前言:要获得全国排名,(因为权限问题,显示的数据不是全国的数据,而是某个分区的数据,因此,不能获得数据后排序得到排名) 显示本部的员工积分并且获得在全国的排名. 我的思路:获得显示的员工信息集合1,获 ...
- Debian sudo自动补全
解决 debian sudo TAB 键不能自动补全命令的原因 一般情况,命令行输入 sudo apt-get ins 按 tab ,它后面会自动补全为 install 如果右面写了包的名的一部分,按 ...