C语言Window控制台实现弹弹方块(单个方块,多个方块)

简介: 前面,我们用C语言实现了列表时的学生信息管理系统,那么,window控制台还能做什么好玩的东西呢?http://blog.csdn.net/morixinguan/article/details/77511003这节我们来实现一下Window下的弹弹方块。

前面,我们用C语言实现了列表时的学生信息管理系统,那么,window控制台还能做什么好玩的东西呢?

http://blog.csdn.net/morixinguan/article/details/77511003

这节我们来实现一下Window下的弹弹方块。

设计这个小游戏要考虑的问题

(1)方块:方块的大小,方块的颜色,方块在Window控制终端的起始位置(x,y的坐标),方块移动的速度,移动的方向。

(2)边框:弹弹方块需要在一定的空间内弹,而不能超出这个空间,那么这时需要设计一个边框,需要考虑边框的大小。

(3)方块和边框之间的关系:方块不能超出边框之外,也就是要判断一个方块以及方框的临界条件。

方块用" * " 组成的图形来代替,边框长用" - ",宽用方向 " | "代替。

现在可以来实现这个小游戏:

我们需要有以下的接口:

//窗口初始化
void HANDLE_init(HANDLE hOut);
//显示边框的函数
void show_map(HANDLE hOut);
//显示方块
void show_block(HANDLE hOut,struct block_t *array , int size);
//清除方块
void clear_block(HANDLE hOut,struct block_t *array , int size);
//移动方块
void move_block(struct block_t *array , int size);
//检测方块是否在边框内
int  check_block(struct block_t *array , int size);

下面开始写代码:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <conio.h>
#include <tchar.h>
#define msleep(x)  		(usleep(1000*x))
#define   ROW     18
#define   COL     60
#define TITLE "弹弹方块游戏 设计者:杨源鑫 日期:2017年8月24日 版本:1.0"
//在终端上打印信息
#define Print_Info_To_console(str,hOut,pos,x,y,color_type) \
	SetConsoleTextAttribute(hOut, color_type); 	\
	pos.X = x;									\
	pos.Y = y ;									\
	SetConsoleCursorPosition(hOut,pos);    		\
	printf("%s",str);
//窗口初始化
void HANDLE_init(HANDLE hOut);
void show_map(HANDLE hOut);
void show_block(HANDLE hOut,int row , int col , int w , int h);
void clear_block(HANDLE hOut,int row , int col , int w , int h);
void move_block(int *row , int *col , int *drow , int *dcol , int h , int w);


//定义设置光标结构体变量
CONSOLE_CURSOR_INFO cci; 
//定义默认的坐标位置  	
COORD pos = {0,0};

int main(int argc , char **argv)
{
	int row = 5 ; 
	int col = 5 ; 
	
	int w = 4 ; 
	int h = 2 ; 	

	int drow = 1 ; 
	int dcol = 1 ; 
	HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE_init(hOut);
	//刷方框
	show_map(hOut);
	while(1)
	{
	
		show_block(hOut, row , col , w , h);
		//sleep(1);
		Sleep(100);
		clear_block(hOut,row , col , w , h);
		move_block(&row , &col , &drow , &dcol , h , w);
	}

	return 0 ;
}

//窗口初始化
void HANDLE_init(HANDLE hOut)
{
    SetConsoleTitleA(TITLE);
    //获取当前的句柄---设置为标准输出句柄 
    //获取光标信息
    GetConsoleCursorInfo(hOut, &cci); 
	//设置光标大小   
    cci.dwSize = 1; 
	//设置光标不可见 FALSE   
    cci.bVisible =  0; 
    //设置(应用)光标信息
    SetConsoleCursorInfo(hOut, &cci); 
}

