弹弹方块项目实现需求
本项目是在Linux下实现的,实现效果就是在Linux终端上显示一个方块,方块的大小由编写者自行决定。然后画一个方框,小方块会在这个方框的范围中来回弹,如图3-7-12所示。
我们用上一篇文章的VT100控制码来实现这个需求。
VT100控制码表
项目实现步骤规划
一、画一个方框,从终端的哪一个位置(行,列)坐标开始画起,颜色又是什么?
二、画一个方块,方块的起始位置,方块的大小,方块移动的方向,方块的颜色是什么?
三、移动的时候,为了不要方块留下移动的痕迹,那么需要清除方块的痕迹,如何实现?
具体实现
一、方块结构体
1struct block 2{ 3 int W ; //方块的宽度 4 int H ; //方块的高度 5 int row ; //方块的起始坐标row和col 6 int col ; 7 int drow ; //方块的移动方向drow和dcol 8 int dcol ; 9 void (*show)(struct block block) ; //方块显示 10 void (*clear)(struct block block); //方块清除 11 void (*move)(struct block *block) ; //方块移动 12};
该结构体描述方块的一切信息,包括显示的位置、方块的大小、移动的方向以及方块的颜色。
二、操作方块的API函数
1//显示边框的函数 2void show_map(void); 3//显示方块 4void show_block(struct block_t *array , int size); 5//清除方块 6void clear_block(struct block_t *array , int size); 7//移动方块 8void move_block(struct block_t *array , int size); 9//检测方块是否在边框内 10int check_block(struct block_t *array , int size);
三、源代码实现 block.c
1#include <stdio.h> 2#include <unistd.h> 3//窗体的大小 4#define ROW 20 5#define COL 60 6//定义延迟函数 7#define msleep(x) usleep(x*1000) 8 9 10//方块操作结构体 11struct block 12{ 13 int W ; //方块的宽度 14 int H ; //方块的高度 15 int row ; //方块的起始坐标row和col 16 int col ; 17 int drow ; //方块的移动方向drow和dcol 18 int dcol ; 19 void (*show)(struct block block) ; //方块显示 20 void (*clear)(struct block block); //方块清除 21 void (*move)(struct block *block) ; //方块移动 22}; 23 24void show_background(void); 25void show_block(struct block block); 26void clear_block(struct block block); 27void move_block(struct block *block); 28int main(void) 29{ 30 struct block b1 = {4,2,5,5,1,1,show_block , clear_block , move_block}; 31 system(“clear”); 32 show_background(); 33 printf("\033[?25l"); 34 while(1) 35 { 36 b1.show(b1); 37 msleep(100); 38 b1.clear(b1); 39 b1.move(&b1); 40 } 41 return 0 ; 42} 43//显示方块 44void show_block(struct block block) 45{ 46 int i ,j ; 47 for(i = 0 ; i < block.H ; i++) 48 { 49 for(j = 0 ; j < block.W ; j++) 50 { 51 printf("\033[%d;%dH\033[43m \033[0m" ,block.row+i, block.col+j); 52 } 53 } 54 fflush(stdout); 55} 56//清除方块 57void clear_block(struct block block) 58{ 59 int i ,j ; 60 for(i = 0 ; i < block.H ; i++) 61 { 62 for(j = 0 ; j < block.W ; j++) 63 { 64 printf("\033[%d;%dH \033[0m" ,block.row+i, block.col+j); 65 } 66 } 67 fflush(stdout); 68} 69//移动方块 70void move_block(struct block *block) 71{ 72 if(block->row < 3 || block->row > ROW-block->H-1) 73 block->drow = -block->drow ; 74 if(block->col < 3 || block->col > COL-block->W-1) 75 block->dcol = -block->dcol ; 76 77 block->row += block->drow ; 78 block->col += block->dcol ; 79} 80//显示背景 81void show_background(void) 82{ 83 int i ,j ; 84 //画出上下和左右边框 85 for(i = 1 ; i <= ROW ; i++) 86 { 87 printf("\033[%d;1H\033[43m \033[0m" , i); 88 printf("\033[%d;%dH\033[43m \033[0m" , i , COL); 89 } 90 91 for(i = 1 ; i <= COL ; i++) 92 { 93 printf("\033[1;%dH\033[43m \033[0m" , i); 94 printf("\033[%d;%dH\033[43m \033[0m" ,ROW, i); 95 } 96}
在Linux下,使用gcc命令编译程序生成可执行文件,然后运行。显示效果如图3-7-13所示:
那么,如果我想一次性显示多个同时移动的方块呢?如何是两个,该如何编写程序呢?其实很简单,多定义一个方块结构体。然后在循环中,调用对应的显示方块,清除方块,移动方块的函数即可。再看看效果,如图3-7-14所示。
struct block b2 = {4,2,7,8,1,3,show_block , clear_block , move_block};
程序还有许多的优化方法,读者可以自行发挥,修改以上源代码。下面给读者一个思考的空间,我们已经学习过VT控制码了,你能否改变方块的颜色呢?还有,如果每次都像现在的一样多定义一个结构体,然后在主循环中调用,程序将会越来越臃肿,能否设计新的程序架构解决这个问题呢?