直接放代码啦。

#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>

#define ROW 29 //游戏区行数
#define COL 20 //游戏区列数

#define DOWN 80 //方向键:下
#define LEFT 75 //方向键:左
#define RIGHT 77 //方向键:右

#define SPACE 32 //空格键
#define ESC 27 //Esc键

struct Face
{
    int data[ROW][COL + 10]; //用于标记指定位置是否有方块(1为有,0为无)
    int color[ROW][COL + 10]; //用于记录指定位置的方块颜色编码
}face;

struct Block
{
    int space[5][5];
}block[12][4]; //用于存储7种基本形状和自定义的5种形态方块的各自的4种形态的信息,共48种

//游戏主体逻辑函数
void StartGame();
//选择界面
void AdminView();

//隐藏光标
void HideCursor();
//光标跳转
void CursorJump(int x, int y);
//初始化界面
void InitInterface();
//初始化方块信息
void InitBlockInfo();
//颜色设置
void color(int num);
//画出方块
void DrawBlock(int shape, int form, int x, int y);
//空格覆盖
void DrawSpace(int shape, int form, int x, int y);
//合法性判断
int IsLegal(int shape, int form, int x, int y);
//判断得分与结束
int JudeFunc();

int max, grade,beat,times; //全局变量

int main()
{

grade = 0; beat = 1,times = 0;//初始化变量
    AdminView(); 
    srand((unsigned int)time(NULL)); //设置随机数生成的起点
    return 0;
}

void Instructions(){

printf("俄罗斯方块游戏说明:\n");
    printf("玩法说明:\n");
    printf("  计分标准:下落一个块10分,一次消一行100分,两行200分,3行400分,4行800分\n");
    printf("  当分数达到2000分就进入下一关  如果空间被占满就失败!\n");
     
    printf("操作说明:\n");
    printf("左移:←\n");
    printf("右移:→\n");
    printf("加速:↓\n");
    printf("旋转:空格\n");
    printf("暂停: S\n");
    printf("退出: Esc\n");
    printf("重新开始:R\n\n\n");
    
    
}

void AdminView(){
    int n;
    while(1){
        system("cls");
        printf("\t\t俄罗斯方块游戏\n");
        printf("\t\t 1.开始游戏\n");
        printf("\t\t 2.游戏说明\n");
        printf("\t\t 0.退出\n");
        printf("请选择0-2:\n");
        scanf("%d",&n);
        switch(n){
            case 1:
                system("mode con lines=29 cols=60"); //设置cmd窗口的大小
                HideCursor(); //隐藏光标    
                InitInterface(); //初始化界面
                InitBlockInfo(); //初始化方块信息
                StartGame();break;
            case 2:
                Instructions();system("pause"); 
                break;
            case 0:exit(0);break;
        }    
    }    
}

