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;
}
}
}
}