【六、数组实现的打砖块】

这次我们使用数组来改进打砖块游戏

反弹的球

首先我们实现一个可以在荧幕上反弹的小球。使用二维数组 int canvas[High][Width] ( 和js的canvas没有一毛钱关系)来储存画布上的所有元素,值为0时输出空格,值为1时输出小球。

设小球坐标为(ball_x, ball_y),则有canvas[ball_x][ball_y] = 1 ,且暂时将其他元素的值设为0。

每次更新小球位置时将原位置元素设为0,将新位置元素设为1即可。

注意:gotoxy函数用于清屏重画,很久以前讲过的。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <cwindow.h>
// 画面尺寸设定
#define High 15
#define Width 20

//全局变量
int ball_x,ball_y;	//小球坐标
int ball_vx,ball_vy;//小球速度
int canvas[High][Width] = [0];

void gotoxy(int x, int y)	//移动光标便于清屏重画
{
	HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE);
	CROOD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void startup()				//数据初始化
{
	ball_x = 0;
	ball_y = Width/2;
	ball_vx = 1;
	ball_vy = 1;
	canvas[ball_x][ball_y] = 1;
}

void show()
{
	gotoxy(0, 0);
	int i,j;
	for(i=0; i<High; i++)
	{
		for(j=0; j<Width; j++)
		{
			if (canvas[i][j] == 0)
				printf(" ");//输出空格
			else if (canvas[i][j] == 1)
				printf("O");//输出小球
		}
		printf("|\n");//每画完一行显示边界并换行
	}
	for(j=0; j<Width; j++)
		printf("-");//最后画下边界
}

void updateWithoutInput()	//无关输入的更新
{
	//小球移动
	canvas[ball_x][ball_y] = 0;
	ball_x = ball_x + ball_vx;
	ball_y = ball_y + ball_vy;
	//反弹判断
	if ((ball_x == 0)||(ball_x == High - 1))
		ball_vx = -ball_vx;
	if ((ball_y == 0)||(ball_y == Width - 1))
		ball_vy = -ball_vy;
			
	canvas[ball_x][ball_y] = 1;
	//休眠时间,避免刷新过快
	sleep(50);
}

void updateWithInput()
{}