//隐藏光标
void HideCursor()
{
    CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量
    curInfo.dwSize = 1;  //如果没赋值的话,隐藏光标无效
    curInfo.bVisible = FALSE; //将光标设置为不可见
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
    SetConsoleCursorInfo(handle, &curInfo); //设置光标信息
}
//光标跳转
void CursorJump(int x, int y)
{
    COORD pos; //定义光标位置的结构体变量
    pos.X = x; //横坐标设置
    pos.Y = y; //纵坐标设置
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
    SetConsoleCursorPosition(handle, pos); //设置光标位置
}
//初始化界面
void InitInterface()
{
    int i;
    int j;
    color(7); //颜色设置为白色
    for (i = 0; i < ROW; i++)
    {
        for (j = 0; j < COL + 10; j++)
        {
            if (j == 0 || j == COL - 1 || j == COL + 9)
            {
                face.data[i][j] = 1; //标记该位置有方块
                CursorJump(2 * j, i);
                printf("=");
            }
            else if (i == ROW - 1)
            {
                face.data[i][j] = 1; //标记该位置有方块
                
            }
            else
                face.data[i][j] = 0; //标记该位置无方块
        }
    }
    for (i = COL; i < COL + 10; i++)
    {
        face.data[8][i] = 1; //标记该位置有方块
        CursorJump(2 * i, 8);
        printf("=");
    }

CursorJump(2 * COL, 1);
    printf("下一个方块:");

CursorJump(2 * COL + 4, ROW - 17);
    printf("当前分数:%d", grade);
    
    CursorJump(2 * COL + 4,ROW - 19); 
    printf("当前关卡:%d 关",beat);
}
//初始化方块信息
void InitBlockInfo()
{
    int i;
    //“T”形
    for (i = 0; i <= 2; i++)
        block[0][0].space[1][i] = 1;
    block[0][0].space[2][1] = 1;

//“L”形
    for (i = 1; i <= 3; i++)
        block[1][0].space[i][1] = 1;
    block[1][0].space[3][2] = 1;

//“J”形
    for (i = 1; i <= 3; i++)
        block[2][0].space[i][2] = 1;
    block[2][0].space[3][1] = 1;

for (i = 0; i <= 1; i++)
    {
        //“Z”形
        block[3][0].space[1][i] = 1;
        block[3][0].space[2][i + 1] = 1;
        //“S”形
        block[4][0].space[1][i + 1] = 1;
        block[4][0].space[2][i] = 1;
        //“O”形
        block[5][0].space[1][i + 1] = 1;
        block[5][0].space[2][i + 1] = 1;
    }

//“I”形
    for (i = 0; i <= 3; i++)
        block[6][0].space[i][1] = 1;
        
    //自定义形态
        
        //“”形
    for (i = 0; i <= 2; i++)
        block[7][0].space[1][i] = 1;
    block[7][0].space[2][0] = 1;
    block[7][0].space[3][0] = 1;
    block[7][0].space[4][0] = 1;
            //“”形    
    for (i = 0; i <= 3; i++){
        block[8][0].space[i][0] = 1;
    }
    block[8][0].space[0][1] = 1;
    
    for (i = 0; i <= 3; i++){
        block[9][0].space[i][0] = 1;
    }
    block[9][0].space[3][1] = 1;
    
    for (i = 0; i <= 1; i++){
        block[10][0].space[i][0] = 1;
    }
    block[10][0].space[0][1] = 1;
    
    for (i = 0; i <= 2; i++){
        block[11][0].space[0][i] = 1;
    }

int temp[4][4];
    int shape;
    int form;
    int j;
    for (shape = 0; shape < 12; shape++) //12种形状
    {
        for (form = 0; form < 3; form++) //4种形态(已经有了一种,这里每个还需增加3种)
        {
            //获取第form种形态
            for (i = 0; i < 4; i++)
            {
                for (j = 0; j < 4; j++)
                {
                    temp[i][j] = block[shape][form].space[i][j];
                }
            }
            //将第form种形态顺时针旋转,得到第form+1种形态
            for (i = 0; i < 4; i++)
            {
                for (j = 0; j < 4; j++)
                {
                    block[shape][form + 1].space[i][j] = temp[3 - j][i];
                }
            }
        }
    }
}
//颜色设置
void color(int c)
{    
    
    switch (c)
    {
    case 0:
        c = 13; //“T”形方块设置为紫色
        break;
    case 1:
    case 2:
        c = 12; //“L”形和“J”形方块设置为红色
        break;
    case 3:
    case 4:
        c = 10; //“Z”形和“S”形方块设置为绿色
        break;
    case 5:
        c = 14; //“O”形方块设置为黄色
        break;
    case 6:
        c = 11; //“I”形方块设置为浅蓝色
        break;
    case 7:
        c = 7; //其他默认设置为白色
        break;
    default:
        
        c = 5;break;
    }

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置
    //注:SetConsoleTextAttribute是一个API(应用程序编程接口)
}
//画出方块
void DrawBlock(int shape, int form, int x, int y)
{
    int i,j;
    for ( i= 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (block[shape][form].space[i][j] == 1) //如果该位置有方块
            {
                CursorJump(2 * (x + j), y + i); //光标跳转到指定位置
                printf("田"); //输出方块
            }
        }
    }
}
//空格覆盖
void DrawSpace(int shape, int form, int x, int y)
{
    int i,j;
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (block[shape][form].space[i][j] == 1) //如果该位置有方块
            {
                CursorJump(2 * (x + j), y + i); //光标跳转到指定位置
                printf("  "); //打印空格覆盖(两个空格)
            }
        }
    }
}
//合法性判断
int IsLegal(int shape, int form, int x, int y)
{
    int i,j;
    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))
                return 0; //不合法
        }
    }
    return 1; //合法
}
//判断得分与结束
int JudeFunc()
{

int i,j,m,n;
    //int times = 0; //记录消除了几行方块 一行100分 二行200分 三行400分 4行800分 
    //判断是否得分
    for (i = ROW - 2; i > 4; i--)
    {
        int sum = 0; //记录第i行的方块个数
        for (j = 1; j < COL - 1; j++)
        {
            sum += face.data[i][j]; //统计第i行的方块个数
        }
        if (sum == 0) //该行没有方块,无需再判断其上的层次(无需再继续判断是否得分)
            break; //跳出循环
        if (sum == COL - 2) //该行全是方块,可得分
        {
            times++;
            //PlaySound(TEXT("del.wav"),NULL,SND_FILENAME | SND_ASYNC | NULL);
        
            color(7); //颜色设置为白色

for (j = 1; j < COL - 1; j++) //清除得分行的方块信息
            {
                face.data[i][j] = 0; //该位置得分后被清除,标记为无方块
                CursorJump(2 * j, i); //光标跳转到该位置
                printf("  "); //打印空格覆盖(两个空格)
            }
            //把被清除行上面的行整体向下挪一格
            for (m = i; m >1; m--)
            {
                sum = 0; //记录上一行的方块个数
                for (n = 1; n < COL - 1; n++)
                {
                    sum += face.data[m - 1][n]; //统计上一行的方块个数
                    face.data[m][n] = face.data[m - 1][n]; //将上一行方块的标识移到下一行
                    face.color[m][n] = face.color[m - 1][n]; //将上一行方块的颜色编号移到下一行
                    if (face.data[m][n] == 1) //上一行移下来的是方块,打印方块
                    {
                        CursorJump(2 * n, m); //光标跳转到该位置
                        color(face.color[m][n]); //颜色设置为还方块的颜色
                        printf("田"); //打印方块
                    }
                    else //上一行移下来的是空格,打印空格
                    {
                        CursorJump(2 * n, m); //光标跳转到该位置
                        printf("  "); //打印空格(两个空格)
                    }
                }
                if (sum == 0) //上一行移下来的全是空格,无需再将上层的方块向下移动(移动结束)
                    return 1; //返回1,表示还需调用该函数进行判断(移动下来的可能还有满行)
            }
        }
        
        
        
        
    }
    //判断游戏是否结束
    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);
            printf("游戏结束!当前得分%d",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;

//rand() % 8 
    int shape = rand() % 12, form = rand() % 4; //随机获取方块的形状和形态
    while (1)
    {
        int t = 0;

//rand() % 8
        int nextShape = rand() % 12, 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越小,方块下落越快
            }    
            if(grade >= 2000){
                t -= 300;
                grade = 0;//分数清零 
                beat++;            //关卡加一 
                int zero = 0;
                //显示分数和关卡
                system("cls");
                //清除缓存区
        
                InitInterface(); //初始化界面
                InitBlockInfo(); //初始化方块信息

}
            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; //记录该方块的颜色数值
                            }
                        }
                    }
                    //此次方块下路+10分
                    grade += 10; 
                    while (JudeFunc()); //判断此次方块下落是否得分以及游戏是否结束
                    //显示分数
                    if(times == 0);
                    else if(times == 1) grade += 100;
                    else if(times == 2)    grade += 200;
                    else if(times == 3) grade += 400;
                    else grade += 800;
                    
                    CursorJump(2 * COL + 4, ROW - 17); //光标跳转到显示当前分数的位置
                    printf("当前分数:%d\n", grade); //更新当前分数 
                    
                    times = 0;
                    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); //将右上角的方块信息用空格覆盖
    }
}

