C语言实现一个简单的俄罗斯方块小游戏

使用dev c++
直接上代码:
程序分两部份,其中各类函数声明在.h文件

.h 文件

#ifndef DAY2_H_INCLUDED
#define DAY2_H_INCLUDED
//#include <string.h>
#include <windows.h>
#include <time.h>
#include <stdbool.h>
#include <conio.h>



//定义游戏区域大小
#define col_begin  2
#define col_end    14
#define row_begin  4
#define row_end    26
//定义句柄变量
HANDLE consoleoutpt;

//定义一个结构体Data,存储游戏数据
typedef struct DATA{
  unsigned int pool[28];//游戏池深度28 宽度16 包含边界
  int x;//当前正在下落方块的左上角坐标
  int y;//当前同上
  int type[3];//当前,下一个,下下一个方块类型
  int revolve[3];//当前,下一个,下下一个方块旋转状态
  unsigned int score;//得分
  unsigned int erasetotal;//消行总数
  unsigned int erasestatistics[4];//不同数量行数一并消去次数统计
  unsigned int tetristotal;//方块总数统计
  unsigned int tetristatistics[7];//不同形状方块统计
  bool dead;//游戏失败,结束
}Data;

//control结构体存储游戏相关控制数据
typedef struct tetriscontrol{
    int direction;//移动方向,值为0左移值为1右移
    bool revolvedirection;//旋转方向,值为TURE顺时针,FALSE逆时针
    bool pause;//暂停
    int color[28][16];//游戏池内28行16列每格的颜色
}Control;

//7种方块的每种的旋转状态(4个状态)
static const int tetrisstate[7][4] =
{
    { 0X00F0, 0X2222, 0X00F0, 0X2222 },  // I型
    { 0X0072, 0X0262, 0X0270, 0X0232 },  // T型
    { 0X0223, 0X0074,  0X0622, 0X0170},  // L型
    { 0X0644, 0X0710, 0X0226, 0X0470 },  // J型
    { 0X0360, 0X0462, 0X0360, 0X0462 },  // Z型
    { 0X0630, 0X0264, 0X0630, 0X0264 },  // S型
    { 0X0660, 0X0660, 0X0660, 0X0660 }   // O型
};
//游戏池初始状态 游戏池边界每一格设为1,游戏池内全设为0,转化为16进制数
static const unsigned gamepooltetris[28] =
    {
        0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,
        0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,
        0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,
        0XC003,0XC003,0XFFFF,0XFFFF
    };


//全角定位函数
void fullposition( short x, short y );

//按键信息提示函数
void prekeyinfo();

//显示游戏池边界
void gamepoolboundary();

//得分信息显示
void scoreinfo( const Data *s_data );

//下一、下下一方块
void nexttetris();

//初始化游戏
void initgame( Data *s_data,Control *control );

//开始游戏
void startgame( Data *s_data,Control *control );

//显示游戏池
void printgamepool( Data *s_data,Control *control );

//初始化方块
void inittetris( Data *s_data );

//插入方块
void inserttetris( Data *s_data );

//设置游戏池方块颜色
void setpoolcolor(const Data *s_data,Control *control );

//显示当前方块
void printcurrenttetris( const Data *s_data,Control *control );

//碰撞检测
bool crashtetris(const Data *s_data );

//向下移动方块
void movedowntetris( Data *s_data,Control *control );

//运行游戏
void rungame( Data *s_data,Control *control );

//水平移动方块
void horizontalmove( Data *s_data,Control *control );

//按键控制方块
void keydowncontrol( Data *s_data,Control *control,int key );

//消行检测
bool checkerase( Data *s_data,Control *control );

//旋转方块
void revolvetetris( Data *s_data,Control *control );

//方块直接落地
void dropdowntetris( Data *s_data,Control *control );

//再来一次
bool playagain();

#endif // DAY2_H_INCLUDED




.c文件

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

#include "day.h"

