C语言小游戏:弹球

目录

1:基础的小球运动

1:下落的小球

2:上下弹动的小球

3:上下左右弹动的小球

4:控制速度

2:函数包装的小球运动

1:代码重构

1:数值在函数间的传递

2:光标移动函数

2:显示边框

3:显示移动的挡板

4:反弹小球

5:消除砖块

3:小结


1:基础的小球运动

1:下落的小球

        要实现下落的小球,即改变小球的位置,即坐标变量,让小球的竖直坐标y增加即可,结合清屏函数system(”cls"),每一次输出y都增加一次,即可实现小球的下落运动。

#include <stdio.h>
#include <stdlib.h>            //清屏函数头文件
int main()
{
	int i,j;
	int x=5;
	int y=10;
	
	int hight=20;
	int velocity=1;
	
	while(1)
	{
		x=x+velocity;
		system("cls");
		
		for(i=1;i<x;i++)
		{
			printf("\n");
		}
		for(j=1;j<y;j++)
		{
			printf(" ");
		}
		printf("o");
		printf("\n");
		
	}
	
	return 0;
}

这样就得到了一个竖直下落的小球。

2:上下弹动的小球

上面写出了竖直下落的小球,当小球下落刀边界时,改变位移改变值的正负。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int i,j;
	int x=5;
	int y=10;
	
	int hight=20;
	int velocity=1;
	
	while(1)
	{
		x=x+velocity;
		system("cls");
		
		for(i=1;i<x;i++)
		{
			printf("\n");
		}
		for(j=1;j<y;j++)
		{
			printf(" ");
		}
		printf("o");
		printf("\n");
		
		if(x==hight)                //当小球到达边界时,改变位移改变值的方向。
		{
			velocity=-velocity;
		}
		if(x==0)
		{
			velocity=-velocity;
		}
	}
	
	return 0;
}

3:上下左右弹动的小球

        有了上面竖直弹动的小球,在水平上增加一个运动变量,提供位移改变值信息,即可实现小球的水平碰撞,效果和竖直的相同,都是通过改变正负号,依葫芦画瓢即可。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int i,j;
	int x=5;
	int y=10;
	int velocity_x=1;
	int velocity_y=1;
	int top=0;
	int botton=10;
	int left=0;
	int right=20;
	
	while(1)
	{
		x=x+velocity_x;
		y=y+velocity_y;
		system("cls");
		
		for(i=1;i<x;i++)
		{
			printf("\n");
		}
		for(j=1;j<y;j++)
		{
			printf(" ");
		}
		printf("o");
		printf("\n");
		
		if((x==top)||(x==botton))
		{
			velocity_x=-velocity_x;
		}
		if((y==left)||(y==right))
		{
			velocity_y=-velocity_y;
		}
	}
	return 0;
}

4:控制速度

        以上代码运行的时候小球运动过快,无法看清楚具体行踪,我们可以用Sleep函数(头文件#include <windows.h>)。比如Sleep(50)表示在此处暂停50毫秒。

printf("0");
Sleep(50);        //暂停50ms

 

2:函数包装的小球运动

1:代码重构

        首先对第一大步的程序重构,分成不同的函数部分,如基础信息,与用户无关的变量,与用户有关的变量等等。

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



int x,y;                            //全局变量的定义
int velocity_x,velocity_y;
int high,width;

void gotoxy(int x,int y)					//光标移动到原点,以下重画屏幕 
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X=x;
	pos.Y=y;
	SetConsoleCursorPosition(handle,pos);
}

void startup()				//定义初始变量 
{
	high=20;
	width=15;
	velocity_x=1;
	velocity_y=1;
	x=0;
	y=high/2;
}

void show()                            //输出到屏幕上的信息
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<high;i++)
	{
		for(j=0;j<width;j++)
		{
			if((y==i)&&(x==j))
				printf("0");
			else 
				printf(" ");
		}
		printf("\n");
	}
	
}

void updatewithoutinput()            //与用户无关的变量
{
	x=x+velocity_x;
	y=y+velocity_y;
	if((x==0)||(x==width-1))
		velocity_x=-velocity_x;
	if((y==0)||(y==high-1))
		velocity_y=-velocity_y;
		
	Sleep(50);
}

void updatewithinput()            //与用户有关的变量
{
}