//画边框 
void show_map(HANDLE hOut)
{
	int i ; 
	system("cls");  //全局刷
	Print_Info_To_console(TITLE,hOut,pos,2,0,FOREGROUND_GREEN | 0x8);
	//Print_Info_To_console(str,hOut,pos,x,y,color_type) 
	for(i = 1 ; i <= COL ; i++)
	{
		Print_Info_To_console("-",hOut,pos,i,1,FOREGROUND_GREEN | 0x8);
		Print_Info_To_console("-",hOut,pos,i,ROW,FOREGROUND_GREEN | 0x8);
	}
	for(i = 1 ; i <= ROW ; i++ )
	{
		Print_Info_To_console("|",hOut,pos,1,i,FOREGROUND_GREEN | 0x8);
		Print_Info_To_console("|",hOut,pos,COL,i,FOREGROUND_GREEN | 0x8);
	}
	fflush(stdout);
}

//画方块 
void show_block(HANDLE hOut,int row , int col , int w , int h)
{
	int i , j ; 
	for(i = 0 ; i < h ; i++)
	{
		for(j = 0 ; j < w ; j++)
		{
			Print_Info_To_console("*",hOut,pos,col+j,row+i,FOREGROUND_RED | FOREGROUND_GREEN | 0x8);
		}
	}
	fflush(stdout);	
}

void move_block(int *row , int *col , int *drow , int *dcol , int h , int w)
{
	if((*row == ROW-h) || (*row == 2) )
		*drow = -*drow ; 
	if((*col == COL-w) || (*col == 2)) 
		*dcol = -*dcol;
	*row += *drow ;
	*col += *dcol ; 
}
void clear_block(HANDLE hOut,int row , int col , int w , int h)
{
	int i , j ; 
	for(i = 0 ; i < h ; i++)
	{
		for(j = 0 ; j < w ; j++)
		{
			Print_Info_To_console("*",hOut,pos,col+j,row+i,0);	
		}
	}
	fflush(stdout);
}
运行结果演示:


那么既然可以实现一个,可以实现多个方块同时运行吗?当然是可以的!

多个方块,这时候要考虑什么问题?

前面我们知道,关于方块我们设计的时候需要考虑的问题:方块的起始位置,方块的大小,方块的移动方向,方块的颜色。现在我们要实现多个方块,那么就需要设计一个结构体,然后定义一个结构体数组来存储这些方块。

我们设计的结构体如下:

struct  block_t
{
	//方块的起始位置
	int row; 
	int col; 
	//方块的大小
	int w; 
	int h; 	
	//方块的移动方向
	int drow ; 
	int dcol ; 
	//方块着色
	int color ;
};

当然,上面的接口内存需要改动一下,参数传参改为结构体数组的形式即可,这样就方便很多了。

接口修改如下:

//窗口初始化
void HANDLE_init(HANDLE hOut);
//显示边框的函数
void show_map(HANDLE hOut);
//显示方块
void show_block(HANDLE hOut,struct block_t *array , int size);
//清除方块
void clear_block(HANDLE hOut,struct block_t *array , int size);
//移动方块
void move_block(struct block_t *array , int size);
//检测方块是否在边框内
int  check_block(struct block_t *array , int size);
下面开始修改代码:

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

#define msleep(x)  		(usleep(1000*x))
#define NR(x)			(sizeof(x)/sizeof(x[0]))
//定义边框的行为18,列为60
#define   ROW     18
#define   COL     60
#define TITLE "弹弹方块游戏 设计者:杨源鑫 日期:2017年8月24日 版本:2.0"
//在终端上打印信息
#define Print_Info_To_console(str,hOut,pos,x,y,color_type) \
	SetConsoleTextAttribute(hOut, color_type); 	\
	pos.X = x;									\
	pos.Y = y ;									\
	SetConsoleCursorPosition(hOut,pos);    		\
	printf("%s",str);
	

struct  block_t
{
	//方块的起始位置
	int row; 
	int col; 
	//方块的大小
	int w; 
	int h; 	
	//方块的移动方向
	int drow ; 
	int dcol ; 
	//方块着色
	int color ;
};