int main()
{
    Data s_data;
    Control control;

    //初始化游戏
    initgame( &s_data,&control );
    //函数调用
	//nexttetris( &s_data );
    //printgamepool( &s_data,&control );
	
	
   do
    {
         prekeyinfo();
         gamepoolboundary();
         //scoreinfo( &s_data );
         //运行游戏
	     rungame( &s_data,&control );
	     if( playagain() )//是否再来一次
         {
             //定位,清屏
             SetConsoleTextAttribute( consoleoutpt,0x7 );
             system( "cls" );//清屏
             //重新开始游戏
             startgame( &s_data,&control );
         }else
         {
             break;
         }
         // Sleep( 40 );
    }while(1);
    fullposition( 0,0 );
    //关闭句柄
    CloseHandle( consoleoutpt );


    return 0;
}

//初始化游戏
void initgame( Data *s_data,Control *control )
{
    //设置控制台标题
    SetConsoleTitle( "俄罗斯块块" );
    //获取标准输出句柄
    consoleoutpt = GetStdHandle( STD_OUTPUT_HANDLE );
    //定义光标隐藏变量,并初始化
    CONSOLE_CURSOR_INFO info;//定义变量info
    //初始化
    info.bVisible = FALSE;//光标隐藏
    info.dwSize   = 1;//光标厚度为1
    //设置光标隐藏
    SetConsoleCursorInfo( consoleoutpt , &info );

    //开始游戏
    startgame( s_data,control );


}



//全角定位函数
void fullposition( short x, short y )
{
    static COORD pos;
    pos.X = 2*x;//之所以左、右移1,像素点总距离变2,是在windows命令提示窗口中,需要两个单位x和
                //一个单位y才能组成一个小方块形状,即是两个单位x变化1
    pos.Y = y;  //下移一,像素点变1
    SetConsoleCursorPosition( consoleoutpt,pos );
}

//按键信息提示函数
void prekeyinfo()
{
    //设置输出字体 颜色
    SetConsoleTextAttribute( consoleoutpt,0xc );
    //设置位置信息
    fullposition( 33,10 );
    printf( "?控制:");
    fullposition( 34, 12 );
    printf( "□向左移动:← A " );
    fullposition( 34, 13 );
    printf( "□向右移动:→ D " );
    fullposition( 34, 14 );
    printf( "□向下移动:↓ S " );
    fullposition( 34, 15 );
    printf( "□顺时针转:↑ W " );
    fullposition( 34, 16 );
    printf( "□逆时针转:0" );
    fullposition( 34, 17 );
    printf( "□直接落地:空格" );
    fullposition( 34, 18 );
    printf( "□暂停游戏:回车" );
}

//显示游戏池边界
void gamepoolboundary()
{
    int y;//打印纵线需要纵坐标y
    //确定颜色 0xf0
    SetConsoleTextAttribute( consoleoutpt,0XF0 );
    for( y=row_begin;y<row_end;y++ )//打印纵线
    {
    //确定初始打印位置
    fullposition( 10,y-3);/*//注意此处/*/
    printf("%2s","");
    fullposition( 23,y-3);
    printf("%2s","");
    }
    //确定初始打印位置
    fullposition( 10,y-3 );
    printf("%28s","");
}

//得分信息显示
void scoreinfo( const Data *s_data )
{
    //int i;//控制循环,输出数组
    static const char Tetris[8] = "ITLJZSO";//定义静态字符数组保存方块类型
    //空间全部置零
    //memset( s_data,0,sizeof(Data) );
	fullposition( 2,2 );
    //设置颜色
    SetConsoleTextAttribute( consoleoutpt,0XE );
    
    printf( "■得分:%u",s_data->score );
    fullposition( 2,6 );
    printf( "消行总数:%u",s_data->erasetotal );
    fullposition( 2,8 );
    printf( "|消去1:%u",s_data->erasestatistics[0] );
    fullposition( 2,9 );
    printf( "|消去2:%u",s_data->erasestatistics[1] );
    fullposition( 2,10 );
    printf( "|消去3:%u",s_data->erasestatistics[2] );
    fullposition( 2,11 );
    printf( "|消去4:%u",s_data->erasestatistics[3] );
    fullposition( 2,15 );
    printf( "■方块总数:%u",s_data->tetristotal );
    fullposition( 2,17 );
    printf( "□I形:%u" ,s_data->tetristatistics[0] );
    fullposition( 2,18 );
    printf( "□T形:%u" ,s_data->tetristatistics[1] );
    fullposition( 2,19 );
    printf( "□L形:%u" ,s_data->tetristatistics[2] );
    fullposition( 2,20 );
    printf( "□J形:%u" ,s_data->tetristatistics[3] );
    fullposition( 2,21 );
    printf( "□Z形:%u" ,s_data->tetristatistics[4] );
    fullposition( 2,22 );
    printf( "□S形:%u" ,s_data->tetristatistics[5] );
    fullposition( 2,23 );
    printf( "□O形:%u" ,s_data->tetristatistics[6] );
}

