手记

【养成记】【九月打卡】嵌入式挑战第二天俄罗斯方块之按键控制

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<termios.h>
#include<unistd.h>


// n_x n_y 初始坐标
int n_x = 6,n_y = 6;
// n_num 图形, n_mode 方向, n_color 颜色
int n_num, n_mode, n_color;

// 7种图形
// 4个方向
// 前16个是二维数组数据点,第17个是代表距离右侧距离,第18个代表距离下侧距离
//7----7种图案
int shape[7][4][18] = 
{
    {
            {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 2,2},    //
            {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 2,2},    //
            {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 2,2},    //[][]
            {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 2,2},    //[][]
    },
    {
            {1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,0,0, 3,0},     //[]  [][][][]   
            {1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,3},     //[]
            {1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,0,0, 3,0},     //[]
            {1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,3},     //[] 
    },
    {
            {0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0, 1,2},     //  []    []      [][][]     [] 
            {1,0,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0, 2,1},     //[][][]  [][]      []     [][]
            {1,1,1,0, 0,1,0,0, 0,0,0,0, 0,0,0,0, 1,2},     //        []                 []
            {0,1,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0, 2,1}      //  
    },
    {
            {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0, 1,2},    //[][]       []   
            {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0, 2,1},    //  [][]   [][]     
            {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0, 1,2},    //         []             
            {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0, 2,1},    // 
    },
    {
            {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 1,2},    //  [][]   []       
            {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0, 2,1},    //[][]     [][]  
            {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 1,2},    //           []             
            {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0, 2,1},    // 
    },
    {
            {0,0,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,0, 1,2},    //    []   []    [][][]  [][]
            {1,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0, 2,1},    //[][][]   []    []        []
            {1,1,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,2},    //         [][]            []
            {1,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0, 2,1}     //    
    },
    {
            {1,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0, 1,2},    //[]       [][]  [][][]      []
            {1,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 2,1},    //[][][]   []        []      []
            {1,1,1,0, 0,0,1,0, 0,0,0,0, 0,0,0,0, 1,2},    //         []              [][]
            {0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0, 2,1}},   //
};
int getch()
{
    struct termios tm,tm_old;
    //1.获取用户输入的属性放到tm_old
    tcgetattr(0,&tm_old);
    //2.获取原始输入的属性,默认回显关闭
    cfmakeraw(&tm);
    //3.把输入的属性,设置到终端
    tcsetattr(0,0,&tm);
    //4.读取用户键盘输入
    int ch = getchar();
    //5.恢复正常输入
    tcsetattr(0,0,&tm_old);
    return ch;    
}
// 打印图形
void print_mode_shape(int n, int m, int x, int y, int c)
{   
    // 标记初始x坐标
    int initial_x = x;
    for (int i = 0; i < 16; i++)
    {
        // 4 x 4 方格每经过1行,纵坐标y+1,横坐标回归初始坐标 从第二行开始
        if (i != 0 && i % 4 == 0)
        {
            y += 1;
            x = initial_x;
        }
        // 打印图形
        if (shape[n][m][i] == 1)
        {
            //指定坐标输出
            printf("\033[%d;%dH",y,x);
            //输出背景颜色
            printf("\033[%d;%dm[]\n",c,c-10);
            //关闭背景颜色
            printf("\033[0m");
        }
        // 因为[]占两个位置所以x要移动2位
        x += 2; 
    }
    return;
    
}
// 随机初始化图行
void init_shape()
{
    srandom(time(NULL));
    n_num = random() % 7; // 选择图形
    n_mode = random() % 4; // 选择方向
    n_color = random() % 7 + 40; // 选择颜色
    print_mode_shape(n_num,n_mode,n_x,n_y,n_color);
    // 刷新
    fflush(NULL);
}
// 擦除图像
void eraser_shape(int n, int m, int x, int y)
{   
    // 标记初始x坐标
    int initial_x = x;
    for (int i = 0; i < 16; i++)
    {
        // 4 x 4 方格每经过1行,纵坐标y+1,横坐标回归初始坐标 从第二行开始
        if (i != 0 && i % 4 == 0)
        {
            y += 1;
            x = initial_x;
        }
        // 打印图形
        if (shape[n][m][i] == 1)
        {
            //指定坐标输出空格替换[]
            printf("\033[%d;%dH  \033[0m",y,x);
        }
        // 因为[]占两个位置所以x要移动2位
        x += 2; 
    }
    return;
    
}
/**
 * @brief 改变图像方向
 * 1、原来的方向 + 1 对 4取余就得到之前方向的下一个方向
 * 2、清除原来的图形
 * 3、用新的方向替换原来的方向
 * 4、打印新的图形
 */
void change_shape()
{
    int m = (n_mode + 1) % 4;
    eraser_shape(n_num,n_mode,n_x,n_y);
    n_mode = m;
    print_mode_shape(n_num,n_mode,n_x,n_y,n_color);
    return;
}
/**
 * @brief 按下键向下移动
 * 1、清除原来的图形
 * 2、n_y ++
 * 3、打印图形
 * @param n_num 
 * @param n_mode 
 */
void move_down(int num, int mode)
{
    eraser_shape(num,mode,n_x,n_y);
    n_y ++;
    print_mode_shape(n_num,n_mode,n_x,n_y,n_color);
    return;
}
/**
 * @brief 左移动
 * 1、清除原来的图形
 * 2、n_x -= 2
 * 3、打印图形
 * @param num 
 * @param mode 
 */
void move_left(int num,int mode)
{
    eraser_shape(num,mode,n_x,n_y);
    n_x -= 2;
    print_mode_shape(n_num,n_mode,n_x,n_y,n_color);
    return;
}
/**
 * @brief 右移动
 * 1、清除原来的图形
 * 2、n_x += 2
 * 3、打印图形
 * @param num 
 * @param mode 
 */
void move_right(int num,int mode)
{
    eraser_shape(num,mode,n_x,n_y);
    n_x += 2;
    print_mode_shape(n_num,n_mode,n_x,n_y,n_color);
    return;
}
void key_control()
{
    int ch;
    while (1)
    {
        ch = getch();
        if ('q' == ch || 'Q' == ch)
        {
            break;
        }else if (ch == '\r')
        {
            printf("down\n");
        }else if (ch == '\33')
        {
            ch = getch();
            if (ch == '[')
            {
                ch = getch();
                switch (ch)
                {
                case 'A':
                    /* code */
                    // printf("up\n");
                    change_shape();
                    break;
                case 'B':
                    /* code */
                    // printf("down\n");
                    move_down(n_num,n_mode);
                    break;
                case 'C':
                    /* code */
                    // printf("right\n");
                    move_right(n_num,n_mode);
                    break;
                case 'D':
                    /* code */
                    // printf("left\n");
                    move_left(n_num,n_mode);
                    break;
                }
            }   
        }
    }
    return;
}
int main()
{
    // 清屏幕
    printf("\033[2J");
    //隐藏光标
    printf("\033[?25l");
    init_shape();
    key_control();
    // 显示光标
    // printf("\033[25h")
    return 0;
}
0人推荐
随时随地看视频
慕课网APP