c/c++实现勇闯地下一百层(重点在于实现重力加速度)

实现步骤:

  1. 一块板的上升
  2. 多块随机板的上升
  3. 小人随着板上升
  4. 小人的左右移动
  5. 小人的重力感下落
  6. 死亡的判断
  7. 记录分数
  8. 随着分数增加难度上升

程序中的难点:

(1)重力加速度的实现:

精髓就是把小人自由下落的运动单独分离出来处理
首先看我第一次小人以固定速度下落的代码:
这时小人的下落很不自然,像是直接瞬间从一个高度掉落的另一个高度

#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
using namespace std;

#define High 25  // 游戏画面尺寸
#define Width 40
struct node{
	int left;
	int right;
	int Pos_Y;
	int center;
	node(){
		left=0;  
		right=0; 
		Pos_Y=High-1; 
		center=0;
	}
}; 
// 全局变量
int canvas[High][Width]={0};  
int ban_len;//第一块板的长度
int ban_posX,ban_posY;//第一块板的中心初始位置
int boy_posX,boy_posY;//小人的位置 
int ban_speed;//第一块板子上升的速度 
int boy_speed;//小人的重力加速度 
node ban[3];//多块随机板(每行三个) 
int timer;//板子出现的时间间隔 
double score;//小人的分数(每跳到一个新的板子时分数加一) 

void gotoxy(int a, int b) //光标移动到(x,y)位置
{
    int xx=0x0b;
	HANDLE hOutput;
	COORD loc;
	loc.X =a;
	loc.Y=b;
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput, loc);
	return;
}

void startup() // 数据初始化
{
	srand(time(NULL));
	int i,j;
	ban_len=5;//板的长度        
	ban_posX=Width/2;
	ban_posY=High-1;//板的中心位置 
	boy_posX=ban_posX; 
	boy_posY=ban_posY-1;//小人的初始位置 
	canvas[boy_posY][boy_posX]=1;//小人在第一块板子的正上方 
	int left=ban_posX-ban_len/2,right=ban_posX+ban_len/2;
	ban_speed=1;
	boy_speed=1; 
	timer=5;
	 
	score=0;
	for(j=left;j<=right;j++){
		canvas[ban_posY][j]=2;//第一块板子 
	} 
	for(i=0;i<High;i++){//周围的墙壁 
		canvas[i][0]=-1;
		canvas[i][Width-1]=-1;
	} 
	for(j=1;j<Width-1;j++){ 
		canvas[0][j]=-2;//顶部的刺刀 
	}	
	
} 

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){
				cout<<" ";
			}else if(canvas[i][j]==-1){
				cout<<"|"; 
			}else if(canvas[i][j]==-2){
				cout<<"T";
			}else if(canvas[i][j]==2){
				cout<<"_";
			}else if(canvas[i][j]==1){
				cout<<"O";
			} 
		} 
		cout<<"\n";
	} 
	cout<<"\n";
	cout<<"score:"<<score<<"\n"; 
}	

void updateWithoutInput()  // 与用户输入无关的更新
{	
	int i=0,j=0; 	 
	srand(time(NULL));
	for(i=0;i<High;i++){
		for(j=0;j<Width;j++){
			//板子向上移动
			if(canvas[i][j]==2){
				canvas[i][j]=0;
				if(i>1){//板子触碰到顶部时消失 
					canvas[i-ban_speed][j]=2;
				}
			}
			if(canvas[i][j]==1){//小人的运动 
				canvas[i][j]=0;
				if(boy_posY>1&&boy_posY<High-1){//小人碰到刺刀或者掉入深渊游戏失败 
					if(canvas[i+1][j]!=2){//如果小人不站在板子上会随自身重力下降 
						boy_posY+=boy_speed; 
						score+=0.25;//在游戏中由于有speed和timer来控制板子出现的时间,所以相邻两层板子的间隔不止1个,故加的分数不是1 
					}else{//如果小人站在板子上会随板子上升 
						boy_posY-=ban_speed; 						
					}	
					canvas[boy_posY][j]=1;
				}else{//碰到刺刀或者掉入深渊游戏失败 
					cout<<"游戏失败"<<"\n";
					Sleep(1000);
					exit(0);
				} 
			}
		}
	}
	static int speed=0;
	if(speed==timer){
		for(j=0;j<3;j++){
			ban[j].center=rand()%10+2+j*10;
			ban[j].left=ban[j].center-rand()%4;
			ban[j].right=ban[j].center+rand()%4;
			for(i=ban[j].left;i<=ban[j].right;i++){
				if(i>0&&i<Width-1) 
					canvas[ban[j].Pos_Y][i]=2;
			}
		}
		speed=0;
	}else{
		speed++;
	}
	Sleep(150);	
}