//下一、下下一方块
void nexttetris( Data *s_data )
{
    int i;//循环输出
    unsigned int tetris;//用于储存下一,下下一方块状态
    //提示边框
    int y;//输出纵向条
    SetConsoleTextAttribute( consoleoutpt,0X0B );
    fullposition( 26,1 );
    printf( "¥¥¥¥¥¥¥¥¥¥¥" );
    
    //for( y=3;y<7;y++ )
    //{
        fullposition( 26,2 );
        printf( "¥%8s¥%8s¥","","");
        fullposition( 26,3 );
        printf( "¥%8s¥%8s¥","","");
        fullposition( 26,4 );
        printf( "¥%8s¥%8s¥","","");
        fullposition( 26,5 );
        printf( "¥%8s¥%8s¥","","");
		fullposition( 26,6 );
        printf( "¥¥¥¥¥¥¥¥¥¥¥" );
    //}
    //输出提示图形
    //srand( (unsigned)time(NULL) );
    //打印下一个方块
    //s_data->type[1] = rand() % 7;//产生0 1 2 3 4 5 6共七个随机数
    //s_data->revolve[1] = rand() % 4;//0 1 2 3
    //调取方块种类和旋转状态
    tetris = tetrisstate[ s_data->type[1] ][ s_data->revolve[1] ];
    //设置颜色 高亮
    SetConsoleTextAttribute( consoleoutpt,s_data->type[1]|8 );
    //打印提示图形
    //(34,3)(35,3)(36,3)(37,3)
    //(34,4)(35,4)(36,4)(37,4)
    //(34,5)(35,5)(36,5)(37,5)
    //(34,6)(35,6)(36,6)(37,6)
    for( i=0;i<16;i++ )
    {
        fullposition( 27+i%4,2+i/4 );//定位  注意方法
        if( (tetris>>i)&1)
            printf( "■" );
        else
            printf( "%2s","" );

    }
    //打印下下一个方块 不设置颜色 仅高亮
    //s_data->type[2] = rand() % 7;//产生0 1 2 3 4 5 6共七个随机数
    //s_data->revolve[2] = rand() % 4;//0 1 2 3
    //调取方块种类和旋转状态
    tetris = tetrisstate[ s_data->type[2] ][ s_data->revolve[2] ];
    SetConsoleTextAttribute( consoleoutpt,0x8 );
    for( i=0;i<16;i++ )
    {
        fullposition( 32+i%4,2+i/4 );
        if( (tetris>>i)&1)
            printf( "■" );
        else
            printf( "%2s","" );
    }

}

//开始游戏
void startgame( Data *s_data,Control *control )
{
    //初始化相关数据:存储游戏数据,游戏操作控制数据
    //初始化存储游戏数据
    //空间全部置零
    memset( s_data,0,sizeof(Data) );
    //初始化游戏池
    memcpy( s_data->pool,gamepooltetris,sizeof(unsigned int[28]) );
    //初始化游戏操作控制数据 内存置0
    memset( control,0,sizeof(Control) );
    //初始化下一方块
    srand( (unsigned)time(NULL) );//生成随机数种子
    s_data->type[1] = rand() % 7;//随机下一生成方块形状
    s_data->revolve[1] = rand() % 4;//随机生成下下一旋转状态
    //初始化下下一方块
    s_data->type[2] = rand() % 7;//随机下下一生成方块形状
    s_data->revolve[2] = rand() % 4;//随机生成下下一旋转状态
    //初始化方块
    inittetris( s_data );
    //设置游戏池方格颜色
	setpoolcolor( s_data,control );

}

#define infullposition(x,y) fullposition(x+9,y-3)
//显示游戏池
void printgamepool( Data *s_data,Control *control )
{
    int x,y;//横纵坐标
    for( y=row_begin;y<row_end;y++ )
    {
        //方块入池位置
        infullposition(2,y);//11,1
        for( x=col_begin;x<col_end;x++ )
        {
            //设置方块颜色

            if( (s_data->pool[y]>>x)&1 )
			{   SetConsoleTextAttribute( consoleoutpt,control->color[y][x] );
                printf( "■" );
            }
            else
            {
                //没有方块显示空白
                SetConsoleTextAttribute( consoleoutpt,0 );
                printf( "%2s","" );
            }
        }
    }
}

