C语言实现俄罗斯方块代码

导读:本篇文章讲解 C语言实现俄罗斯方块代码,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

这里为大家敲写一段怎样用C语言实现俄罗斯方块:
首先推荐大家使用CodeBlocks这个软件,方便添加不同的工程。
代码中有很多注释便于理解!
下面是效果图和全部的代码以及注释,大家可以观看并自己新增内容!

在这里插入图片描述

1:

首先是main.c文件:

#include <stdio.h>
#include <stdlib.h>
#include "game.h"

int main()
{
    gameInit();
    return 0;
}

2:

然后是mywindows.h文件:

#ifndef MYWINDOWS_H_INCLUDED
#define MYWINDOWS_H_INCLUDED

// 封装系统函数-系统调用模块
#include <windows.h>

// 初始化句柄
extern void initHandle();

// 设置颜色
extern void setColor(int color);

// 设置光标位置
extern void setPos(int x, int y);

// 设置光标是否可见
extern void setCursorVisible(int flag);

// 关闭句柄
extern void closeHandle();




#endif // MYWINDOWS_H_INCLUDED

3:

接下来是mywindows.c文件:

#include "mywindows.h"

HANDLE handle;

// 初始化句柄
void initHandle()
{
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
}

// 设置颜色
void setColor(int color)
{
    SetConsoleTextAttribute(handle, color);
}

void setPos(int x, int y)
{
    //, ,
    COORD coord = {x*2, y};
    SetConsoleCursorPosition(handle, coord);
}

// 设置光标是否可见
void setCursorVisible(int flag)
{
    CONSOLE_CURSOR_INFO info;
    info.bVisible = flag;   //光标是否可见
    info.dwSize = 100;      //光标宽度1-100
    SetConsoleCursorInfo(handle, &info);
}

// 关闭句柄
void closeHandle()
{
    CloseHandle(handle);
}


4:

下面是data.h文件,也就是数据库的存储地址:

#ifndef DATA_H_INCLUDED
#define DATA_H_INCLUDED


//函数声明\变量声明
// 存储数据-数据模块
//界面数组
extern int windowShape[25][26];

extern int block[7][4][4][4];

#endif // DATA_H_INCLUDED

5:

数据库内容:data.c

#include "data.h"

//函数的定义

int windowShape[25][26] =
{
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};// 边框为1,游戏池长度为14