int main()
{
	startup();
	while(1)
	{
		show();
		updatewithoutinput();
		updatewithinput();
	}
	return 0;
}

1:数值在函数间的传递

1:值传递

2:地址传递

3:全局变量传递

以上的代码就是运用了全局变量传递方式,这样定义的变量可以通过不同函数改变。

2:光标移动函数

        该函数即代码里的gotoxy()函数,如gotoxy(45,8),那么这个程序的首先输入就会出现在终端的(45,8)的这个位置。其余的信息自行百度。

2:显示边框

        通过在右边界和下边界输出 “ | ” 和 “ - ” 来实现边界。

        即在判断坐标(x,y)该输出什么,若x,y==小球的坐标,则输出小球,等于边界的坐标,就输出边界|,什么都不等于的话,就输出空格。

则在show()函数里的改变为:

void show()
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<=high;i++)
	{
		for(j=0;j<=width;j++)
		{
			if((y==i)&&(x==j))
				printf("0");
			else if(j==width)
				printf("|");
			else if(i==high)
				printf("-"); 
			else 
				printf(" ");
		}
		printf("\n");
	}
	
}

通过if....else 判断是否到达了该输入的坐标。

输出结果为:

               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
  0            |
               |
               |
               |
               |
               |
               |
               |
---------------|

宽度有点少了,同志们自行修改自己的数据即可。

3:显示移动的挡板

        既然要做挡板游戏,当然要有挡板的移动。上面提到边界 的输出是判断这个坐标是否到达了输出条件,输出挡板也不例外,到达了这一片范围就输出,其余的为空格。

这个需要两处改动,一是show()函数中判断坐标并输出挡板,二是挡板的移动,通过定义当班的宽度,挡板左右坐标变量,并通过改变左右坐标变量的大小达到移动挡板的效果。

一:

void show()
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<=high+1;i++)
	{
		for(j=0;j<=width;j++)
		{
			if((y==i)&&(x==j))
				printf("0");
			else if(j==width)
				printf("|");
			else if(i==high+1)
				printf("-"); 
			else if((i==high)&&(j>=left)&&(j<=right))
				printf("*");		//输出挡板 
			else 
				printf(" ");
		}
		printf("\n");
	}
	
}

二:

void updatewithinput()
{
	char input;
	if(kbhit())
	{
		input=getch();
		if(input=='a')
		{
			post_x--;
			left=post_x-R;
			right=post_x+R;
		}
		if(input=='d')
		{
			post_x++;
			left=post_x-R;
			right=post_x+R;
		}
		
	}
}

其中的知识同志们自行百度吧,kbhit()函数,getch()等。

输出效果:

                    |
                    |
                    |
                    |
    0               |
                    |
                    |
                    |
                    |
                    |
                    |
                    |
                    |
                    |
                    |
     ***********    |
--------------------|

4:反弹小球

上面的代码中小球只要到达了下边界就会反弹,不管是不是到了挡板上,下面就要增加信息,使其判断如果打到了挡板就反弹,并记录反弹次数,没打到就结束。增加了一个新的记录小球反弹次数的变量ball_number。

int high,width;
int velocity_x,velocity_y;
int x,y;
int R;				//挡板半径 
int left,right;		//挡板左右两边 
int post_x,post_y;
int ball_number;       //小球弹动的次数

以及判断小球是否到达挡板的判定机制。

void updatewithoutinput()
{
	if(y==high-1)
	{
		if((x>=left)&&(x<=right))        //判定是否打到了挡板
		{
			ball_number++;
			printf("\a");
		}
		else
		{
		printf("游戏失败\n");            
		system("pause");                   //程序暂停
		exit(0);                           //正确运行程序并退出
		}
	}
	x=x+velocity_x;
	y=y+velocity_y;
	if((x==0)||(x==width-1))
		velocity_x=-velocity_x;
	if((y==0)||(y==high-1))
		velocity_y=-velocity_y;
	Sleep(50);
}

5:消除砖块

        最后一步,在屏幕指定位置输出一个字符B充当砖块,打到了消失一下重新输出并记录分数。

这里又定义了三个全局变量用来储存砖块的位置和积分。

