俄罗斯方块
这里写目录标题
- 俄罗斯方块
- 俄罗斯方块的初始化
-
- 欢迎界面
-
- 初始化游戏场景
- 清除方块
- 绘制方块
- 在指定位置绘制指定方块的指定方向
- 清除指定位置指定方向的方块
- 随机产生下一个方块
- 在指定位置可以向指定方向移动
- 检测游戏是否结束
- 判断当前方块是否可以转向到指定方向
- 间隔等待的时间
- 移动
- 消除第x行,并把上面的行都下移
- 更新分数
- 更新等级
- 检查
- 源码
俄罗斯方块的初始化
int block[BLOCK_COUNT*4][BLOCK_HEIGHT][BLOCK_WIDTH] = {
{
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0 },
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,1,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,1,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,1,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,1,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,1,0,
0,0,1,1,0,
0,0,0,1,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,0,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 }
};
欢迎界面
void welcome(void) {
initgraph(550, 660);
HWND window = GetHWnd();
SetWindowText(window, _T("俄罗斯方块 (远航版本)"));
setfont(40, 0, _T("微软雅黑"));
setcolor(WHITE);
outtextxy(205, 200, _T("俄罗斯方块(远航)"));
setfont(22, 0, _T("楷体"));
outtextxy(175, 300, _T("俄罗斯方块(远航版本)!"));
Sleep(3000);
}
初始化游戏场景
void initGameScene(void) {
char str[16];
cleardevice();
rectangle(27, 27, 336, 635);
rectangle(29, 29, 334, 633);
rectangle(370, 50, 515, 195);
setfont(24, 0, _T("楷体"));
setcolor(LIGHTGRAY);
outtextxy(405, 215, _T("下一个"));
setcolor(RED);
outtextxy(405, 280, _T("分数"));
sprintf(str, "%d", score);
outtextxy(415, 310, str);
outtextxy(405, 375, _T("等级"));
sprintf(str, "%d", rank);
outtextxy(425, 405, str);
setcolor(LIGHTBLUE);
outtextxy(390, 475, "操作说明");
outtextxy(390, 500, "↑:旋转");
outtextxy(390, 525, "↓: 下降");
outtextxy(390, 550, "←: 左移");
outtextxy(390, 575, "→: 右移");
outtextxy(390, 600, "空格:暂停");
}
清除方块
void clearBlock(void) {
setcolor(BLACK);
setfont(23, 0, "楷体");
for (int i=0; i<BLOCK_HEIGHT; i++) {
for (int j=0; j<BLOCK_WIDTH; j++) {
int x = 391 + j * UNIT_SIZE;
int y = 71 + i * UNIT_SIZE;
outtextxy(x, y, "■");
}
}
}
绘制方块
void drawBlock(int x, int y) {
setcolor(color[NextIndex]);
setfont(23, 0, "楷体");
for (int i=0; i<BLOCK_HEIGHT; i++) {
for (int j=0; j<BLOCK_WIDTH; j++) {
if (block[NextIndex*4][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
在指定位置绘制指定方块的指定方向
void drawBlock(int x, int y, int blockIndex, block_dir_t dir) {
setcolor(color[blockIndex]);
setfont(23, 0, "楷体");
int id = blockIndex * 4 + dir;
for (int i=0; i<BLOCK_HEIGHT; i++) {
for (int j=0; j<BLOCK_WIDTH; j++) {
if (block[id][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
清除指定位置指定方向的方块
void clearBlock(int x, int y, block_dir_t dir) {
setcolor(BLACK);
int id = BlockIndex * 4 + dir;
y += START_Y;
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
if (block[id][i][j] == 1) {
outtextxy(x+20*j, y+i*20, "■");
}
}
}
}
随机产生下一个方块
void nextblock(void) {
clearBlock();
srand(time(NULL));
NextIndex = rand() % BLOCK_COUNT;
drawBlock(391, 71);
}
在指定位置可以向指定方向移动
int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
int x = (y0 - minY) / UNIT_SIZE;
int y = (x0 - minX) / UNIT_SIZE;
int id = BlockIndex * 4 + blockDir;
int ret = 1;
if (moveDir == MOVE_DOWN) {
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
if (block[id][i][j] == 1 &&
(x + i + 1 >= 30 || visit[x+i+1][y+j] == 1)) {
ret = 0;
}
}
}
} else if (moveDir == MOVE_LEFT) {
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
if (block[id][i][j] == 1 &&
(y + j == 0 || visit[x+i][y+j-1]==1)) {
ret = 0;
}
}
}
} else if (moveDir == MOVE_RIGHT) {
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
if (block[id][i][j] == 1 &&
(y+j+1>=15 || visit[x+i][y+j+1]==1)) {
ret = 0;
}
}
}
}
return ret;
}
检测游戏是否结束
void failCheck() {
if (!moveable(START_X, START_Y, MOVE_DOWN, BLOCK_UP)) {
setcolor(WHITE);
setfont(45, 0, "隶体");
outtextxy(75, 300, "GAME OVER!");
Sleep(1000);
system("pause");
closegraph();
exit(0);
}
}
判断当前方块是否可以转向到指定方向
int rotatable(int x, int y, block_dir_t dir) {
int id = BlockIndex * 4 + dir;
int xIndex = (y - minY) / 20;
int yIndex = (x - minX) / 20;
if (!moveable(x, y, MOVE_DOWN, dir)) {
return 0;
}
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
if (block[id][i][j] == 1 &&
(yIndex+j<0 || yIndex+j>=15 || visit[xIndex+i][yIndex+j]==1)) {
return 0;
}
}
}
return 1;
}
间隔等待的时间
void wait(int interval) {
int count = interval / 10;
for (int i=0; i<count; i++) {
Sleep(10);
if (kbhit()) {
return;
}
}
}
移动
void move(void){
int x = START_X;
int y = START_Y;
int k = 0;
block_dir_t blockDir = BLOCK_UP;
failCheck();
while (1) {
int curSpeed = speed;
if (kbhit()) {
int key = getch();
if (key == KEY_SPACE) {
getch();
}
}
clearBlock(x, k, blockDir);
if (kbhit()) {
int key = getch();
if(key == KEY_UP) {
block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);
if (rotatable(x, y+k, nextDir)) {
blockDir = nextDir;
}
} else if (key == KEY_DOWN) {
curSpeed = 50;
} else if (key == KEY_LEFT) {
if (moveable(x, y+k+20, MOVE_LEFT, blockDir)) {
x -= 20;
}
} else if (key ==KEY_RIGHT) {
if (moveable(x, y+k+20, MOVE_RIGHT, blockDir)) {
x += 20;
}
}
}
k += 20;
drawBlock(x, y+k, BlockIndex, blockDir);
wait(curSpeed);
if (!moveable(x, y+k, MOVE_DOWN, blockDir)) {
mark(x, y+k, BlockIndex, blockDir);
break;
}
}
}
消除第x行,并把上面的行都下移
void down(int x){
for (int i=x; i>0; i--) {
for (int j=0; j<15; j++) {
if (visit[i-1][j]) {
visit[i][j] = 1;
markColor[i][j] = markColor[i-1][j];
setcolor(markColor[i][j]);
outtextxy(20*j + minX, 20*i+minY, "■");
} else {
visit[i][j] = 0;
setcolor(BLACK);
outtextxy(20*j + minX, 20*i+minY, "■");
}
}
}
setcolor(BLACK);
for (int j=0; j<15; j++) {
visit[0][j] = 0;
outtextxy(20*j + minX, minY, "■");
}
}
更新分数
void addScore(int lines) {
char str[32];
setcolor(RED);
score += lines * 10;
sprintf(str, "%d", score);
outtextxy(415, 310, str);
}
更新等级
void updateGrade() {
rank = score / 50;
char str[16];
sprintf(str, "%d", rank);
outtextxy(425, 405, str);
speed = 500 - rank*100;
if (speed <= 100) {
speed = 100;
}
}
检查
void check(void) {
int i, j;
int clearLines = 0;
for (i=29; i>=0; i--) {
for (j=0; j<15 && visit[i][j]; j++) ;
if (j >= 15) {
down(i);
i++;
clearLines++;
}
}
addScore(clearLines);
updateGrade();
}
源码
#include
#include
#include
#include
int score = 0;
int rank = 0;
#define BLOCK_COUNT 5
#define BLOCK_WIDTH 5
#define BLOCK_HEIGHT 5
#define UNIT_SIZE 20
#define START_X 130
#define START_Y 30
#define KEY_UP 72
#define KEY_RIGHT 77
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_SPACE 32
int speed = 500;
int minX = 30;
int minY = 30;
typedef enum {
BLOCK_UP,
BLOCK_RIGHT,
BLOCK_DOWN,
BLOCK_LEFT
} block_dir_t;
typedef enum {
MOVE_DOWN,
MOVE_LEFT,
MOVE_RIGHT
} move_dir_t;
int NextIndex = -1;
int BlockIndex = -1;
int color[BLOCK_COUNT] = {
GREEN, CYAN, MAGENTA, BROWN, YELLOW
};
int visit[30][15];
int markColor[30][15];
int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH] = {
{
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0 },
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,1,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,1,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,1,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,1,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,0,1,0,
0,0,1,1,0,
0,0,0,1,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,0,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 }
};
void welcome(void) {
initgraph(550, 660);
HWND window = GetHWnd();
SetWindowText(window, _T("俄罗斯方块 (远航版本)"));
settextstyle(40, 0, _T("微软雅黑"));
setcolor(WHITE);
outtextxy(205, 200, "俄罗斯方块(远航)");
settextstyle(22, 0, _T("楷体"));
outtextxy(175, 300, _T("俄罗斯方块(远航版本)!"));
Sleep(3000);
}
void initGameScene(void) {
char str[16];
cleardevice();
rectangle(27, 27, 336, 635);
rectangle(29, 29, 334, 633);
rectangle(370, 50, 515, 195);
settextstyle(24, 0, "楷体");
setcolor(LIGHTGRAY);
outtextxy(405, 215, "下一个");
setcolor(RED);
outtextxy(405, 280, "分数");
sprintf_s(str, "%d", score);
outtextxy(415, 310, str);
outtextxy(405, 375, "等级");
sprintf_s(str, "%d", rank);
outtextxy(425, 405, str);
setcolor(LIGHTBLUE);
outtextxy(390, 475, "操作说明");
outtextxy(390, 500, "↑:旋转");
outtextxy(390, 525, "↓: 下降");
outtextxy(390, 550, "←: 左移");
outtextxy(390, 575, "→: 右移");
outtextxy(390, 600, "空格:暂停");
}
void clearBlock(void) {
setcolor(BLACK);
settextstyle(23, 0, "楷体");
for (int i = 0; i < BLOCK_HEIGHT; i++) {
for (int j = 0; j < BLOCK_WIDTH; j++) {
int x = 391 + j * UNIT_SIZE;
int y = 71 + i * UNIT_SIZE;
outtextxy(x, y, "■");
}
}
}
void drawBlock(int x, int y) {
setcolor(color[NextIndex]);
settextstyle(23, 0, "楷体");
for (int i = 0; i < BLOCK_HEIGHT; i++) {
for (int j = 0; j < BLOCK_WIDTH; j++) {
if (block[NextIndex * 4][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
void drawBlock(int x, int y, int blockIndex, block_dir_t dir) {
setcolor(color[blockIndex]);
settextstyle(23, 0, "楷体");
int id = blockIndex * 4 + dir;
for (int i = 0; i < BLOCK_HEIGHT; i++) {
for (int j = 0; j < BLOCK_WIDTH; j++) {
if (block[id][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
void clearBlock(int x, int y, block_dir_t dir) {
setcolor(BLACK);
int id = BlockIndex * 4 + dir;
y += START_Y;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (block[id][i][j] == 1) {
outtextxy(x + 20 * j, y + i * 20, "■");
}
}
}
}
void nextblock(void) {
clearBlock();
srand(time(NULL));
NextIndex = rand() % BLOCK_COUNT;
drawBlock(391, 71);
}
int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
int x = (y0 - minY) / UNIT_SIZE;
int y = (x0 - minX) / UNIT_SIZE;
int id = BlockIndex * 4 + blockDir;
int ret = 1;
if (moveDir == MOVE_DOWN) {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (block[id][i][j] == 1 &&
(x + i + 1 >= 30 || visit[x + i + 1][y + j] == 1)) {
ret = 0;
}
}
}
}
else if (moveDir == MOVE_LEFT) {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (block[id][i][j] == 1 &&
(y + j == 0 || visit[x + i][y + j - 1] == 1)) {
ret = 0;
}
}
}
}
else if (moveDir == MOVE_RIGHT) {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (block[id][i][j] == 1 &&
(y + j + 1 >= 15 || visit[x + i][y + j + 1] == 1)) {
ret = 0;
}
}
}
}
return ret;
}
void failCheck() {
if (!moveable(START_X, START_Y, MOVE_DOWN, BLOCK_UP)) {
setcolor(WHITE);
settextstyle(45, 0, "隶体");
outtextxy(75, 300, "GAME OVER!");
Sleep(1000);
system("pause");
closegraph();
exit(0);
}
}
int rotatable(int x, int y, block_dir_t dir) {
int id = BlockIndex * 4 + dir;
int xIndex = (y - minY) / 20;
int yIndex = (x - minX) / 20;
if (!moveable(x, y, MOVE_DOWN, dir)) {
return 0;
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (block[id][i][j] == 1 &&
(yIndex + j < 0 || yIndex + j >= 15 || visit[xIndex + i][yIndex + j] == 1)) {
return 0;
}
}
}
return 1;
}
void wait(int interval) {
int count = interval / 10;
for (int i = 0; i < count; i++) {
Sleep(10);
if (_kbhit()) {
return;
}
}
}
void mark(int x, int y, int blockIndex, block_dir_t dir) {
int id = blockIndex * 4 + dir;
int x2 = (y - minY) / 20;
int y2 = (x - minX) / 20;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (block[id][i][j] == 1) {
visit[x2 + i][y2 + j] = 1;
markColor[x2 + i][y2 + j] = color[blockIndex];
}
}
}
}
void move(void) {
int x = START_X;
int y = START_Y;
int k = 0;
block_dir_t blockDir = BLOCK_UP;
failCheck();
while (1) {
int curSpeed = speed;
if (_kbhit()) {
int key = _getch();
if (key == KEY_SPACE) {
_getch();
}
}
clearBlock(x, k, blockDir);
if (_kbhit()) {
int key = _getch();
if (key == KEY_UP) {
block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);
if (rotatable(x, y + k, nextDir)) {
blockDir = nextDir;
}
}
else if (key == KEY_DOWN) {
curSpeed = 50;
}
else if (key == KEY_LEFT) {
if (moveable(x, y + k + 20, MOVE_LEFT, blockDir)) {
x -= 20;
}
}
else if (key == KEY_RIGHT) {
if (moveable(x, y + k + 20, MOVE_RIGHT, blockDir)) {
x += 20;
}
}
}
k += 20;
drawBlock(x, y + k, BlockIndex, blockDir);
wait(curSpeed);
if (!moveable(x, y + k, MOVE_DOWN, blockDir)) {
mark(x, y + k, BlockIndex, blockDir);
break;
}
}
}
void newblock() {
BlockIndex = NextIndex;
drawBlock(START_X, START_Y);
Sleep(100);
nextblock();
move();
}
void down(int x) {
for (int i = x; i > 0; i--) {
for (int j = 0; j < 15; j++) {
if (visit[i - 1][j]) {
visit[i][j] = 1;
markColor[i][j] = markColor[i - 1][j];
setcolor(markColor[i][j]);
outtextxy(20 * j + minX, 20 * i + minY, "■");
}
else {
visit[i][j] = 0;
setcolor(BLACK);
outtextxy(20 * j + minX, 20 * i + minY, "■");
}
}
}
setcolor(BLACK);
for (int j = 0; j < 15; j++) {
visit[0][j] = 0;
outtextxy(20 * j + minX, minY, "■");
}
}
void addScore(int lines) {
char str[32];
setcolor(RED);
score += lines * 10;
sprintf_s(str, "%d", score);
outtextxy(415, 310, str);
}
void updateGrade() {
rank = score / 50;
char str[16];
sprintf_s(str, "%d", rank);
outtextxy(425, 405, str);
speed = 500 - rank * 100;
if (speed <= 100) {
speed = 100;
}
}
void check(void) {
int i, j;
int clearLines = 0;
for (i = 29; i >= 0; i--) {
for (j = 0; j < 15 && visit[i][j]; j++);
if (j >= 15) {
down(i);
i++;
clearLines++;
}
}
addScore(clearLines);
updateGrade();
}
int main(void) {
welcome();
initGameScene();
nextblock();
Sleep(500);
memset(visit, 0, sizeof(visit));
while (1) {
newblock();
check();
}
system("pause");
closegraph();
return 0;
}

这个是效果图