俄罗斯方块 c语言期中作业相关推荐

  1. 大一c语言大作业课题大全,昆明理工大学大一C语言大作业题目.doc

    昆明理工大学大一C语言大作业题目 综合性实践排序求平均值(包括将数拆散求最大最小值).函数ReadDat()随机产生100个存放到数组aa中00个jsSort()函数的功能是:进行降序排列.最后调用函 ...

  2. 1008c语言答案,c语言大作业题目01008.doc

    c语言大作业题目01008 一.学生信息管理程序 基本要求: 1.要求实现学生信息的查找.添加.删除.修改.浏览.保存.从文件读取.查看奖学金信息8个功能,每个功能模块均能实现随时从模块中退出,而且可 ...

  3. 东莞理工c语言作业,东莞理工学院C语言网上作业..doc

    东莞理工学院C语言网上作业. <C语言程序设计>第2章作业 一. 单选题 (每小题5分,共100分,得分 45 分) 1.1.关于C程序的构成描述,_________是不正确的. A.一个 ...

  4. c语言大作业旋转,c语言大作业全-20210412035629.docx-原创力文档

    Document number:PBGCG-0857-BTDO-0089-PTT1998 Document number:PBGCG-0857-BTDO-0089-PTT1998 C语言大作业全 #i ...

  5. 2010C语言添加背景图片_2019级C语言大作业 - 火柴人试炼之地

    C语言大作业 - 火柴人试炼之地https://www.zhihu.com/video/1200491618794606592 分享19级同学大一上学期用C语言实现的火柴人试炼之地.分步骤代码.图片音 ...

  6. c语言作业请输入一个运算符,C语言书面作业1(有答案版)..doc

    C语言书面作业1(有答案版). 书面作业1(数据类型.变量.输入/输出.运算符与表达式.选择结构.循环结构) 一.判断题:在正确的说法前面填写T,在错误的说法前面填写F(每题1分)[得分: ] ()( ...

  7. 南京大学c语言试卷,2007年4月南京大学C语言期中试题.doc

    2007年4月南京大学C语言期中试题 南京大学<C语言程序设计>期中试卷 (2006年4月15日) 系科 学号______________姓名_____________成绩________ ...

  8. C语言综合期末作业,内蒙古农业大学2010年期末c语言综合作业.doc

    内蒙古农业大学2010年期末c语言综合作业 综合练习作业 #include int main(void) { int choice,i; void shuai();void ge();void wan ...

  9. 医生c语言测试卷b卷的答案,合肥工业大学C语言期中测试题_B卷

    C语言期中小测验(B卷) 学号 姓名 班级 1.写出下列printf的输出结果. printf("\ta=%3d;b=%-8.3f,\ts=%8.4s;c=%c", A ,1.56 ...

最新文章

  1. 16S+功能预测也能发Sciences:尸体降解过程中的微生物组
  2. 【.Net MF网络开发板研究-01】IP地址设定及简单web演示
  3. 快打开《来自艾泽拉斯的一封密码信》,破译网易重大机密
  4. Coverage analysis in AIE
  5. PgSql备份pg_dump与还原手记pg_restore(转)
  6. 对象在内存中的存储布局
  7. macos下使用aria2_macOS下 ansible简单安装及基础使用
  8. mysql数据库命令 单选_mysql中创建数据库命令是?_学小易找答案
  9. 灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断
  10. 5步详解PHP文件上传功能的实现
  11. 初三下半年应该怎样合理的学习?
  12. 215. Kth Largest Element in an Array
  13. Kafka权威指南,初识 Kafka
  14. 【经验分享】MAC系统自带截屏、录屏小工具
  15. 互联网公司裁员潮传言四起,是捕风捉影还是确有其事?
  16. Bios开启CPU虚拟化后,进不了系统,解决办法如下
  17. 沪牌软件操作开发说明
  18. postcss压缩 postcss-clean替换cssnano
  19. 塑造成功性格的15种方法
  20. 简洁好用的3个研发项目管理工具

热门文章

  1. CentosRedhat下bcm43142博通无线网卡linux驱动
  2. Hssfworkbook 设置单元格格式 setdataformat
  3. Eigen库学习笔记(五)张量计算
  4. 招投标系统简介 招投标系统源码 java招投标系统开发类型 招投标系统功能设计
  5. 上海兆芯ASIC设计面试
  6. c++实验2 标准体重
  7. Android:MVP模式+XRecycleView+OKHttp+自定義梯形佈局
  8. 川大972 | 《管理信息系统》考研知识点(含第七版更新)
  9. 支持nvme的linux_一种linux下进行NVMESSD格式化的方法与流程
  10. Hive常见压缩格式和性能对比