【C语言】之实现俄罗斯方块游戏

实现思路:


关键点是使用闹钟信号,闹钟定时一段时间触发信号函数,在信号函数里对方块进行自动下落操作,而主线控制界面显示以及处理用户的输入。

共有两个文件 main.cdata.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]     = 
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值