最近正在学习C语言,于是自己就写了个俄罗斯方块小游戏,本想找一篇博文借鉴一下的,粗略的找了一圈并没有找到让自己满意的,于是花了2天搞了一下。初学者,代码粗陋,大佬勿喷。有哪里不对的,请不吝赐教,谢谢~
废话不多说,上图:
代码开始运行检测C:\GameTetris.dat文件是否是合法的存档,如果是则提示用户游戏有存档,是否读取。
按下N,则删除存档,新建新的游戏,重新开始。
按下Y,则读取文档,从上次状态保存的状态开始运
这里的每个方块都是用双字节字符“■”来实现,没有用到任何画图库
我按下了Y,所以程序读取了存档。
1、键盘信号获取
由 _kbhit(),_getch() ,函数获取
_kbhit()检测有没有键按下
_getch()读取键值
2、方块的产生
通过srand,与rand 函数实现随机产生
3、控制台
一个方块占2个横向空格长度,1个纵向空格长度,所以代码中会频繁出现横坐标 * 2的代码
4、旋转方块
我的方法是选一个中心点作为坐标原点,根据这个原点画一个坐标系,其余4个子方块在这个坐标系中相对原点的位置偏移存储在BlockXY blockXY[4];中,centerXY结构体就是原点的实际坐标,那么其余3个子方块的实际坐标就可以根据这个中心点算出来。
而左移,右移,下移都只需要移动这个中心点的实际坐标即可。
下方堆积的方块是使用一个二维数组在存储,二维数组的成员等于1,则在对应坐标上就有一个堆积方块。
一些代码函数什么的参考了如下博文(一篇讲C语言贪吃蛇的):
https://blog.csdn.net/qq_40953281/article/details/79315254
接下来上代码:(我是用VC6.0写的)
代码中该有的注释都有,有什么问题,欢迎留言讨论~
// 俄罗斯方块.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#include "windows.h"
#include "conio.h"
#include "time.h"
#include "math.h"
#define FilePath "C:\\GameTetris.dat"
#define GameX 24
#define GameY 36
#define SPEED 5 //数值越大速度越慢
//颜色
enum
{
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
//方块元素
struct BlockXY
{
int x;
int y;
int xiangXian;//方块所处相对中心点而言的象限
};
//方块形状
struct BlockShape
{
BlockXY blockXY[4];//方块元素相对中心点的坐标
BlockXY center;//中心旋转轴点的坐标
int type;//方块类型
};
BlockShape* G_pBlockShape1 = NULL, *G_pBlockShape2 = NULL;
char name[200];
int score;//得分
//指令集: w 旋转 a 左 s 下 d 右 o 结束游戏并保存 p 暂停游戏
char KEYVALUESET[] = {'w', 'a', 's', 'd', 'o', 'p', ' '};
int G_BlockScreenArr[GameX][GameY] = {0};//初始化标记已经落下堆积后的全屏方块位置二维数组, 0代表没有方块,1代表有方块
/************************************************************************/
/*光标跳转到指定位置*/
/************************************************************************/
void gotoxy(int x, int y, int ForgC)
{
if(ForgC == -1)
{
ForgC = LIGHTGREEN;
}
// 更新光标位置
COORD pos;
WORD wColor;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(hOutput, &csbi))
{
//设置字体颜色
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hOutput, wColor);
}
// 隐藏光标
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = 1; //值介于1 ~ 100 之间 单元格底部为下划线 ~ 完全填充单元格
SetConsoleCursorInfo(hOutput, &cursor);
}
/************************************************************************/
/*光标跳转到指定位置(函数重载)*/
/************************************************************************/
void gotoxy(int x, int y)
{
gotoxy(x, y, -1);
}
/************************************************************************/
/*指定位置打印游戏边框*/
/************************************************************************/
int switchFlag = 0;
void gotoprint(int x, int y)
{
int color = (switchFlag = ! switchFlag) ? LIGHTGRAY : LIGHTRED;
gotoxy(x * 2, y, color);
printf("■");
}
/************************************************************************/
/*从指定位置开始清除指定长度元素*/
/************************************************************************/
void gotodelete(int x, int y, int length)
{
int i;
gotoxy(x, y);
for (i = 0; i < length; i++)
{
printf(" ");
}
}
/************************************************************************/
/*清除指定位置元素*/
/************************************************************************/
void gotodelete(int x, int y)
{
gotodelete(x, y, 1);
}
/************************************************************************/
/* 绘制游戏边框 */
/************************************************************************/
void drawGameMap()
{
int i;
//初始化左侧游戏窗口
for (i = 0; i < GameX; i++)
{
gotoprint(i, 0);
}
for (i = 0; i < GameX; i++)
{
gotoprint(i, GameY);
}
for (i = 0; i < GameY; i++)
{
gotoprint(0, i);
}
for (i = 0; i <= GameY; i++)
{
gotoprint(GameX, i);
}
//初始化右侧小窗口
for (i = 0; i < 8; i++)
{
gotoprint(i + GameX + 2, 0);
}
for (i = 0; i < 8; i++)
{
gotoprint(i + GameX + 2, 7);
}
for (i = 0; i < 8; i++)
{
gotoprint(GameX + 2, i);
}
for (i = 0; i < 8; i++)
{
gotoprint(GameX + 2 + 7, i);
}
}
/************************************************************************/
/*显示方块*/
/************************************************************************/
void showBlockShape(BlockShape* pBlockShape)
{
int i;
BlockXY *pBlockXY = pBlockShape->blockXY;
for (i = 0; i < 4; i++)
{
gotoxy(pBlockXY[i].x + pBlockShape->center.x, pBlockXY[i].y * -1 + pBlockShape->center.y);
printf("■");
}
}
/************************************************************************/
/* 初始化游戏开始界面*/
/************************************************************************/
bool initGameScreen(int state)
{
int i, j;
bool result;
char keyValue;
system("title 俄罗斯方块 by 机智蛋");
result = false;
gotoxy(15, 10);
printf("/**********************************************/");
gotoxy(15, 22);
printf("/**********************************************/");
gotoxy(20, 13);
printf("WELCOME TO THE GAME OF TETRIS");
gotoxy(14, 16);
printf("W:左移 D:右移 S:下移 空格:下落到底部 P暂停 O结束游戏并保存");
gotoxy(20, 18);
if(state)
{
printf("游戏有存档,是否读取?Y/N");
while(1)
{
keyValue = _getch();
if(keyValue == 'Y' || keyValue == 'y')//同意读档
{
result = true;
break;
}
else if(keyValue == 'N' || keyValue == 'n')//不同意读档
{
DeleteFileA(FilePath); //删除存档
score = 0;
free(G_pBlockShape1);
free(G_pBlockShape2);
G_pBlockShape1 = NULL;
G_pBlockShape2 = NULL;
for (i = 0; i < GameX; i++)
{
for (j = 0; j < GameY; j++)
{
G_BlockScreenArr[i][j] = 0;
}
}
result = false;
break;
}
}
}
if(! result) //不同意读档或无存档
{
gotodelete(20, 18, 30);
gotoxy(20, 18);
printf("PLEASE ENTER YOUR NAME:");
scanf("%s", name);
}
system("CLS");
gotoxy(53, 20);
printf("hello %s,Welcome To Play", name);
gotoxy(53, 25);
printf("Your Score Is:%d = ̄ω ̄= ", score);
gotoxy(53, 30);
printf("This Game Is Created By 机智蛋");
if(result)
{//恢复存档堆积方块图
for (i = 0; i < GameX; i++)
{
for (j = 0; j < GameY; j++)
{
if(G_BlockScreenArr[i][j] == 1)
{
gotoxy(i * 2, j);
printf("■");
}
}
}
//恢复移动方块图
showBlockShape(G_pBlockShape1);
// G_pBlockShape2->center.x = (GameX + 5) * 2;
// G_pBlockShape2->center.y +=2;
//恢复下一个方块图
showBlockShape(G_pBlockShape2);
}
return result;
}
/************************************************************************/
/* 初始化游戏开始界面(函数重载)*/
/************************************************************************/
int initGameScreen()
{
return initGameScreen(0);
}
/************************************************************************/
/* 游戏结束处理*/
/************************************************************************/
void FinishGame()
{
system("CLS");
gotoxy(15, 10);
printf("/**********************************************/");
gotoxy(15, 20);
printf("/**********************************************/");
gotoxy(18, 14);
printf("GAME OVER o(* ̄▽ ̄*)o");
gotoxy(20, 16);
printf("Your Score is %d ", score);
gotoxy(18, 18);
printf("还不错哦, 继续努力O(∩_∩)O");
gotoxy(0, 27);
gotoxy(0, 27);
system("pause");
}
/************************************************************************/
/*顺时针旋转方块*/
/************************************************************************/
void rotateBlock(BlockShape* pBlockShape)
{
int i, tmp, realX, realY;
bool forbit;
BlockXY blockXY;
BlockXY centerXY;
centerXY = pBlockShape->center;
forbit = false;
if(pBlockShape->type == 3)//如果是方形方块,则不做旋转
{
return;
}
//删除原来的点
for (i = 0; i < 4; i++)
{
blockXY.x = pBlockShape->blockXY[i].x;
blockXY.y = pBlockShape->blockXY[i].y;
gotodelete(blockXY.x + pBlockShape->center.x, blockXY.y * -1 + pBlockShape->center.y);
}
//旋转
for (i = 0; i < 4; i++)
{
blockXY.x = pBlockShape->blockXY[i].x;
blockXY.y = pBlockShape->blockXY[i].y;
blockXY.xiangXian = pBlockShape->blockXY[i].xiangXian;
//根据象限不同决定旋转后xy的偏移
switch(blockXY.xiangXian)
{
case 1:
{
tmp = blockXY.x;
blockXY.x = blockXY.y * 2;
blockXY.y = tmp / 2;
blockXY.y *= -1;
blockXY.xiangXian = 4;
break;
}
case 2:
{
tmp = blockXY.x * -1;
blockXY.x = blockXY.y * 2;
blockXY.y = tmp / 2;
blockXY.xiangXian = 1;
break;
}
case 3:
{
tmp = blockXY.x;
blockXY.x = blockXY.y * 2;
blockXY.y = tmp / 2 * -1;
blockXY.xiangXian = 2;
break;
}
case 4:
{
tmp = blockXY.x;
blockXY.x = blockXY.y * 2;
blockXY.y = tmp / 2 * -1;
blockXY.xiangXian = 3;
break;
}
}
//检查真实坐标是否超出边界,如超出则移动中心点位置
realX = blockXY.x + centerXY.x;
if(realX <= 0)
{
centerXY.x += realX * -1 + 2;//旋转时如超出左边边界,则中心点向右移动
}
else if(realX >= GameX * 2)
{
centerXY.x -= realX - GameX * 2 + 2;//旋转时如超出右边边界,则中心点向左移动
}
realY = blockXY.y * -1 + centerXY.y;
if(realY <= 0)
{
centerXY.y += realY * -1 + 1;//旋转时如超出顶部边界,则中心点向下移动
}
else if(realY >= GameY)//旋转时如碰到底部边框,则不允许旋转
{
forbit = true;
break;
}
if(G_BlockScreenArr[realX /2 ][realY] == 1)//旋转时如碰到其他方块则不允许旋转
{
forbit = true;
break;
}
if(! forbit)
{
pBlockShape->center = centerXY;
pBlockShape->blockXY[i].x = blockXY.x;
pBlockShape->blockXY[i].y = blockXY.y;
pBlockShape->blockXY[i].xiangXian = blockXY.xiangXian;
}
}
showBlockShape(pBlockShape);//旋转之后显示移动方块图
}
/************************************************************************/
/*
方块移动
@type 0 下落 1左移 2右移
return 返回true 已到底部 返回false 未到底部
*/
/************************************************************************/
bool dropBlockShape(BlockShape* pBlockShape, int type)
{
int i, realX, realY;
BlockXY blockXY;
bool forbit = false;
BlockXY centerXY;
centerXY = pBlockShape->center;
switch(type)
{
case 0://下落
{
centerXY.y++;
break;
}
case 1:
{
centerXY.x-=2;//1个方块横向占2个空,纵向占1个空,所以x +- 2,y +- 1
break;
}
case 2:
{
centerXY.x+=2;
break;
}
default:
{
return false;
}
}
for (i = 0; i < 4; i++)
{
blockXY.x = pBlockShape->blockXY[i].x;
blockXY.y = pBlockShape->blockXY[i].y;
//检查真实坐标是否超出边界,如超出则禁止移动
realX = blockXY.x + centerXY.x;
if(realX <= 0)
{
return false;
}
else if(realX >= GameX * 2)
{
return false;
}
realY = blockXY.y * -1 + centerXY.y;
if(realY >= GameY)//已到底部则停止下落
{
return true;
}
else if(G_BlockScreenArr[realX / 2][realY] == 1)//判断是否碰到其他方块,是则停止下落
{
return true;
}
}
//删除原来的点
for (i = 0; i < 4; i++)
{
blockXY.x = pBlockShape->blockXY[i].x;
blockXY.y = pBlockShape->blockXY[i].y;
gotodelete(blockXY.x + pBlockShape->center.x, blockXY.y * -1 + pBlockShape->center.y);
}
pBlockShape->center = centerXY;
showBlockShape(pBlockShape);//显示移动后的方块图
return false;
}
/************************************************************************/
/* 生成新的方块*/
/************************************************************************/
BlockShape* creatBlockShape()
{
BlockShape* pBlockShape = (BlockShape*)malloc(sizeof(BlockShape));
pBlockShape->type = rand() % 7; //总共7种方块
switch (pBlockShape->type)
{
case 0:// 直条方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 1;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = 2;
pBlockShape->blockXY[2].y = 0;
pBlockShape->blockXY[2].xiangXian = 1;
pBlockShape->blockXY[3].x = 4;
pBlockShape->blockXY[3].y = 0;
pBlockShape->blockXY[3].xiangXian = 1;
break;
}
case 1 :// L1型方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 1;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = 2;
pBlockShape->blockXY[2].y = 0;
pBlockShape->blockXY[2].xiangXian = 1;
pBlockShape->blockXY[3].x = -2;
pBlockShape->blockXY[3].y = -1;
pBlockShape->blockXY[3].xiangXian = 3;
break;
}
case 2:// L2型方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 1;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = 2;
pBlockShape->blockXY[2].y = 0;
pBlockShape->blockXY[2].xiangXian = 1;
pBlockShape->blockXY[3].x = 2;
pBlockShape->blockXY[3].y = -1;
pBlockShape->blockXY[3].xiangXian = 4;
break;
}
case 3:// 方型方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 1;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = -2;
pBlockShape->blockXY[2].y = -1;
pBlockShape->blockXY[2].xiangXian = 3;
pBlockShape->blockXY[3].x = 0;
pBlockShape->blockXY[3].y = -1;
pBlockShape->blockXY[3].xiangXian = 4;
break;
}
case 4:// 倒Z型方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 2;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = 0;
pBlockShape->blockXY[2].y = 1;
pBlockShape->blockXY[2].xiangXian = 2;
pBlockShape->blockXY[3].x = 2;
pBlockShape->blockXY[3].y = 1;
pBlockShape->blockXY[3].xiangXian = 1;
break;
}
case 5:// Z型方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 1;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = 0;
pBlockShape->blockXY[2].y = -1;
pBlockShape->blockXY[2].xiangXian = 4;
pBlockShape->blockXY[3].x = 2;
pBlockShape->blockXY[3].y = -1;
pBlockShape->blockXY[3].xiangXian = 4;
break;
}
case 6:// T型方块
{
pBlockShape->center.x = GameX;
pBlockShape->center.y = 2;
pBlockShape->blockXY[0].x = -2;
pBlockShape->blockXY[0].y = 0;
pBlockShape->blockXY[0].xiangXian = 3;
pBlockShape->blockXY[1].x = 0;
pBlockShape->blockXY[1].y = 0;
pBlockShape->blockXY[1].xiangXian = 0;
pBlockShape->blockXY[2].x = 2;
pBlockShape->blockXY[2].y = 0;
pBlockShape->blockXY[2].xiangXian = 1;
pBlockShape->blockXY[3].x = 0;
pBlockShape->blockXY[3].y = 1;
pBlockShape->blockXY[3].xiangXian = 2;
break;
}
}
return pBlockShape;
}
/************************************************************************/
/*读档游戏*/
/************************************************************************/
bool readGameFile()
{
FILE *fp;
int blockScreenArr[GameX][GameY] = {0};
int s, i, j;
BlockShape *pBlockShape1, *pBlockShape2;
if((fp = fopen(FilePath, "rb")) == NULL)
{
return 0;
}
pBlockShape1 = (BlockShape*)malloc(sizeof(BlockShape));
pBlockShape2 = (BlockShape*)malloc(sizeof(BlockShape));
fread(blockScreenArr, sizeof(blockScreenArr), 1, fp);
fread(pBlockShape1, sizeof(BlockShape), 1, fp);
fread(pBlockShape2, sizeof(BlockShape), 1, fp);
fread(&s, sizeof(int), 1, fp);
fread(name, sizeof(name), 1, fp);
fclose(fp);
if(pBlockShape1->type > 6 || pBlockShape1->type < 0 || pBlockShape2->type> 6 || pBlockShape2->type < 0 || s < 0)
{
free(pBlockShape1);
free(pBlockShape2);
return false;
}
G_pBlockShape1 = pBlockShape1;
G_pBlockShape2 = pBlockShape2;
score = s;
for (i = 0; i < GameX; i++)
{
for (j = 0; j < GameY; j++)
{
G_BlockScreenArr[i][j] = blockScreenArr[i][j];
}
}
return true;
}
/************************************************************************/
/*保存游戏*/
/************************************************************************/
void saveGame()
{
FILE *fp;
if((fp = fopen(FilePath, "wb")) == NULL)
{
gotoxy(0, 27);
printf("游戏保存失败\n");
return;
}
fwrite(G_BlockScreenArr, sizeof(G_BlockScreenArr), 1, fp);
fwrite(G_pBlockShape1, sizeof(BlockShape), 1, fp);
fwrite(G_pBlockShape2, sizeof(BlockShape), 1, fp);
fwrite(&score, sizeof(score), 1, fp);
fwrite(name, sizeof(name), 1, fp);
fclose(fp);
}
/************************************************************************/
/*判断按键*/
/************************************************************************/
bool jugeKeyValue(char key)
{
int i;
for (i = 0; i < sizeof(KEYVALUESET); i++)
{
if(key == KEYVALUESET[i])
{
break;
}
}
if(i >= sizeof(KEYVALUESET)) //判断按键是否在指令集中,如不在其中则不做处理
{
return true;
}
if(key == 'o') //结束游戏并保存
{
saveGame();
FinishGame();
return false;
}
else if(key == 'p')//暂停游戏
{
gotoxy(0, GameY + 2);
printf("按任意键继续......");
_getch();
gotodelete(0, GameY + 2, 20);
}
else if(key == 'w')//旋转方块
{
rotateBlock(G_pBlockShape1);
}
else if(key == 'a')//左移方块
{
dropBlockShape(G_pBlockShape1, 1);//左移
}
else if(key == 'd')//右移方块
{
dropBlockShape(G_pBlockShape1, 2);//右移
}
return true;
}
/************************************************************************/
/*将方块各个点的坐标在全屏方块二维数组中标记出来*/
/************************************************************************/
void addInBlockScreenArr(BlockShape* pBlockShape)
{
int i;
for (i = 0; i < 4; i++)
{
G_BlockScreenArr[(pBlockShape->blockXY[i].x + pBlockShape->center.x) / 2][pBlockShape->blockXY[i].y * -1 + pBlockShape->center.y]
= 1;
}
}
/************************************************************************/
/*检测堆积的方块是否到达顶端
return true 到达顶端 false 未到达
*/
/************************************************************************/
bool checkBlockReachTop()
{
int i;
for (i = 1; i < GameX; i++)
{
if(G_BlockScreenArr[i][1] == 1)
{
return true;
}
}
return false;
}
/************************************************************************/
/*执行删除指定行的方格并下移上方方块 */
/************************************************************************/
void clearLine(int line, int clearCount)
{
int i, j, count;
score += (int)pow(2, clearCount);//根据连续多少行满行计算分数,1行+1, 2行+2, 3行+4, 4行+8
gotoxy(67, 25);
printf("%d", score); //打印分数
gotodelete(2, line, (GameX - 1) * 2);
for (i = 1; i < GameX; i++)//消除一行方块,并标记消除
{
G_BlockScreenArr[i][line] = 0;
}
Sleep(50);
//被消除的一行上方所有方块全部下移一行
for (j = line - 1; j > 0; j--)
{
count = 0;
for (i = 1; i < GameX; i++)
{
gotodelete(i * 2, j);
if(G_BlockScreenArr[i][j] == 1)
{
G_BlockScreenArr[i][j] = 0;
count++;
G_BlockScreenArr[i][j + 1] = 1;
gotoxy(i * 2, j + 1);
printf("■");
}
}
if(count == 0)
{
break;
}
}
}
/************************************************************************/
/*检测某一行的方块是否已满并消除
return true 代表有一行方块消除 false 代表无消除
*/
/************************************************************************/
bool checkBlockLineIsFull()
{
int i, j, count, clearCount;//固定方块计数,清除方块计次
clearCount = 0;
for (j = GameY - 1; j > 0; j--)
{
count = 0;
for (i = 1; i < GameX; i++)
{
if(G_BlockScreenArr[i][j] == 1)
{
count++;
}
}
if(count == GameX - 1)//一行已满
{
clearLine(j, clearCount++);
j++;
}
else if(count == 0)//如果这一行没有方块,则说明检测的堆积方块到达最高度
{
return false;
}
}
return false;
}
int main(int argc, char* argv[])
{
char c;
bool onBottom, dropFast;
int speedCount = 0;
int i;
dropFast = false;//快速下落
srand(time(0));
initGameScreen(readGameFile());//检测游戏存档并初始化游戏显示
drawGameMap();//绘制游戏边框
while(1)
{
if (_kbhit())//判断是否有按键按下
{
c = _getch();//读取按下的键值
if(! jugeKeyValue(c)) //判断指令是否合法
{
return 0;
}
}
if(G_pBlockShape2 == NULL)//创建新的方块
{
G_pBlockShape2 = creatBlockShape();
if(G_pBlockShape1 == NULL)
{
G_pBlockShape1 = G_pBlockShape2;
G_pBlockShape2 = NULL;
}
else
{
//右侧小窗口显示下一个要出现的方块
G_pBlockShape2->center.x = (GameX + 5) * 2;
G_pBlockShape2->center.y +=2;
showBlockShape(G_pBlockShape2);
}
showBlockShape(G_pBlockShape1);
}
if(c == ' ')//按下空格快速下落
{
dropFast = true;
}
if(c == 's' || dropFast || speedCount++ == SPEED)//按下s 或 按下空格 或 自动下落
{
speedCount = 0;
onBottom = dropBlockShape(G_pBlockShape1, 0);//下落,true则无法下落
if(onBottom)
{
dropFast = false;
if(checkBlockReachTop())//检测是否到达边界顶点
{
FinishGame();
return 0;
}
addInBlockScreenArr(G_pBlockShape1);//将方块各个成员在全屏二维数组坐标中标记
checkBlockLineIsFull();//检测满行并清除
free(G_pBlockShape1);
//清除右侧小窗口中显示的方块
for (i = 0; i < 4; i++)
{
gotodelete(G_pBlockShape2->center.x + G_pBlockShape2->blockXY[i].x, G_pBlockShape2->center.y + G_pBlockShape2->blockXY[i].y * -1);
}
//将下一个方块置为当前移动的方块
G_pBlockShape1 = G_pBlockShape2;
G_pBlockShape1->center.x = GameX;
G_pBlockShape2->center.y -=2;
G_pBlockShape2 = NULL;
}
}
Sleep(100);
c = '\0';
}
return 0;
}
全篇完~各位兄弟留下一个赞再走呗!