这篇文章我们继续来看俄罗斯方块的复现过程:
目录
判断游戏是否结束
判断游戏是否结束,利用for循环对每一次的结果进行判断
//判断游戏是否结束
for ( j = 1; j < COL - 1; j++)
{
if (face.data[1][j] == 1) //顶层有方块存在(以第1行为顶层,不是第0行)
{
Sleep(1000); //留给玩家反应时间
system("cls"); //清空屏幕
color(7); //颜色设置为白色
CursorJump(2 * (COL / 3), ROW / 2 - 3);
if (grade>max)
{
printf("恭喜你打破最高记录,最高记录更新为%d", grade);
WriteGrade();
}
else if (grade == max)
{
printf("与最高记录持平,加油再创佳绩", grade);
}
else
{
printf("请继续加油,当前与最高记录相差%d", max - grade);
}
CursorJump(2 * (COL / 3), ROW / 2);
printf("GAME OVER");
while (1)
{
char ch;
CursorJump(2 * (COL / 3), ROW / 2 + 3);
printf("再来一局?(y/n):");
scanf("%c", &ch);
if (ch == 'y' || ch == 'Y')
{
system("cls");
main();
}
else if (ch == 'n' || ch == 'N')
{
CursorJump(2 * (COL / 3), ROW / 2 + 5);
exit(0);
}
else
{
CursorJump(2 * (COL / 3), ROW / 2 + 4);
printf("选择错误,请再次选择");
}
}
}
}
return 0; //判断结束,无需再调用该函数进行判断
}
游戏主体
在游戏主体中主要是对游戏的难度,游戏的按键进行编写,也可以在代码中对其修改。
/游戏主体逻辑函数
void StartGame()
{
int i,j;
int shape = rand() % 7, form = rand() % 4; //随机获取方块的形状和形态
while (1)
{
int t = 0;
int nextShape = rand() % 7, nextForm = rand() % 4; //随机获取下一个方块的形状和形态
int x = COL / 2 - 2, y = 0; //方块初始下落位置的横纵坐标
color(nextShape); //颜色设置为下一个方块的颜色
DrawBlock(nextShape, nextForm, COL + 3, 3); //将下一个方块显示在右上角
while (1)
{
color(shape); //颜色设置为当前正在下落的方块
DrawBlock(shape, form, x, y); //将该方块显示在初始下落位置
if (t == 0)
{
t = 15000; //这里t越小,方块下落越快(可以根据此设置游戏难度)
}
while (--t)
{
if (kbhit() != 0) //若键盘被敲击,则退出循环
break;
}
if (t == 0) //键盘未被敲击
{
if (IsLegal(shape, form, x, y + 1) == 0) //方块再下落就不合法了(已经到达底部)
{
//将当前方块的信息录入face当中
//face:记录界面的每个位置是否有方块,若有方块还需记录该位置方块的颜色。
for ( i = 0; i < 4; i++)
{
for ( j = 0; j < 4; j++)
{
if (block[shape][form].space[i][j] == 1)
{
face.data[y + i][x + j] = 1; //将该位置标记为有方块
face.color[y + i][x + j] = shape; //记录该方块的颜色数值
}
}
}
while (JudeFunc()); //判断此次方块下落是否得分以及游戏是否结束
break; //跳出当前死循环,准备进行下一个方块的下落
}
else //未到底部
{
DrawSpace(shape, form, x, y); //用空格覆盖当前方块所在位置
y++; //纵坐标自增(下一次显示方块时就相当于下落了一格了)
}
}
else //键盘被敲击
{
char ch = getch(); //读取keycode
switch (ch)
{
case DOWN: //方向键:下
if (IsLegal(shape, form, x, y + 1) == 1) //判断方块向下移动一位后是否合法
{
//方块下落后合法才进行以下操作
DrawSpace(shape, form, x, y); //用空格覆盖当前方块所在位置
y++; //纵坐标自增(下一次显示方块时就相当于下落了一格了)
}
break;
case LEFT: //方向键:左
if (IsLegal(shape, form, x - 1, y) == 1) //判断方块向左移动一位后是否合法
{
//方块左移后合法才进行以下操作
DrawSpace(shape, form, x, y); //用空格覆盖当前方块所在位置
x--; //横坐标自减(下一次显示方块时就相当于左移了一格了)
}
break;
case RIGHT: //方向键:右
if (IsLegal(shape, form, x + 1, y) == 1) //判断方块向右移动一位后是否合法
{
//方块右移后合法才进行以下操作
DrawSpace(shape, form, x, y); //用空格覆盖当前方块所在位置
x++; //横坐标自增(下一次显示方块时就相当于右移了一格了)
}
break;
case SPACE: //空格键
if (IsLegal(shape, (form + 1) % 4, x, y + 1) == 1) //判断方块旋转后是否合法
{
//方块旋转后合法才进行以下操作
DrawSpace(shape, form, x, y); //用空格覆盖当前方块所在位置
y++; //纵坐标自增(总不能原地旋转吧)
form = (form + 1) % 4; //方块的形态自增(下一次显示方块时就相当于旋转了)
}
break;
case ESC: //Esc键
system("cls"); //清空屏幕
color(7);
CursorJump(COL, ROW / 2);
printf(" 游戏结束 ");
CursorJump(COL, ROW / 2 + 2);
exit(0); //结束程序
case 's':
case 'S': //暂停
system("pause>nul"); //暂停(按任意键继续)
break;
case 'r':
case 'R': //重新开始
system("cls"); //清空屏幕
main(); //重新执行主函数
}
}
}
shape = nextShape, form = nextForm; //获取下一个方块的信息
DrawSpace(nextShape, nextForm, COL + 3, 3); //将右上角的方块信息用空格覆盖
}
}
从文件中读取
/从文件读取最高分
void ReadGrade()
{
FILE* pf = fopen("俄罗斯方块最高得分记录.txt", "r"); //以只读方式打开文件
if (pf == NULL) //打开文件失败
{
pf = fopen("俄罗斯方块最高得分记录.txt", "w"); //以只写方式打开文件(文件不存在可以自动创建该文件)
fwrite(&grade, sizeof(int), 1, pf); //将max写入文件(此时max为0),即将最高历史得分初始化为0
}
fseek(pf, 0, SEEK_SET); //使文件指针pf指向文件开头
fread(&max, sizeof(int), 1, pf); //读取文件中的最高历史得分到max当中
fclose(pf); //关闭文件
pf = NULL; //文件指针及时置空
}
更新最高分数
//更新最高分到文件
void WriteGrade()
{
FILE* pf = fopen("俄罗斯方块最高得分记录.txt", "w"); //以只写方式打开文件
if (pf == NULL) //打开文件失败
{
printf("保存最高得分记录失败\n");
exit(0);
}
fwrite(&grade, sizeof(int), 1, pf); //将本局游戏得分写入文件当中(更新最高历史得分)
fclose(pf); //关闭文件
pf = NULL; //文件指针及时置空
}
从文件中读取最高分数和更新最高分数这两个并不影响程序的完整性,主要是关于文件方面的操作我也不是太熟悉,是搭档完成的这一部分。
完整的代码
接下来是完整的代码,这些代码加上注释确实有点多,就用链接的形式呈上了。
如果有什么问题的话欢迎指出。接下来会对opencv进行学习。