//初始化方块
void inittetris( Data *s_data )
{    //下一方块变为当前方块
    s_data->type[0] = s_data->type[1];
    s_data->revolve[0] = s_data->revolve[1];
    //下下一方块变为下一方块
    s_data->type[1] = s_data->type[2];
    s_data->revolve[1] = s_data->revolve[2];
    //随机生成下下一个方块
    s_data->type[2] = rand()%7;
    s_data->revolve[2] = rand()%4;
    s_data->x = 6;  //相对位置
    //s_data->y = 4;  //绝对位置
    s_data->y = 0;
    //检测是否有碰撞
    if(crashtetris( s_data ))
    {
        //有碰撞
        s_data->dead = true;
    }
    else
        //没有碰撞
        //插入方块
        inserttetris( s_data );
        s_data->tetristotal++ ;  //方块总数
        s_data->tetristatistics[s_data->type[0]]++ ;//方块种类统计
        //显示下一方块
        nexttetris( s_data );
        //显示得分信息
        scoreinfo( s_data );
    
    
    //插入方块
   // inserttetris( s_data );
    //设置游戏池方块颜色
    //setpoolcolor( s_data,control );
}

//插入方块
void inserttetris( Data *s_data )
{
    //当前方块tetrisstate[ s_data->type[0] ][ s_data->revovle[0]]
    unsigned int tetris = tetrisstate[ s_data->type[0] ][ s_data->revolve[0]];
    s_data->pool[s_data->y+0] |= (((tetris>>0x0)&0x000f)<<s_data->x);
    s_data->pool[s_data->y+1] |= (((tetris>>0x4)&0x000f)<<s_data->x);
    s_data->pool[s_data->y+2] |= (((tetris>>0x8)&0x000f)<<s_data->x);
    s_data->pool[s_data->y+3] |= (((tetris>>0xc)&0x000f)<<s_data->x);

}

//设置游戏池方块颜色
void setpoolcolor( const Data *s_data,Control *control )
{
    //显示颜色前需要先判断是否有方块,有再显示颜色
    //此函数仅设置颜色,无需清楚方块
    //当初始化方块时或移动方块时调用
    int i;//控制循环,便于定位
    int x,y;//待设置的行列
    //当前的方块
    unsigned int tetris;
    tetris = tetrisstate[ s_data->type[0] ][ s_data->revolve[0]];
    for( i=0;i<16;i++ )
    {
        y = s_data->y+i/4;
        if( y>row_end )
          break;
        x = s_data->x+i%4;
        if( (tetris>>i)&1 )
          control->color[y][x] = s_data->type[0]|8;
    }
}

//显示当前方块
void printcurrenttetris( const  Data *s_data,Control *control ) 
{
    //方块不会向上移动,故不需要向下扩展
    int x,y;//用于扩展方块移动后的行数//记录方块移动后的坐标
    //若方块向左/右移动一格,则要向右或左扩展一格,即横向扩展两格
    if( s_data->y>row_begin )
        y = s_data->y-1;
    else
        y = row_begin;
    for( ;y<row_end && y<s_data->y+4;y++ )
    {
        if( s_data->x>col_begin )
            x = s_data->x-1;
        else
            x = col_begin;
        for( ;x<col_end && x<s_data->x+5;x++ )
        {
            //定位到游戏池中
            infullposition( x,y );
            //游戏池中的方块的定点确定
            if( (s_data->pool[y]>>x)&1)
            {
                //设置颜色
                SetConsoleTextAttribute( consoleoutpt,control->color[y][x] );
                printf( "■" );
            }
            else
            {
                SetConsoleTextAttribute( consoleoutpt,0 );
                printf( "%2s","" );
            }
        }
    }
}