void updateWithInput()  // 与用户输入有关的更新
{
	char input;
	if(kbhit()){
		input=getch();
		if(input=='a'){//小人左移 
			canvas[boy_posY][boy_posX]=0;
			boy_posX-=1; 
			canvas[boy_posY][boy_posX]=1; 
		}else if(input=='d'){//小人右移 
			canvas[boy_posY][boy_posX]=0;
			boy_posX+=1; 
			canvas[boy_posY][boy_posX]=1;
		}
	}
}

int main()
{
	startup();  // 数据初始化	
	while (1) //  游戏循环执行
	{
		gotoxy(0,0);
		show();  // 显示画面
		updateWithoutInput();  // 与用户输入无关的更新
		updateWithInput();  // 与用户输入有关的更新
	}
	return 0;
}

再看第二次实现的带有重力加速度的下落(这次只实现到了第五步,完整的在最下面):
这次不仅改良了下落的缺点,为了减少全局变量,很多精灵的属性都只用数组frame中的值代替了。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>

#define high 30
#define wide 40

//1为人,2为板,3为边界,4为上边界的锯齿//
void starup();
void show();
void updateWithoutinput();
void updateWithinput();
void gotoxy(int a, int b);               //清屏//

int frame[high][wide];
int i,j;
int radius;
int interval_static;
int interval_1,interval_2;                           //首先是可以用于调控新板生成的频率,其次可以让小球下落与整个画面的上升产生频率的落差感,造成重力的假象// 
int board_1,board_2,board_3;
int ball;//小人的位置 
int judge=0;                                         //用于跳出两层循环的变量// 
char ch;

int main()
{
    starup();
	while(1)
	{
		gotoxy(0,0);
    	show();
    	updateWithoutinput();
    	updateWithinput();
	}
}

void starup()
{
	//srand(time(NULL));
	radius=2;
	interval_static=20;
	interval_1=0;
	interval_2=0;
	ball=wide/2;
	for (i=0;i<high;i++)
	{
		for (j=0;j<wide;j++)
		{
			if (j==wide-1)//右边的墙 
			{
				frame[i][j]=3;
			}
			if (j==0)//左边的墙 
			{
				frame[i][j]=3;
			}
			if (i==0&&j!=0&&j!=wide-1)//顶部的刺刀 
			{
				frame[i][j]=4;
			}
			if (i==high-1&&j>(wide/2-3)&&j<(wide/2+3))//第一块板子 
			{
                frame[i][j]=2;
			}
			if (i==high-2&&j==ball)//小人的初始位置 
			{
				frame[i][j]=1;
			}
		}
	}
}

void show()
{
	for (i=0;i<high;i++)
	{
		for (j=0;j<wide;j++)
		{
			if (frame[i][j]==2)
			{
				printf ("_");
			}
			else if (frame[i][j]==3)
			{
				printf ("|");
			}
			else if (frame[i][j]==4)
			{
				printf ("T");
			}
			else if (frame[i][j]==0)
			{
				printf (" ");
			}
			else if (frame[i][j]==1)
			{
                printf ("O");
			}
		}
		printf ("\n");
	}
}


