实现思路:
关键点是使用闹钟信号,闹钟定时一段时间触发信号函数,在信号函数里对方块进行自动下落操作,而主线控制界面显示以及处理用户的输入。
共有两个文件 main.c
和 data.h
,需要把两个文件放到同一目录下,直接在该目录下执行命令:
gcc main.c -o main
注意:如果编译的时候提示没有或者找不到 data.h 这个文件的话:
- 1、确保两个文件是在同一路径下并检查 data.h 这个文件的命名是否正确(有时候你的data.h后面可能多了个空格或者其它空白字符)导致这个文件找不到;
- 2、实在是解决不了的话,直接把 data.h 里面的数据复制到 main.c 文件的
#include "data.h"
下面并去掉#include "data.h"
这句代码
提示:如果中途遇到问题,可以留言评论,我有时间上线看到之后会回复大家的疑惑(但我的空闲时间有限,并不是所有问题都会回复,代码一定是完整、可以正常运行的,至于自己的电脑为什么起不来,就需要自己学会找一下问题了),同时也希望大家看完后认真学习一下代码的思路(代码里面的注释已经非常详细了),只有这样大家才能有所进步!
代码:
main.c (这是主程序,需要用到下面的 data.h
文件)
/*
* 文件名称: main.c
* 功能:实现俄罗斯方块小游戏
* 编写人:王廷云
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "data.h"
#define ROW 21 // 游戏区域的行数
#define COL 18 // 游戏区域的列数
/* 按键枚举 */
enum key {
DOWN, // 上
LEFT, // 左
RIGHT, // 右
CHANGE, // 变化
STOP, // 停止
EXIT, // 退出
UNKNOW, // 未知
};
/***** 函数声明区域 ******/
void initalGameArea(void); // 初始化游戏区域
void drawBlock(char bl[NR][NR]); // 画方块
void cleanBlock(char bl[NR][NR]); // 清除方块
void turnBlock(char bl[NR][NR]); // 旋转方块
void gameEnd(void); // 结束游戏
void gameStop(void); // 暂停游戏
void showGame(void); // 显示游戏
void gameSelf(int signo); // 游戏自动运行
void checkDeleteLine(void); // 检查是否满一行
void checkGameOver(char bl[NR][NR]); // 检查是否游戏结束
int checkMove(char bl[NR][NR], int flag); // 检查方块是否可移动
int getInput(void); // 获取输入
/* 全局变量区域 */
static char gameArea[ROW][COL] = {
0}; // 游戏区域数据
static int startX = 7, startY = 6; // 方块出现的起始位置
static int type = 0; // 方块当前类型
static int nextType = 0; // 方块的下一种类型
static int diret = 0; // 方块的方向
char *state = "\033[32m游戏中...\033[0m"; // 游戏运行状态
static unsigned int level = 0; // 游戏等级
static unsigned int score = 0; // 游戏分数
static unsigned int maxScore = 0; // 游戏最高记录
static FILE *fp = NULL; // 用于把记录保存到文件
/*
* 主函数:控制全局流程
*/
int main(void)
{
/*
* 设置闹钟:
* 当前时间间隔为0.7秒,下一次时间间隔为0.7秒
*/
struct itimerval timer = {
{
0,700000},{
0,700000}};
setitimer(ITIMER_REAL, &timer,NULL);
/* 初始化游戏区域 */
initalGameArea();
/* 设置游戏信号 */
signal(SIGALRM, gameSelf);
/* 初始化方块类型 */
srand(time(NULL));
type = rand()%7;
nextType = rand()%7;
/* 读取文件的最高记录 */
fp = fopen("./record","r+");
if (NULL == fp)
{
/*
* 文件不存在则创建并打开
* "w"方式打开会自动创建不存在的文
*/
fp = fopen("./record","w");
}
fscanf(fp,"%u",&maxScore);
/* 用户操作 */
int key;
while (1)
{
key = getInput();
switch (key)
{
case RIGHT : checkMove(bl[type][diret],RIGHT);
break;
case LEFT : checkMove(bl[type][diret],LEFT);
break;
case DOWN : checkMove(bl[type][diret],DOWN);
break;
case CHANGE: turnBlock(bl[type][(diret+1)%4]);
break;
case STOP : gameStop();
break;
case EXIT : gameEnd();
break;
case UNKNOW: continue;
}
/* 画方块 */
drawBlock(bl[type][diret]);
/* 显示游戏 */
showGame();
/* 清除方块 */
cleanBlock(bl[type][diret]);
}
return 0;
}
/*
* 函数名:initalGameArea
* 函数功能:初始化游戏区域
* 参数:无
* 返回值:无
*/
void initalGameArea(void)
{
int i;
/* 屏幕设置 */
printf("\033[2J"); // 清屏
system("stty -icanon"); // 关缓冲
system("stty -echo"); // 关回显
fprintf(stdout,"\033[?25l"); // 关闭鼠标显示
/* 初始化行 */
for (i = 0; i < COL; i++)
{
gameArea[0][i] = 8; // 第0行
gameArea[5][i] = 8; // 第5行
gameArea[ROW-1][i] = 8; // 最后一行
}
/* 初始化列 */
for (i = 0; i < ROW; i++)
{
gameArea[i][0] =