int high,width;
int velocity_x,velocity_y;
int x,y;
int R;				//挡板半径 
int left,right;		//挡板左右两边 
int post_x,post_y;
int ball_number;
int block_x,block_y;        //砖块位置信息
int score;                 //得分变量

同样在show()函数里添加了判断输出砖块的条件

void show()
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<=high+1;i++)
	{
		for(j=0;j<=width;j++)
		{
			if((y==i)&&(x==j))
				printf("0");
			else if(j==width)
				printf("|");
			else if(i==high+1)
				printf("-"); 
			else if((i==high)&&(j>=left)&&(j<=right))
				printf("*");		//输出挡板 
			else if((i==block_y)&&(j==block_x))
				printf("B");
			else 
				printf(" ");
		}
		printf("\n");
	}
	printf("反弹小球数:%d\n",ball_number);
	printf("消失的砖块数:%d\n",score);
	
}

还是比较一目了然的。当然还在与用户输入无关的函数updatewithoutinput()里添加了关于砖块的信息。

void updatewithoutinput()
{
	if(y==high-1)
	{
		if((x>=left)&&(x<=right))
		{
			ball_number++;
			printf("\a");
		}
		else
		{
		printf("游戏失败\n");
		system("pause");
		exit(0);
		}
	if((x==block_x)&&(y==block_y))        //判断砖块是否被打到
	{
		score++;
		block_x=rand()%width;
	}
	}
	x=x+velocity_x;
	y=y+velocity_y;
	if((x==0)||(x==width-1))
		velocity_x=-velocity_x;
	if((y==0)||(y==high-1))
		velocity_y=-velocity_y;
	Sleep(50);
}

3:小结

这样一个弹砖块小游戏就做好了,其中有些细节比如头文件和全局变量的赋值没有提到,同志们自行百度吧,这样学的应该比较通透一些。最后把完整的代码贴上:
 

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



int high,width;
int velocity_x,velocity_y;
int x,y;
int R;				//挡板半径 
int left,right;		//挡板左右两边 
int post_x,post_y;
int ball_number;
int block_x,block_y;
int score; 
//int i,j;



void gotoxy(int x,int y)					//光标移动到原点,以下重画屏幕 
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X=x;
	pos.Y=y;
	SetConsoleCursorPosition(handle,pos);
}

void startup()				//定义初始变量 
{
	high=15;
	width=20;
	y=0;
	velocity_y=1;
	velocity_x=1;
	x=width/2;
	R=5;
	post_x=width/2;
	post_y=high; 
	left=post_x-R;
	right=post_x+R;
	ball_number=0;
	block_y=0;
	block_x=width/2+2;
	score=0;
}

void show()
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<=high+1;i++)
	{
		for(j=0;j<=width;j++)
		{
			if((y==i)&&(x==j))
				printf("0");
			else if(j==width)
				printf("|");
			else if(i==high+1)
				printf("-"); 
			else if((i==high)&&(j>=left)&&(j<=right))
				printf("*");		//输出挡板 
			else if((i==block_y)&&(j==block_x))
				printf("B");
			else 
				printf(" ");
		}
		printf("\n");
	}
	printf("反弹小球数:%d\n",ball_number);
	printf("消失的砖块数:%d\n",score);
	
}

void updatewithoutinput()
{
	if(y==high-1)
	{
		if((x>=left)&&(x<=right))
		{
			ball_number++;
			printf("\a");
		}
		else
		{
		printf("游戏失败\n");
		system("pause");
		exit(0);
		}
	if((x==block_x)&&(y==block_y))
	{
		score++;
		block_x=rand()%width;
	}
	}
	x=x+velocity_x;
	y=y+velocity_y;
	if((x==0)||(x==width-1))
		velocity_x=-velocity_x;
	if((y==0)||(y==high-1))
		velocity_y=-velocity_y;
	Sleep(50);
}

void updatewithinput()
{
	char input;
	if(kbhit())
	{
		input=getch();
		if(input=='a')
		{
			post_x--;
			left=post_x-R;
			right=post_x+R;
		}
		if(input=='d')
		{
			post_x++;
			left=post_x-R;
			right=post_x+R;
		}
	}
}

int main()
{
	startup();
	while(1)
	{
		show();
		updatewithoutinput();
		updatewithinput();
	}
	return 0;
}

 

完结。。。。。

  • 10
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值