//窗口初始化
void HANDLE_init(HANDLE hOut);
//显示边框的函数
void show_map(HANDLE hOut);
//显示方块
void show_block(HANDLE hOut,struct block_t *array , int size);
//清除方块
void clear_block(HANDLE hOut,struct block_t *array , int size);
//移动方块
void move_block(struct block_t *array , int size);
//检测方块是否在边框内
int  check_block(struct block_t *array , int size);

//定义设置光标结构体变量
CONSOLE_CURSOR_INFO cci; 
//定义默认的坐标位置  	
COORD pos = {0,0};

int main(void)
{
	//定义方块结构体数组
	struct block_t  array[] = {
	{3,4,3,2,1,1,FOREGROUND_RED | FOREGROUND_GREEN | 0x8},
	{6,7,3,2,1,1,FOREGROUND_RED | 0x8},
	{8,9,3,2,1,1,FOREGROUND_GREEN | FOREGROUND_BLUE | 0x8},
	};
	//刷方框
	if(check_block(array , NR(array)))
	{
		printf("方块定义不在界线内\n");
		return -1 ; 
	}
	HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE_init(hOut);
	fflush(stdout);
	//显示边框
	show_map(hOut);
	while(1)
	{
		//显示方块
		show_block(hOut ,array , NR(array));
		//延时
		msleep(100);
		//清除方块
		clear_block(hOut ,array , NR(array));
		//移动方块
		move_block(array , NR(array));
	}
	return 0 ;
}

//窗口初始化
void HANDLE_init(HANDLE hOut)
{
	SetConsoleTitleA(TITLE);
	//获取当前的句柄---设置为标准输出句柄 
    //获取光标信息
    GetConsoleCursorInfo(hOut, &cci); 
	//设置光标大小   
    cci.dwSize = 1; 
	//设置光标不可见 FALSE   
    cci.bVisible =  0; 
    //设置(应用)光标信息
    SetConsoleCursorInfo(hOut, &cci); 
}

//画边框 
void show_map(HANDLE hOut)
{
	int i ; 
	system("cls");  //全局刷
	Print_Info_To_console(TITLE,hOut,pos,2,0,FOREGROUND_GREEN | 0x8);
	for(i = 1 ; i <= COL ; i++)
	{
		Print_Info_To_console("-",hOut,pos,i,1,FOREGROUND_GREEN | 0x8);
		Print_Info_To_console("-",hOut,pos,i,ROW,FOREGROUND_GREEN | 0x8);
	}
	for(i = 1 ; i <= ROW ; i++ )
	{
		Print_Info_To_console("|",hOut,pos,1,i,FOREGROUND_GREEN | 0x8);
		Print_Info_To_console("|",hOut,pos,COL,i,FOREGROUND_GREEN | 0x8);
	}
	fflush(stdout);
}

//显示方块子函数
static void _show_block(HANDLE hOut,struct block_t block)
{
	int i , j ; 
	for(i = 0 ; i < block.h ; i++)
	{
		for(j = 0 ; j < block.w ; j++)
		{
			Print_Info_To_console("*",hOut,pos,block.col+j,block.row+i,block.color);
			//Print_Info_To_console("*",hOut,pos,block.col+j,block.row+i,FOREGROUND_RED | FOREGROUND_GREEN | 0x8);
			//printf("\033[%d;%dH\033[%dm \033[0m" , block.row+i , block.col+j , block.color);
		}
	}
	fflush(stdout);
}

void show_block(HANDLE hOut ,struct block_t *array , int size)
{
	int i ; 
	for(i = 0 ; i < size ; i++)
	{
		_show_block(hOut,array[i]);
	}
}	
//移动方块子函数
static void _move_block(struct block_t *block)
{
	if((block->row >= ROW-block->h) || (block->row <= 2) )
		block->drow = -block->drow ; 
	if((block->col >= COL-block->w) || (block->col <= 2)) 
		block->dcol = -block->dcol;
	block->row += block->drow ;
	block->col += block->dcol ; 
}
void move_block(struct block_t *array , int size)
{
	int i ; 
	for(i = 0 ; i < size ; i++)
	{
		_move_block(&(array[i]));
	}
}	