int main()
{
	startup();
	while(1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}

这里要注意的是:

  • updateWithInput留空,因为现在还没有用户操作的功能实现。
  • main是死循环,所以测试时要注意,当然也可以改进。

增加挡板

现在我们可以新定义,当数组中某一元素值为2时,输出挡板“ * ”。

并且为updateWithInput增加移动挡板的功能,每次移动一个单位作为其速度(当然可以改成别的数)。

挡板的刷新方式和小球一样,先将原位置清零然后把新位置元素改为2。

需要增加的内容如下:

//全局变量
int position_x,position_y; //挡板中心坐标
int ridus;	//挡板半径,就是延伸的长度
int left,right;	//挡板左右位置

//初始化
ridus = 5;
position_x = High - 1;
position_y = Width/2;
left = position_y - ridus;
right = position_x + ridus;

int k;
for(k=left; k<=right; k++)
	canvas[position_x][k] = 2;

//输出部分
...
else if (canvas[i][j] == 2)
	printf("*");
...

//更新部分(与输入无关)
if (ball_x == High - 2)
{
	//判断是否挡住
	if ((ball_y >= left)&&(ball_y <= right))
	{
		printf("\a");
	}
	else	//未挡住
	{
		printf("游戏失败\n");
		printf("pause");
		exit(0);
	}
}

//与输入有关的更新
void updateWithInput()
{
	char input;
	if (kbhit())	//判断是否有输入
		input = getch();
	if ((input == 'a')&&(left > 0))//左移
	{
		canvas[position_x][right] = 0;
		position_y --;
		left = position_y - ridus;
		right = position_x + ridus;
		canvas[position_x][left] = 2;
	}
	if ((input == 'd')&&(right < Width -1))//右移
	{
		canvas[position_x][left] = 0;
		position_y ++;
		left = position_y - ridus;
		right = position_x + ridus;
		canvas[position_x][right] = 2;	
	}
}

打砖块

这部分内容就和之前的内容一样了。

需要增加的内容有:

  1. 初始砖块
  2. 小球碰到砖块的判定
  3. 碰到砖块后的更新(砖块消失、小球反弹)

具体代码如下:

//初始化
int k,i;

for(k=0; k<Width; k++)
	for(i=0; i<high/4; i++)	//这里是画砖块,可以根据修改 i 的范围改变砖块的排数
		canvas[i][k] = 3;
//输出
...
else if (canvas[i][j] == 3)
	printf("#");
...
//碰到砖块后
if (canvas[ball_x + ball_vx][ball_y + ball_vy] == 3)
{
	canvas[ball_x + ball_vx][ball_y + ball_vy] = 0;
	ball_vx = -ball_vx;
	ball_vy = -ball_vy;
	printf("\a");
}

最后

  1. 坐标系是x轴向下,y 轴向右。
  2. 实际对碰撞的判定是在斜方向上,当然可以改进判定内容。
  3. 游戏胜利条件还没有完善。

全代码:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <cwindow.h>
// 画面尺寸设定
#define High 15
#define Width 20

//全局变量
int ball_x,ball_y;	//小球坐标
int ball_vx,ball_vy;//小球速度
int canvas[High][Width] = [0];
int position_x,position_y; //挡板中心坐标
int ridus;	//挡板半径,就是延伸的长度
int left,right;	//挡板左右位置

void gotoxy(int x, int y)	//移动光标便于清屏重画
{
	HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE);
	CROOD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void startup()				//数据初始化
{
	ball_x = 0;
	ball_y = Width/2;
	ball_vx = 1;
	ball_vy = 1;
	canvas[ball_x][ball_y] = 1;

	ridus = 5;
	position_x = High - 1;
	position_y = Width/2;
	left = position_y - ridus;
	right = position_x + ridus;

	int k,i;
	for(k=left; k<=right; k++)
	canvas[position_x][k] = 2;

	for(k=0; k<Width; k++)
		for(i=0; i<high/4; i++)	//这里是画砖块,可以根据修改 i 的范围改变砖块的排数
			canvas[i][k] = 3;
}

void show()
{
	gotoxy(0, 0);
	int i,j;
	for(i=0; i<High; i++)
	{
		for(j=0; j<Width; j++)
		{
			if (canvas[i][j] == 0)
				printf(" ");//输出空格
			else if (canvas[i][j] == 1)
				printf("O");//输出小球
			else if (canvas[i][j] == 2)
				printf("*");
			else if (canvas[i][j] == 3)
				printf("#");
		}
		printf("|\n");//每画完一行显示边界并换行
	}
	for(j=0; j<Width; j++)
		printf("-");//最后画下边界
}

void updateWithoutInput()	//无关输入的更新
{
	if (canvas[ball_x + ball_vx][ball_y + ball_vy] == 3)
	{
		canvas[ball_x + ball_vx][ball_y + ball_vy] = 0;
		ball_vx = -ball_vx;
		ball_vy = -ball_vy;
		printf("\a");
	}
	if (ball_x == High - 2)
	{
		//判断是否挡住
		if ((ball_y >= left)&&(ball_y <= right))
		{
			printf("\a");
		}
		else	//未挡住
		{
			printf("游戏失败\n");
			printf("pause");
			exit(0);
		}
	}
	//小球移动
	canvas[ball_x][ball_y] = 0;
	ball_x = ball_x + ball_vx;
	ball_y = ball_y + ball_vy;
	//反弹判断
	if ((ball_x == 0)||(ball_x == High - 1))
		ball_vx = -ball_vx;
	if ((ball_y == 0)||(ball_y == Width - 1))
		ball_vy = -ball_vy;
			
	canvas[ball_x][ball_y] = 1;
	//休眠时间,避免刷新过快
	sleep(50);
}

void updateWithInput()
{
	char input;
	if (kbhit())	//判断是否有输入
		input = getch();
	if ((input == 'a')&&(left > 0))//左移
	{
		canvas[position_x][right] = 0;
		position_y --;
		left = position_y - ridus;
		right = position_x + ridus;
		canvas[position_x][left] = 2;
	}
	if ((input == 'd')&&(right < Width -1))//右移
	{
		canvas[position_x][left] = 0;
		position_y ++;
		left = position_y - ridus;
		right = position_x + ridus;
		canvas[position_x][right] = 2;	
	}
}

int main()
{
	startup();
	while(1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值