//移除方块
void movetetris( Data *s_data )
{
    //当前方块
    unsigned int tetris = tetrisstate[s_data->type[0]][s_data->revolve[0]];
    //移除当前方块即将当前方块的16位二进制数取反,再与原游戏池内该位置上
    //方块与运算,即可全部置零
    s_data->pool[ s_data->y+0 ] &= ~(((tetris>>0x0)&0x000f)<<s_data->x);
    s_data->pool[ s_data->y+1 ] &= ~(((tetris>>0x4)&0x000f)<<s_data->x);
    s_data->pool[ s_data->y+2 ] &= ~(((tetris>>0x8)&0x000f)<<s_data->x);
    s_data->pool[ s_data->y+3 ] &= ~(((tetris>>0xc)&0x000f)<<s_data->x);
}

//碰撞检测
bool crashtetris( const Data *s_data )
{
    //当前方块
    unsigned int tetris = tetrisstate[s_data->type[0]][s_data->revolve[0]];
    //游戏池内的方块
    unsigned int dest = 0;//初始化
    //获取当前方块在游戏池中的位置
    //游戏池中x,y处小方格信息,按低位到高位存放在16位二进制的无符号数中
    dest |= (((s_data->pool[ s_data->y+0 ]>>s_data->x)<<0x0)&0x000f );//与第0行做按位或运算(有一为真即为真)
    dest |= (((s_data->pool[ s_data->y+1 ]>>s_data->x)<<0x4)&0x00f0 );
    dest |= (((s_data->pool[ s_data->y+2 ]>>s_data->x)<<0x8)&0x0f00 );
    dest |= (((s_data->pool[ s_data->y+3 ]>>s_data->x)<<0xc)&0xf000 );
    //上面的操作是将游戏池中的方格型二进制码先右移到最右端,再左移到横条行二进制码上应有的位置处
    //dest 是通过或预算得到的16位二进制码
    //每一行游戏池1100 0000 0000 0000 0011
    //最后一行1111 1111 1111 1111 1111
    //检测碰撞就是将游戏池方块转化成16位二进制数,再与当前方块进行位于运算
    //若运算结果存在重叠,即结果只要有一不为0,则产生碰撞,不可移动
    return ((dest&tetris) != 0);
}

//向下移动方块
void movedowntetris( Data *s_data,Control *control )
{
    int y = s_data->y;//用于记录原行位置
    //调用移除函数,移除当前方块
    movetetris( s_data );
    //向下移动
    s_data->y++ ;
    //检测是否有碰撞
    //若有碰撞,则要恢复到下落前位置,插入当前方块,由于位置没变,无需设置颜色
    if( crashtetris( s_data ) )//检测碰撞
    {
        //恢复到原行位置
        s_data->y = y;
        //插入当前方块,位置不变,不设置颜色
        inserttetris( s_data );
        //初始化方块
        //inittetris( s_data );
        //显示下一个方块
        //nexttetris( s_data );
        if( checkerase( s_data,control))
             //刷新游戏池,显示游戏池
             printgamepool( s_data,control );
    }
    else
    {
        //没有碰撞,插入方块,设置颜色,显示当前方块
        inserttetris( s_data );
        setpoolcolor( s_data,control );
        printcurrenttetris( s_data,control );
    }
}

//运行游戏
void rungame( Data *s_data,Control *control )
{
    //显示游戏池
    //printgamepool( s_data,control );
    //向下移动方块
    //movedowntetris( s_data,control );
    //clock_t代表长整型,clock_t用来保存时间的数据类型
    clock_t clocklast,clocknow;
    clocklast = clock();//计时
    //显示当前游戏池
    printgamepool( s_data,control );
    while( !s_data->dead )//游戏是否失败,未失败执行
    {
        while( kbhit())//有按键按下
        {
            keydowncontrol( s_data,control,getch() );//getch()接受不回显
        }
        if(!control->pause)//未暂停
        {
            clocknow = clock();
            if( clocknow-clocklast >= 0.3*1000 )//CLOCK_PER_SEC=1000
            {
                //向下移动方块
                movedowntetris( s_data,control );
                clocklast = clocknow;
            }
            
            
        }
    }
}

//水平移动方块
void horizontalmove( Data *s_data,Control *control )
{
    //记录原列位置
    int x = s_data->x;
    //移除当前方块
    movetetris( s_data );
    //左移x--,右移x++
    control->direction == 0?s_data->x--:s_data->x++;
    //检测碰撞
    if( crashtetris( s_data ))
    {
        //恢复原列位置
        s_data->x = x;
        //插入方块
        inserttetris( s_data );
    }
    else  //未检测到碰撞
    {
        inserttetris( s_data );
        setpoolcolor( s_data,control );
        printcurrenttetris( s_data,control );
    }
    
}