void updateWithoutinput()
{
	judge=0;
	//srand(time(NULL));
   	if (interval_2==interval_static)           //只要板球上升,和出现新板,小球下落的刷新频率不同,就能实现重力的落差感// 
	{
		interval_2=0;                            //计时清零// 
		for (i=0;i<high;i++)
		{
			for (j=0;j<wide;j++)
			{
	            if (frame[i][j]==1&&frame[i+1][j]==2)
				{
					frame[i][j]=0;
					frame[i-1][j]=1;
				}
				else if (frame[i][j]==2&&i>1)
				{
					frame[i-1][j]=2;
					frame[i][j]=0;
				}
				else if (frame[i][j]==2&&i==1)
				{
	                frame[i][j]=0;
				}
			}
		}
    }
    else
    {
    	interval_2=interval_2+4;
	}
    
	for (i=0;i<high;i++)
	{
		for (j=0;j<wide;j++)
		{
		   if (frame[i][j]==1&&frame[i+1][j]==0)
			{
				frame[i][j]=0;
				frame[i+1][j]=1;
				judge=1;
			}
		}
		if (judge)
		{
			break;
		}
	} 
	if (interval_1==interval_static)          //频率制造器// 
	{
	  interval_1=0;                                      //计时清零// 
      board_1=rand()%13+1;
	  board_2=rand()%13+13;
	  board_3=rand()%13+24;
	  for (i=0;i<high;i++)
	  {
		  for (j=0;j<wide;j++)
		  {
			  if (i==high-1&&((j>=board_1-radius)&&(j<=board_1+radius)&&j>0||(j>=board_2-radius)&&(j<=board_2+radius)||(j>=board_3-radius)&&(j<=board_3+radius)))
			  { 
				  frame[i][j]=2;
			  }
		  }
	  }
	}
	else
	{
		interval_1=interval_1+1;
	}
}

void updateWithinput()
{
	if (kbhit())
	{
		ch=getch();
		if (ch=='A')
		{
	    	for (i=0;i<high;i++)
	          {
		        for (j=0;j<wide;j++)
		         {
		         	if (frame[i][j]==1)
		         	{
		         	  frame[i][j]=0;
					  frame[i][j-1]=1;	
					  break;
					}
				 }
			  }
		}
	    if (ch=='D')
		{
	    	for (i=0;i<high;i++)
	          {
		        for (j=0;j<wide;j++)
		         {
		         	if (frame[i][j]==1)
		         	{
		         	  frame[i][j]=0;
					  frame[i][j+1]=1;
					  break;	         //加入break的原因是不加入的话,循环会一直将1往后推导致这一排全为0了// 
					}
				 }
			  }
		}
	}
}

void gotoxy(int a, int b)
{
        int xx=0x0b;
        HANDLE hOutput;
        COORD loc;
        loc.X =a;
        loc.Y=b;
        hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleCursorPosition(hOutput, loc);
        return;
}

(2)还有就是随分数增加难度提升

其实就是加一个分数的判断,随着指定分数到达后就增加板子更新的速率interval_1和上升的速率interval_2,其本质还是增加循环开启的频率,下面是最完整的代码

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>

#define high 25
#define wide 40

void starup();
void show();
void updateWithoutinput();
void updateWithinput();
void gotoxy(int a, int b); 
int frame[high][wide];  //1为人,2为板,3为边界,4为上边界的锯齿//
int i,j;
int radius;
int interval_static;
int interval_1,interval_2;     //首先是可以用于调控新板生成的频率,其次可以让小球下落与整个画面的上升产生频率的落差感,造成重力的假象// 
int board_1,board_2,board_3;
int ball;
int judge=0;                                         //用于跳出两层循环的变量// 
int score;  
int turn_1,turn_2;                                          //刷新木板上升的中间量

char ch;
char input;

int main()
{
    starup();
    printf ("温馨提示:\nA向左,D向右\n难度会不断增加\n按回车键继续");
	scanf ("%c", &input);
	
	while(1)
	{
		gotoxy(0,0);
    	show();
    	updateWithoutinput();
    	updateWithinput();
	}
}

void starup()
{
	srand(time(NULL));
	radius=2;
	score=0;
	turn_1=1;
	turn_2=4;
	interval_static=64;
	interval_1=0;
	interval_2=0;
	ball=wide/2;
	for (i=0;i<high;i++)
	{
		for (j=0;j<wide;j++)
		{
			if (j==wide-1)
				frame[i][j]=3;
			if (j==0)
				frame[i][j]=3;
			if (i==0&&j!=0&&j!=wide-1)
				frame[i][j]=4;
			if (i==high-1&&j>(wide/2-3)&&j<(wide/2+3))
                frame[i][j]=2;
			if (i==high-2&&j==ball)
				frame[i][j]=1;
		}
	}
}