int block[7][4][4][4] =
{
    {
        //Z{}
        {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
        {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
        {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
        {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}
    },
    {
        //S
        {{0,1,1,0},{1,1,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,1,1,0},{1,1,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}}
    },
    {
        //L{}
        {{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}},
        {{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},
        {{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},
        {{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}
    },
    {
        //J
        {{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},
        {{1,0,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
        {{1,1,0,0},{1,0,0,0},{1,0,0,0},{0,0,0,0}},
        {{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}}
    },
    {
        //I{}
        {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
        {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},
        {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
        {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}
    },
    {
        //T
        {{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}},
        {{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
        {{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
        {{1,0,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}
    },
    {
        //田
        {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
        {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
        {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
        {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}
    }


};

6:

游戏头部:game.h:

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

// 游戏逻辑模块

#include <stdio.h>
#include <time.h>

typedef struct{
    int x;
    int y;
    int shape;
    int status;
    int color;
}BLOCK;

// 定义当前正在下落的方块,和下一个方块
BLOCK curBlock;
BLOCK nextBlock;

// 绘制游戏池边框
extern void gamePool(int x, int y);

// 打印操作说明
extern void printRule();

// 打印分数和等级
extern void printGradeLevel(int num);

// 游戏计时
extern void gameTime(clock_t startTime);

// 打印一个方块
extern void printBlock(int x, int y, int shape, int status, int color);

// 删除一个方块
extern void delBlock(int x, int y, int shape, int status);

//方块左移
extern void leftBlock();

//方块右移
extern void rightBlock();

//方块下移
extern int downBlock();

//方块变形
extern void changeBlock();

//方块直接落底
extern void bottomBlock();

//游戏暂停
extern void pause();

//随机产生游戏第一个方块
extern void startBlock();

//随机产生下一个方块
extern void blockNext();

//拷贝方块:把下一个方块变成当前正在下落的方块
extern void copyBlock();

//碰撞检测
extern int crash(int x, int y, int shape, int status);

//保存方块
extern void saveBlock();

//刷新游戏池
extern void updateGamePool();

//消行检测
extern void lineClear();

//消行下移
extern void lineDown(int line);

// 初始化游戏
extern void gameInit();










#endif // GAME_H_INCLUDED

7:

最后一部分,游戏内容,game.c文件:

#include "game.h"
#include "mywindows.h"
#include "data.h"
#include <conio.h>

int level = 1;
int grade = 100;

// 打印游戏池
void gamePool(int x, int y)
{
    int i, j;
    for(i=0;i<25;i++)
    {
        for(j=0;j<26;j++)
        {
            if(windowShape[i][j] == 1)
            {
                setColor(0xc0);
                setPos(x+j,y+i);
                printf("  ");   // printf("%2s", "");
            }
        }
    }
}

// 打印操作说明
void printRule()
{
    setColor(0x0f);
    setPos(31, 9);
    printf("操作规则:");
    setPos(32, 11);
    printf("按a或A左移");
    setPos(32, 12);
    printf("按d或D右移");
    setPos(32, 13);
    printf("按s或S下移");
    setPos(32, 14);
    printf("按w或W变形");
    setPos(32, 15);
    printf("按空格暂停");
    setPos(32, 16);
    printf("按回车直接下落");

}

void printGradeLevel(int num)
{
    switch(num)
    {
        case 0: break;
        case 1: grade += 10;break;
        case 2: grade += 25;break;
        case 3: grade += 50;break;
        case 4: grade += 70;break;
    }

    //等级-->作业

    setColor(0x09);
    setPos(3,6);
    printf("分数:%d", grade);

    setColor(0x0a);
    setPos(3,7);
    printf("等级:%d", level);
}

void gameTime(clock_t startTime)
{
    //clock_t endTime = clock();
    //clock_t ti = (endTime-startTime)/CLOCKS_PER_SEC;
    setColor(0x0d);
    setPos(3,8);
    printf("本次游戏运行时间:%ld", (clock()-startTime)/CLOCKS_PER_SEC);
}

// 打印一个方块
void printBlock(int x, int y, int shape, int status, int color)
{
    int i,j;
    setColor(color);
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            if(1 == block[shape][status][i][j])
            {
                setPos(x+j,y+i);
                printf("■");
            }
        }
    }
}

// 删除一个方块
void delBlock(int x, int y, int shape, int status)
{
    int i, j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            if(1 == block[shape][status][i][j])
            {
                setPos(x+j,y+i);
                printf("  ");   //打印两个空格
            }
        }
    }
}

//方块左移
void leftBlock()
{
    //已经显示的方块删除,改变坐标,重新打印
    if(crash(curBlock.x-1, curBlock.y, curBlock.shape,curBlock.status) == -1)
    {
        return;
    }
    delBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status);
    curBlock.x -= 1;
    printBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status,curBlock.color);
}

//方块右移
void rightBlock()
{
    if(crash(curBlock.x+1, curBlock.y, curBlock.shape,curBlock.status) == -1)
    {
        return;
    }
    delBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status);
    curBlock.x += 1;
    printBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status,curBlock.color);
}

//方块下移
int downBlock()
{
    if(crash(curBlock.x, curBlock.y+1,curBlock.shape,curBlock.status) == -1)
    {
        //落到游戏池底部,产生新方块
        saveBlock();
        lineClear();
        updateGamePool();
        copyBlock();
        return -1;
    }else if(crash(curBlock.x, curBlock.y+1,curBlock.shape,curBlock.status) == -2)
    {
        //游戏结束
        return -2;
    }else{
        delBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status);
        curBlock.y += 1;
        printBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status,curBlock.color);
        return 0;
    }

}

//方块变形
void changeBlock()
{
    if(crash(curBlock.x, curBlock.y, curBlock.shape, (curBlock.status+1)%4) == -1){
        return;
    }
    delBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status);
    curBlock.status = (curBlock.status+1)%4;
    printBlock(curBlock.x,curBlock.y,curBlock.shape,
             curBlock.status,curBlock.color);
}

//方块直接落底
void bottomBlock()
{
    while(1){
        //流程参考方块下落
        if(downBlock() !=0){
            return;
        }
    }
}

//游戏暂停
void pause()
{
    //
}

//随机产生游戏第一个方块
void startBlock()
{
    //设置时间为随机数种子
    srand((unsigned)time(NULL));
    //初始化curBlock
    curBlock.x = 22;
    curBlock.y = 1;
    //rand取一个随机整数
    curBlock.shape = rand()%7;    //0-6
    curBlock.status = rand()%4;   //0-3
    curBlock.color = rand()%0x10;
    if(0x00 == curBlock.color)
    {
        curBlock.color = 0x0f;
    }
    printBlock(curBlock.x, curBlock.y, curBlock.shape,
               curBlock.status, curBlock.color);
}

//随机产生下一个方块
void blockNext()
{
    //初始化nextBlock
    delBlock(nextBlock.x,nextBlock.y,
               nextBlock.shape,nextBlock.status);
    nextBlock.x = 34;
    nextBlock.y = 2;
    nextBlock.shape = rand()%7;
    nextBlock.status = rand()%4;
    nextBlock.color = rand()%0x10;
    if(0x00 == nextBlock.color)
    {
        nextBlock.color = 0x0f;
    }
    printBlock(nextBlock.x,nextBlock.y,
               nextBlock.shape,nextBlock.status,nextBlock.color);
}

//拷贝方块:把下一个方块变成当前正在下落的方块
void copyBlock()
{
    //当前方块=下一个方块
    curBlock = nextBlock;
    curBlock.x = 22;
    curBlock.y = 1;
    printBlock(curBlock.x, curBlock.y, curBlock.shape,
               curBlock.status, curBlock.color);
    blockNext();
}

//碰撞检测
//x,y为方块的下一个位置, status下一种形态
//碰撞返回-1,未碰撞返回0, 游戏结束返回-2
int crash(int x, int y, int shape, int status)
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            if(block[shape][status][i][j] == 1)
            {
                if(windowShape[i+y][j+x-15] == 1)
                {
                    //方块一产生就发生碰撞
                    if(curBlock.x == 22 && curBlock.y == 1)
                    {
                        return -2;
                    }
                    return -1;
                }
            }
        }
    }
    return 0;
}

//保存方块
void saveBlock()
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            if(block[curBlock.shape][curBlock.status][i][j] == 1)
            {
                windowShape[i+curBlock.y][j+curBlock.x-15] = 1;
            }
        }
    }
}

//刷新游戏池
void updateGamePool()
{
    int i,j;
    //从下到上刷新游戏池
    for(i=23;i>0;i--)
    {
        for(j=1;j<15;j++)
        {
            if(windowShape[i][j] == 1)
            {
                setColor(0x0e);
                setPos(j+15,i);
                printf("■");
            }else{
                setColor(0x00);
                setPos(j+15,i);
                printf("  ");
            }
        }
    }
}

//消行检测
//检测满行->这一行所有值都为1
void lineClear()
{
    int i,j;
    int num = 0;    //统计一次消行数目
    for(i=23;i>0;i--)
    {
        int total = 0;
        for(j=1;j<15;j++)
        {
            total += windowShape[i][j];
        }
        if(total == 14)
        {
            //满行
            lineDown(i);
            i += 1;
            num += 1;
        }
    }
    printGradeLevel(num);
}

//消行下移
//从满行的这行开始,上面所有行顺序下移
void lineDown(int line)
{
    int i,j;
    for(i=line;i>1;i--)
    {
        for(j=1;j<15;j++)
        {
            windowShape[i][j] = windowShape[i-1][j];
        }
    }
}


// 初始化游戏
void gameInit()
{
    //第一步,必须初始化句柄
    //clock_t startTime = clock();
    initHandle();
    setCursorVisible(FALSE);

    gamePool(15,0);
    printRule();
    printGradeLevel(0);

    startBlock();
    blockNext();
    //定时开始时间,结束时间,通过控制时间差实现定时
    clock_t start,stop;
    start = clock();

    while(1)        //for(;;)
    {
        //检测是否有按键按下
        if(kbhit())
        {
            switch(getch())
            {
            case 'a':
            case 'A':
            case 75:
                leftBlock();break;
            case 'd':
            case 'D':
            case 77:
                rightBlock();break;
            case 's':
            case 'S':
            case 80:
                downBlock();break;
            case 'w':
            case 'W':
            case 72:
                changeBlock();break;
            case 32:
                pause();break;
            case 13:
                bottomBlock();break;
            }
        }
        //获取时间
        stop = clock();
        if(stop-start>0.5*CLOCKS_PER_SEC)
        {
            downBlock();
            //重新计时
            start = stop;
        }
    }
}






好,到现在这个游戏也就结束了!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/81124.html

(1)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!