//按键控制方块
void keydowncontrol( Data *s_data,Control *control,int key )
{
    //回车 暂停/解除暂停
    if( key == 13 )
    {
        control->pause = !control->pause;
    }
    if( control->pause )
        return ;//终止语句作用
    switch( key )
    {
        case 75:
		case 'a':
		case 'A': 
            control->direction = 0; //向左移动
            horizontalmove( s_data,control );break;
        case 77:
        case 'd':
        case 'D':
            control->direction = 1;//右移
            horizontalmove( s_data,control );break;
            
        case 'w':
        case 'W':
        case '8':  //顺时针旋转
            control->direction = true;
            revolvetetris( s_data,control );break;
        case '0':  //逆时针旋转
            control->direction = false;
            revolvetetris( s_data,control );break;
        case 32:  //直接落地
            dropdowntetris( s_data,control );break; 
        case 80:
        case 's':
        case 'S':
            movedowntetris( s_data,control );break;
        default:
            break;
        
    }
}

//消行检测
bool checkerase( Data *s_data,Control *control )
{
    int count = 0;//消行数
    static const score[5] = { 0,10,30,90,150 };//最多同时消去四行
    //从下往上检测
    int y = s_data->y + 3;
    while( y>=s_data->y+0 )
    {
        //有效区域,且已填满
        if( y<row_end && s_data->pool[y] == 0xffff )
        {
            count++;
            //消去一行方块
            //数据内存要移动 memove
            memmove( s_data->pool+1,s_data->pool,sizeof(unsigned int)*y );
            //颜色数据地移动
            memmove( control->color[1],control->color[0],sizeof(int[16])*y );
        }
        else
            y--;
    }
    s_data->erasetotal += count;
    s_data->score += score[ count ];
    if( count>0 )
        s_data->erasestatistics[ count-1 ]++;
    //初始化方块
    inittetris( s_data );
    //设置颜色
    setpoolcolor( s_data,control );
    return( count>0 );
}

//旋转方块
void revolvetetris( Data *s_data,Control *control )
{
    //记录原旋转状态
    int ori = s_data->revolve[0];
    //移除当前方块
    movetetris( s_data );
    //顺逆时针旋转状态判定
    s_data->revolve[0] = control->direction?( ori+1 )%4:( ori+3 )%4;
    //检测到碰撞,方块恢复到旋转前状态,插入方块
    //若没有,在当前位置放入方块,设置颜色,显示当前方块
    if( crashtetris( s_data ) )//检测到碰撞
    {
        //恢复原旋转状态
        s_data->revolve[0] = ori;
        //放入当前方块
        inserttetris( s_data );
    }
    else//未检测到碰撞
    {
        //插入方块
        inserttetris( s_data );
        //设置颜色
        setpoolcolor( s_data,control );
        //显示当前方块
        printcurrenttetris( s_data,control );
    }
    
    
}

//方块直接落地
void dropdowntetris( Data *s_data,Control *control )
{
   //移走当前方块
   movetetris( s_data );
   //检测是否有碰撞
   for( ;s_data->y<row_end;s_data->y++ ) 
   {
       if( crashtetris( s_data ) )
       {
           break;
       }
       
   }
   s_data->y--;//上移一格没碰撞
   //插入方块,设置颜色
   //插入方块
   inserttetris( s_data );
   //设置颜色
   setpoolcolor( s_data,control );
   //检测消行
   checkerase( s_data,control );
   //显示游戏池
   printgamepool( s_data,control );
   
}

//再来一次
bool playagain()
{
    int ch;//用于接收按键 y n
    //定位设置结束文字
    SetConsoleTextAttribute( consoleoutpt,0xf0 );
    fullposition( 15,10 );
    printf( "游戏结束!" );
    fullposition( 13,11 );
    printf( "按Y重玩,按N结束" );
    //判断是否重来一次
    //按Y重新开始
    //按N结束游戏
    do
    {
        ch = getch();
        if( ch=='y' | ch=='Y' )
            return true;
        else if( ch=='n' | ch=='N' )
            
            return false;
    }while(1);
    
}