void show()
{
	gotoxy(0,0);
	for (i=0;i<high+1;i++)
	{
		for (j=0;j<wide;j++)
		{
			if (i==high)
			{
				printf ("score:%d", score);
				break;
			}
			if (frame[i][j]==2)
				printf ("_");
			else if (frame[i][j]==3)
				printf ("|");
			else if (frame[i][j]==4)
				printf ("T");
			else if (frame[i][j]==0)
				printf (" ");
			else if (frame[i][j]==1)
                printf ("O");
		}
		printf ("\n");
	}
}

void updateWithoutinput()
{
	judge=0;
	srand(time(NULL));
	if (score>=10&&turn_1==1&&turn_2==4)
	{
		interval_1=0;
		interval_2=0; 
		turn_1=2;
		turn_2=8;
	}
	if (score>=25&&turn_1==2&&turn_2==8)
	{
		interval_1=0;
		interval_2=0; 
		turn_1=4;
		turn_2=16;
	}
	if (score>=50&&turn_1==4&&turn_2==16)        //增加一个难度系数// 
	{
		interval_1=0;
		interval_2=0;
		turn_1=4;
		turn_2=32;
	}
	for (i=0;i<high;i++)                            //判断游戏结束// 
	{
		for (j=0;j<wide;j++)
		{
			if (frame[i][j]==1&&(i==1||i==high-1))
            	{
	                system("cls");
	             	printf ("game over!\nscore:%d", score);
		            exit(0);
	            }
		}
	}
   	if (interval_2==interval_static)          //木板上升部分以及小球上升部分// 
	{
		interval_2=0;                            //计时清零// 
		for (i=0;i<high;i++)              
		{
			for (j=0;j<wide;j++)
			{
      	      if (frame[i][j]==1&&frame[i+1][j]==2)
				{
					frame[i][j]=0;
					frame[i-1][j]=1;
				}
				else if (frame[i][j]==2&&i>1)
				{
					frame[i-1][j]=2;
					frame[i][j]=0;
				}
				else if (frame[i][j]==2&&i==1)
				{
          	      frame[i][j]=0;
				}
			}
		}
    }
    else
    	interval_2=interval_2+turn_2;

	for (i=0;i<high;i++)                             //小人下落部分// 
	{
		for (j=0;j<wide;j++)
		{
		   if (frame[i][j]==1&&frame[i+1][j]==0)
			{
				score++;                         //每下落一层分数加1// 
				frame[i][j]=0;
				frame[i+1][j]=1;
				judge=1;
			}
		}
		if (judge)
			break;
	} 
	if (interval_1==interval_static)                     //刷新木板部分// 
	{
	  interval_1=0;                                      //计时清零// 
      board_1=rand()%13+1;
	  board_2=rand()%13+13;
	  board_3=rand()%13+24;
	  for (i=0;i<high;i++)
	  {
		  for (j=0;j<wide;j++)
		  {
			  if (i==high-1&&((j>=board_1-radius)&&(j<=board_1+radius)&&j>0||(j>=board_2-radius)&&(j<=board_2+radius)||(j>=board_3-radius)&&(j<=board_3+radius)))
			  { 
				  frame[i][j]=2;
			  }
		  }
	  }
	}
	else
		interval_1=interval_1+turn_1;
}
	
void updateWithinput()
{
	if (kbhit())
	{
		ch=getch();
		if (ch=='a')
		{
	    	for (i=0;i<high;i++)
	          {
		        for (j=0;j<wide;j++)
		         {
		         	if (frame[i][j]==1)
		         	{
		         	  frame[i][j]=0;
					  frame[i][j-1]=1;	
					  break;
					}
				 }
			  }
		}
	    if (ch=='d')
		{
	    	for (i=0;i<high;i++)
	          {
		        for (j=0;j<wide;j++)
		         {
		         	if (frame[i][j]==1)
		         	{
		         	  frame[i][j]=0;
					  frame[i][j+1]=1;
					  break;	    //加入break的原因是不加入的话,循环会一直将1往后推导致这一排全为0了
					}
				}
			}
		}
	}
}

void gotoxy(int a, int b)
{
	int xx=0x0b;
	HANDLE hOutput;
	COORD loc;
	loc.X =a;
	loc.Y=b;
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput, loc);
	return;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值