俄罗斯方块大概

VS2022 C++控制台窗口

c语言版

输出显示 方块

整体思路 

1. 整体是一个map数组  

#define HIG  20

#define WID  15

int map[HIG][WID] = { 0 };

设置成全局数组

2.方块结构体   用来记录方块的信息

typedef struct block  //方块的结构体

{

    int type;

    char blockdata[4][4];

    int x;   //横坐标

    int y;  //纵坐标

    int dir;  //方向  

}Block;

3.通用数组  方块的所有的类型  

整体逻辑  把地图作为二维数组 所有的操作都对这个二维数组进行 

方块的坐标对应着地图的位置 在4*4的二维数组中显示出来

/*
                            俄罗斯方块
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define HIG  20
#define WID  15
int map[HIG][WID] = { 0 };
char arrBlock[][4] = {
    0,0,0,0,	// Type = 1
    1,1,1,1,
    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,0,0,0,
    1,1,1,1,
    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,0,0,0,	// Type = 2
    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,	// Type = 3
    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,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,	// Type = 4
    1,1,0,0,
    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,
    1,1,0,0,
    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,	// Type = 5
    1,1,1,0,
    0,0,1,0,
    0,0,0,0,

    0,0,1,0,
    0,0,1,0,
    0,1,1,0,
    0,0,0,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,	// Type = 6
    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,
    0,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,	// Type = 7
    0,1,0,0,
    1,1,1,0,
    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,0,0,0,
    1,1,1,0,
    0,1,0,0,

    0,0,0,0,
    0,1,0,0,
    1,1,0,0,
    0,1,0,0,
};
typedef struct block  //方块的结构体
{
    int type;
    char blockdata[4][4];
    int x;   //横坐标
    int y;  //纵坐标
    int dir;  //方向   
}Block;
//创造起始的方块
Block* Creat_Block()
{
    srand(time(NULL));
    int type = rand() % 7;
    //int type = 1;
    Block* b1 = (Block*)malloc(sizeof(Block));
    b1->y = 1;          //起始纵坐标
    b1->x = (WID) / 2;//起始横坐标
  //  b1->flg = 0;
    b1->dir = 1;
    b1->type = type;//哪种类型
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            b1->blockdata[i][j] = arrBlock[16 * b1->type + 4 * (b1->dir) + i][j];
        }
    }
    return b1;
}
//画方块
void draw_block(Block* b1)
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (b1->blockdata[i][j] == 1)
            {
                map[b1->y + i][b1->x + j] = 1; //将方块的数据赋值给地图 y为纵坐标 x为横坐标
            }
        }
    }
}
//清除方块上一步的位置
void clear_block(Block* b1)
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (b1->blockdata[i][j] == 1)
            {
                map[b1->y + i][b1->x + j] = 0;
            }
        }
    }
}

//判断能不能动
int  CanMove(Block* b1)
{
    //判断有没有重合的有重合
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (b1->blockdata[i][j] == 1 && map[b1->y + i][b1->x + j] == 1) //有重合的地方
            {
                return 1;
            }
        }
    }
    return 0;
    //如果有重合清空 否则不清空
}
//向下移动
int Block_move_down(Block* b1)
{
    clear_block(b1); //清除上个图像
    b1->y++;  // 绘制下一次移动的图型
    if (CanMove(b1) == 1) //如果不能动了
    {
        b1->y--;
        draw_block(b1);
        return 1;
    }
    clear_block(b1);
    draw_block(b1);
}
//向左移动
void Block_move_left(Block* b1)
{
    clear_block(b1); //清除上个图像
    b1->x--;  // 绘制下一次移动的图型
    if (CanMove(b1) == 1) //如果不能动了
    {
        b1->x++;
        draw_block(b1);
        return 1;
    }
    clear_block(b1);
    draw_block(b1);
}
//向右移动
void Block_move_right(Block* b1)
{ 
    clear_block(b1); //清除上个图像
    b1->x++;  // 绘制下一次移动的图型
    if (CanMove(b1) == 1) //如果不能动了
    {
        b1->x--;
        draw_block(b1);
        return 1;
    }
    clear_block(b1);
    draw_block(b1);
}
void SPinBlock(Block* b1)
{
    int flag = 0;
    //判断能不能转
    clear_block(b1);
    int a[4][4] = { 0 };
    //记录之前的数据
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            a[i][j] = b1->blockdata[i][j];
        }
    }
    //转成什么样子
    if (++(b1->dir) == 4)
    {
        b1->dir = 1;
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            b1->blockdata[i][j] = arrBlock[b1->type * 16 + 4 * (b1->dir) + i][j];
        }
    }
    //判断能不能转
    flag = CanMove(b1);
    if (flag == 1)
    {
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                b1->blockdata[i][j] = a[i][j];
            }
        }
    }
    //旋转
}

void map_init()
{
    for (size_t i = 0; i < WID; i++)
    {
        map[0][i] = 1;
        map[HIG - 1][i] = 1;
    }
    for (size_t i = 0; i < HIG; i++)
    {
        map[i][0] = 1;
        map[i][WID - 1] = 1;
    }
}
void print_map()
{
    for (size_t i = 0; i < HIG; i++)
    {
        for (size_t j = 0; j < WID; j++)
        {
            if (map[i][j] == 0)
            {
                printf("□");
            }
            if (map[i][j] == 1)
            {
                printf("■");
            }
            if (map[i][j] == 3)
            {
                printf("田");
            }
        }
        printf("\n");
    }
}

void watch_last(Block* b1)
{
    //清除场上之前的3
   for (size_t j = 0; j < HIG; j++)
   {
       for (size_t i = 0; i < WID; i++)
       {
           if (map[j][i] == 3)
           {
               map[j][i] = 0;
           }
       }
   }
    // 保留现在的 y
    int temp_y = b1->y;
    //找到最后的位置的xy坐标
    clear_block(b1);
    while (1)
    {
        b1->y++;
        int flag = CanMove(b1);
        if (flag == 1)
        {
            b1->y--;
            break;
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (b1->blockdata[i][j] == 1)
            {
                map[b1->y + i][b1->x + j] = 3;
            }
        }
    }
    b1->y = temp_y;

}
//判断一排是不是满了 
void is_full(Block* b1)
{
    for (int i = HIG - 2; i >= b1->y; i--)  // 从后往前
    {
        int sum = 0;
        for (int j = 1; j < WID - 1; j++)
        {
            sum += map[i][j];
        }
        if (sum == WID - 2) // i行 满了 
        {
            for (int k = i; k > 1; k--)
            {
                for (int p = 1; p < WID - 1; p++)
                {
                    map[k][p] = map[k - 1][p];
                }
            }
            //有重复的行 到原来的那一行
            i++;
        }
    }
}
int main()
{
    map_init();
    char inputKey = '\0';
    while (1)
    {
        Block* a = Creat_Block();
        while (1)
        {
            draw_block(a);
            print_map();
            watch_last(a);
            if (_kbhit())
            {
                inputKey = _getch();
            }
            switch (inputKey)
            {
            case 'w':
                printf("w\r\n");
                SPinBlock(a);
                break;

            case 'a':
                Block_move_left(a);
                break;

            case 's':
                //直接到最下面
                while (1)
                {
                 int flag = Block_move_down(a);
                    if (flag == 1)
                    {
                        break;
                    }
                }
                printf("s\r\n");
                break;
            case 'd':
                Block_move_right(a);
                break;
            default:
                break;
            }
        int flag = Block_move_down(a);
            inputKey = '\0'; //重新刷新input的值
            Sleep(300);
            system("cls");
            if (flag == 1)
            {
                is_full(a);
                free(a);
                break;
            }
        }
    }
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值