//清除方块子函数
static void _clear_block(HANDLE hOut,struct block_t block)
{
	int i , j ; 
	for(i = 0 ; i < block.h ; i++)
	{
		for(j = 0 ; j < block.w ; j++)
		{
			Print_Info_To_console("*",hOut,pos,(block.col)+j,(block.row)+i,0);	
			//printf("\033[%d;%dH " , (block.row)+i , (block.col)+j);
		}
	}
	fflush(stdout);
}
void clear_block(HANDLE hOut,struct block_t *array , int size)
{
	int i ; 
	for(i = 0 ; i < size ; i++)
	{
		_clear_block(hOut,array[i]);
	}
}	

//检测方块是否在允许的方块内
static int _check_block(struct block_t block)
{
	if((block.row == 2) || (block.col == 2) || 
		(block.row == ROW - block.h) || (block.col == COL-block.w))
	{
		return 1 ; 
	}	
	return 0 ; 
}

int  check_block(struct block_t *array , int size)
{

	int i ; 
	for(i = 0 ; i < size ; i++)
	{
		if(_check_block(array[i]))
			return 1 ; 
	}
	return 0 ; 
}
运行结果演示:


那么该游戏还能继续拓展,比如,方块的移动方式修改用手动用键盘的上下左右按键来进行控制,还有,方块如果碰撞到了,会弹开一段距离。甚至,我们还可以借助这个,设计一个控制台版本的坦克大战。

        更多脑洞,需要你仔细的斟酌与思考,一个游戏不是轻轻松松就做出来的。发挥你的脑洞,想你所想,编你所编!!






目录
相关文章
|
存储 C语言
C语言Window控制台实现弹弹方块(单个方块,多个方块)
C语言Window控制台实现弹弹方块(单个方块,多个方块)
121 0
用c语言输出有颜色的字体 printf输出 控制台程序修改文本位置 设置控制台程序窗口标题
用c语言输出有颜色的字体 printf输出 控制台程序修改文本位置 设置控制台程序窗口标题
|
Linux API C语言
Linux下C语言实现弹弹方块小游戏
Linux下C语言实现弹弹方块小游戏
198 0
|
Linux C语言 C++
C语言实现一个Window控制台带彩色,且可以用方向键选择并确认的菜单式列表(一)
C语言实现一个Window控制台带彩色,且可以用方向键选择并确认的菜单式列表(一)
228 0
|
C语言
C语言——修改控制台背景色和字体颜色
C语言——修改控制台背景色和字体颜色
|
C语言
在C语言中,SetConsoleTextAttribute(参数1,参数2)是设置控制台窗口字体颜色和背景颜色的函数。GetStdHandle(参数)函数用于获得句柄
在C语言中,SetConsoleTextAttribute(参数1,参数2)是设置控制台窗口字体颜色和背景颜色的函数。 参数1:句柄 参数2:颜色
323 0
在C语言中,SetConsoleTextAttribute(参数1,参数2)是设置控制台窗口字体颜色和背景颜色的函数。GetStdHandle(参数)函数用于获得句柄
|
API C语言 C++
C语言或者C++中隐藏控制台窗口
C语言或者C++中隐藏控制台窗口
719 0
java实战项目超市管理系统控制台版
java实战项目超市管理系统控制台版
180 0
|
Java
【Java开发指南 | 第二十篇】Java流之控制台
【Java开发指南 | 第二十篇】Java流之控制台
151 2
|
XML 监控 Dubbo
Dubbo03【管理控制台和监控中心搭建】,Java开发实用必备的几款插件
Dubbo03【管理控制台和监控中心搭建】,Java开发实用必备的几款插件