``

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是用C语言一个简单俄罗斯方块小游戏的代码,同时注释了每一部分的功能和实现方式: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <windows.h> // 定义俄罗斯方块的大小和形状 #define MAX_ROW 20 #define MAX_COL 10 #define BLANK ' ' #define WALL '*' #define BLOCK '#' // 定义方块的形状 const int block[7][4][4] = { 1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0, // Z型方块 0,1,1,0, 0,1,1,0, 0,0,0,0, 0,0,0,0, // 方块 0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0, // L型方块 0,1,0,0, 0,1,1,0, 0,1,0,0, 0,0,0,0, // 反Z型方块 0,0,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,0, // T型方块 1,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0, // J型方块 0,1,0,0, 0,1,0,0, 0,1,1,0, 0,0,0,0, // 反L型方块 }; // 定义游戏的状态 int board[MAX_ROW][MAX_COL]; int score = 0; // 随机生成方块的形状和位置 void generate_block(int *type, int *row, int *col) { *type = rand() % 7; // 生成0-6之间的随机数 *row = 0; *col = rand() % (MAX_COL - 3); // 随机生成方块的左上角坐标 } // 显示游戏界面 void print_board() { system("cls"); // 清空屏幕 printf("Score: %d\n\n", score); // 显示得分 for (int i = 0; i < MAX_ROW; i++) { for (int j = 0; j < MAX_COL; j++) { if (board[i][j] == 0) { printf("%c ", BLANK); // 空格表示空白 } else if (board[i][j] == 1) { printf("%c ", BLOCK); // #表示方块 } else { printf("%c ", WALL); // *表示墙壁 } } printf("\n"); } } // 判断方块是否可以移动 int can_move(int type, int row, int col) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (block[type][i][j] == 1) { // 如果该位置有方块 int r = row + i; int c = col + j; if (r < 0 || r >= MAX_ROW || c < 0 || c >= MAX_COL || board[r][c] == 2) { return 0; // 如果超出边界或该位置已经有方块,则不能移动 } } } } return 1; // 可以移动 } // 将方块放到游戏区域中 void put_block(int type, int row, int col) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (block[type][i][j] == 1) { // 如果该位置有方块 int r = row + i; int c = col + j; board[r][c] = 1; // 将方块放到游戏区域中 } } } } // 消除满行的方块 void clear_line() { for (int i = MAX_ROW - 1; i >= 0; i--) { int flag = 1; // 标记该行是否满行 for (int j = 0; j < MAX_COL; j++) { if (board[i][j] != 1) { flag = 0; break; } } if (flag == 1) { // 如果该行满行 score++; // 增加得分 for (int k = i; k > 0; k--) { for (int j = 0; j < MAX_COL; j++) { board[k][j] = board[k-1][j]; // 将上面的方块下移一行 } } i++; // 重新判断该行 } } } int main() { srand(time(NULL)); // 随机数种子 int type, row, col; generate_block(&type, &row, &col); // 随机生成方块的形状和位置 while (1) { print_board(); // 显示游戏界面 if (can_move(type, row+1, col)) { // 如果方块可以向下移动 row++; } else { // 如果方块不能向下移动 put_block(type, row, col); // 将方块放到游戏区域中 clear_line(); // 消除满行的方块 generate_block(&type, &row, &col); // 随机生成下一个方块 if (!can_move(type, row, col)) { // 如果下一个方块不能移动了 printf("Game over!\n"); break; // 游戏结束 } } Sleep(500); // 延时一段时间,控制方块的下落速度 if (_kbhit()) { // 如果有按键按下 char ch = _getch(); // 获取按下的键 switch (ch) { case 'a': // 左移 if (can_move(type, row, col-1)) { col--; } break; case 'd': // 右移 if (can_move(type, row, col+1)) { col++; } break; case 's': // 加速下落 while (can_move(type, row+1, col)) { row++; } break; case 'q': // 退出游戏 printf("Game over!\n"); exit(0); break; } } } return 0; } ``` 这段代码实现一个简单俄罗斯方块小游戏,包括随机生成方块、方块的移动、方块的旋转、方块的放置、满行消除、得分计算等功能。同时使用了Windows API中的Sleep函数和conio.h库中的_kbhit和_getch函数来控制游戏的速度和获取按键输入。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值