飞翔的年兽

创建常量

#define UP_DOWN_DISTANCE 5  //上下柱子之间的距离
#define LEFT_RIGHT_DISTANCE 20 //左右柱子之间的距离
#define LENGTH 6 //储存随机数

创建结构体

  • 年兽

    struct bird {
        //年兽的形象
        char ch[10];
    	//年兽的初始位置
    	int x;
    	int y;
    	int speed;//年兽的速度
    }={"○",15,13,2};
    
  • 柱子

    struct pillar
    {
    	//柱子的起始坐标
    	int x;
    	int y;
    	int hight;//柱子的高度
    
    };
    

设置光标

  • 还是抄就行

    void gotoxy(int x, int y)
    {
    	COORD pos = { x,y };
    	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
    	SetConsoleCursorPosition(hout, pos);
    }
    

创建界面

  • 界面大小

    system("mode con cols=120 lines=30");//cols是列,lines是行
    
  • 开始界面

    void startMap()
    {
    	printf("\n\n\n");
    	printf("\t\t\t----------------------------------------------------------------------\n");
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t-                             开始游戏                               -\n");
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t----------------------------------------------------------------------\n\n\n");
    	gotoxy(51, 15);
    	system("pause");
    }
    
  • 结束界面

    void endMap()
    {
    
    	system("cls");
    	printf("\n\n\n");
    	printf("\t\t\t----------------------------------------------------------------------\n");
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t-                             开始结束                               -\n");
    	printf("\t\t\t-                           你的得分为:%d                           -\n",score);
    	printf("\t\t\t-                                                                    -\n");
    	printf("\t\t\t----------------------------------------------------------------------\n\n\n");
    	gotoxy(51, 15);
    	system("pause");
    }
    

设置年兽

  • 画年兽

    void drawBird(int y)
    {
    	gotoxy(flyBird.x, y);
    	printf("%s", flyBird.ch);
    }
    
    
  • 覆盖掉年兽

    void deleteBird(int y)
    {
    	gotoxy(flyBird.x, y);
    	printf("  ");
    }
    
  • 年兽向上升,别看现在只有一行代码,后面用来判断是否会和柱子碰撞有用

    void birdJump(int y)
    {
    	deleteBird(y);
    	flyBird.y -= flyBird.speed;
    }
    

判断是否会撞墙

  • 撞到墙会返回1,否则就返回0

    int isHitFloor(int y)
    {
    	if (flyBird.y < 0 || flyBird.y > 28)
    	{
    		return 1;
    	}
    	else {
    		return 0;
    	}
    }
    

    当返回1时,就退出循环

    		if (isHitFloor(flyBird.y))
    		{
    			break;
    		}
    

设置柱子

  • 利用随机数,设置上下柱子的长度

    void arrayRand()
    {
    	for (int i = 0; i < LENGTH; i++)
    	{
    		Pipe[i].hight = rand() % 10 + 10;
    	}
    }
    
  • 创建柱子

    void creatPipe(int move)
    {
    	int i = 0;
    	int y = 0;
    	int x = 0;
    	for (x = 31-move ; x < 120; x += LEFT_RIGHT_DISTANCE)//循环五次,在指定位置生成五个柱子
    	{
    		
    		//生成上半部分的柱子
    		for (y = 0; y < Pipe[i].hight; y++) {
    			gotoxy(x, y);
    			printf("*");
    		}
    		
    		//实时记录柱子的位置
    		Pipe[i].x = x;
    		Pipe[i].y_up = Pipe[i].hight;
    		Pipe[i].y_down = y + UP_DOWN_DISTANCE;
    		//生成下半部分的柱子
    		for (y = y + UP_DOWN_DISTANCE; y < 30; y++)
    		{
    			gotoxy(x, y);
    			printf("*");
    		}
    		i++;
    	}
    }
    
    • 为了检测柱子的信息是否正确,写了一个打印函数来确认

      void printPipe()
      {
      	for (int i = 0; i < LENGTH; i++)
      	{
      		gotoxy(0, i);
      		printf("%d %d %d\n", Pipe[0].x, Pipe[0].y_up, Pipe[0].y_down);
      	}
      }
      
  • 覆盖柱子

    void deletePipe(int move)
    {
    	int i = 0;
    	int y = 0;
    	int x = 0;
    	for (x = 31-move; x < 120; x += LEFT_RIGHT_DISTANCE)//循环五次,覆盖掉指定位置的柱子
    	{
    
    		//覆盖掉上半部分的柱子
    		for (y = 0; y < Pipe[i].hight; y++) {
    			gotoxy(x, y);
    			printf(" ");
    		}
    
    		//覆盖掉下半部分的柱子
    		for (y = y + UP_DOWN_DISTANCE; y < 30; y++)
    		{
    			gotoxy(x, y);
    			printf(" ");
    		}
    
    		i++;
    	}
    }
    
  • 柱子的移动

    void movePipe()
    {
    	move = 0;
    	arrayRand();
    	while (1)
    	{
    		creatPipe(move);
    		Sleep(200);
    		deletePipe(move);
    		move++;
    
    		//简单的来说,就是将第一个柱子接到第六条柱子后面,但第一条柱子再次出场时,数值发生了改变
    		if (move == 20)
    		{
    			//当第一条柱子移动了20个单位时(此刻此刻的年兽以及穿过柱子了),将偏移量move归零
    			move = 0;
    			//此刻将第二个随机数以后的数都向前移动一位,将第一个随机数覆盖掉,空出最后一个位置
    			for (int i = 0; i < LENGTH - 1; i++)
    			{
    				Pipe[i].hight = Pipe[i + 1].hight;
    			}
    			//重新生成一个随机数放到最后一位
    			Pipe[LENGTH - 1].hight = rand() % 10 + 10;
    
    		}
    	}
    }
    
  • 接下来就是将年兽的移动和柱子的移动进行结合了

运行

  • 年兽的上下运动,柱子的移动,分数的计算都在这里完成

    void run()
    {
    	startMap();//开始界面
    	move = 0;
    	arrayRand();//生成随机数
    	while (1)
    	{
    		drawBird(flyBird.y);//初始化年兽
    		creatPipe(move);//柱子初始化(在界面生成5条柱子) 
    		for (int i = 0; i < 10; i++)//该循环可当作时间延迟
    		{
    			if (_kbhit())
    			{
    				//该出判断用来打断下降的时间循环,即刚按下按键就可让年兽向上升,不用等到每一次下降的时间结束在再上升
    				//可让年兽的上升操作更顺畅
    				char ch = _getch();
    				if (ch == 32)//空格的ascil码为32
    				{
    					birdJump(flyBird.y);//让年兽上升
    					break;
    				}
    
    			}
    			Sleep(1);//睡眠1毫秒,20次循环共20毫秒,但是可能里面的函数运行时会有时间延迟,所以总时间不止20毫秒
    		}
    		if (isHitFloor(flyBird.y) || isHitPipe())//判断是否会撞到边界或柱子
    		{
    			Sleep(1000);//死亡后,睡眠1秒
    			break;
    		}
    
    		getScore();//得分
    
    		deleteBird(flyBird.y);//覆盖掉上一个年兽的痕迹
    		deletePipe(move);//覆盖掉上一个柱子的痕迹
    		move++;//偏移量加1,即柱子向左移动
    
    		if (move == 20)
    		{
    			//当第一条柱子移动了20个单位时(此刻此刻的年兽以及穿过柱子了),将偏移量move归零
    			move = 0;
    			//此刻将第二个随机数以后的数都向前移动一位,将第一个随机数覆盖掉,空出最后一个位置
    			for (int i = 0; i < LENGTH - 1; i++)
    			{
    				Pipe[i].hight = Pipe[i + 1].hight;
    			}
    			//重新生成一个随机数放到最后一位
    			Pipe[LENGTH - 1].hight = rand() % 10 + 10;
    
    		}
    
    		
    		flyBird.y += 1;//下降1的单位
    	}
    	endMap();//结束界面
    }
    
    

得分

  • 需要注意的一个点是getScore()函数要放在判断是否会撞到墙的if语句之后,因为两者都对(Pipe[0].x==flyBird.x)成立。如果getScore()放在判断是否会撞到墙的if语句之前,就算年兽撞到了墙,还是会加1 分后在死亡

    void getScore()
    {
    	gotoxy(0, 0);
    	printf("得分:%d", score);
    	if (Pipe[0].x == flyBird.x)
    	{
    		score++;
    	}
    }
    

选择角色

  • 为了增加游戏的趣味性,这一功能是特别加入的

  • 箭头图标(需要将界面调大)

    void selectMap()
    {
    	system("cls");
    	printf("\n\n\n\n\n");
    	printf("\t\t\t\t\t\t      请选择角色\n");
    	printf("\n\n\n\n\n");
    	
    	printf("\t\t\t\t      *                                         *                     \n");
    	printf("\t\t\t\t    * *                                         * *                      \n");
    	printf("\t\t\t\t  * * *                                         * * *             \n");
    	printf("\t\t\t\t    * *                                         * *              \n");
    	printf("\t\t\t\t      *                                         *                     \n");
    	
    
    }
    
  • 选择功能

    void selectRole()
    {
    	char role[10][5] = { "★","○","□" ,"=","@" };//“年兽”
    	int flag = 0;
    	while (1)
    	{
    		for (int i = 12; i < 15; i++)
    		{
    			gotoxy(59, i);
    			printf("%s", role[flag]);
    			for (int j = 0; j < 15; j++)
    			{
    				if (_kbhit())
    				{
    					//回车,ASCII码13;“键盘上下左右 方向键的键码(keyCode)是38、40、37和39,或者称虚拟ASCII值是38、40、37和39。”
    					char ch = _getch();
    					if (ch == 77 && flag < 4)//空格的ascil码为32
    					{
    						flag++;
    					}
    					else if (ch == 75 && flag > 0)
    					{
    						flag--;
    					}
    					else if (ch == 32)
    					{
    						system("cls");
    						return;
    					}
    				}
    				strcpy_s(flyBird.ch, role[flag]);
    				Sleep(1);
    			}
    			gotoxy(59, i);
    			printf("  ");
    			
    			
    		}
    		
    		
    	}
    
    }
    

新年祝福

  • 好吧,由于界面的原因,现在显示出来的东西很乱
void printNewYear()
{
	system("cls");
	printf("\n\n\n\n\n");


	printf("\t      *                                  *                  *               *                      *    \n");
	printf("\t       *                 *             *                    *               *                    *      \n");
	printf("\t  * * * * * * *        *             * * * * * * * * *      *        * * * * * * *            *         \n");
	printf("\t    *      *        *              *        *               * *             *    *         *               \n");
	printf("\t      *  *        * * * * * *   *           *               *  *           *     *         *      *       \n");
	printf("\t * * * * * * * *  *     *           * * * * * * * * *     * *   *         *      *         *      *       \n");
	printf("\t       *          *     *           *       *            *  *      * * * * * * * * * *     * * * * * * * *  \n");
	printf("\t   * * * * *      *     *           *       *           *   *           *   *                  *  *  *    \n");
	printf("\t     * * *        *     *       * * * * * * * * * * * *     *         *       *               *   *    *  \n");
	printf("\t    *  *  *       *     *                   *               *       *           *           *     *      * \n");
	printf("\t   *   *   *      *     *                   *               *     *               *       *       *        *   \n");
	printf("\t  *    *    *     *     *                   *               *   *                   *   *         *          *  \n");
	printf("\t       *          *     *                   *               *                                     *       \n");
	 


}

完整代码

  • 到现在总算是成功了,也没什么要总结的,就先祝大家新年快乐
 
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<conio.h> 
#include<time.h>
#include<string.h>

#define UP_DOWN_DISTANCE 7  //上下柱子之间的距离
#define LEFT_RIGHT_DISTANCE 20 //左右柱子之间的距离
#define LENGTH 6 //储存随机数


//柱子的结构体
struct pipe
{
	//柱子的起始坐标
	int x;
	int y_up;
	int y_down;
	int hight;//柱子的高度

};

struct bird {
	//年兽的形象
	char ch[10];
	//年兽的初始位置
	int x;
	int y;
	int speed;//年兽的速度
}flyBird = { "○",15,13,3 };

int score = 0;//得分
int random[LENGTH];
int move = 0;//偏移量

struct pipe Pipe[LENGTH];


void gotoxy(int x, int y);//设置光标
void startMap();//设置游戏开始界面
void endMap();//设置游戏结束界面
void run();//运行
void drawBird(int y);//画年兽
void deleteBird(int y);//覆盖掉年兽
void birdJump(int y);//年兽上升
int isHitFloor(int y);//判断年兽是否会撞到边界
void creatPipe(int move);//创建柱子
void arrayRand();//创建随机数
void deletePipe(int move);//覆盖柱子
void movePipe();//移动柱子
int isHitPipe();//判断是否会撞到柱子
void printPipe();//打印柱子的信息
void getScore();//得分
void selectMap();//打印选择图标
void selectRole();//选择角色
void printNewYear();//打印新年快乐


int main()
{
	srand((unsigned int)time(NULL));//随机数种子
	system("mode con cols=130 lines=30");//cols是列,lines是行
	//movePipe();
	//run();
	run();
	//printNewYear();
	return 0;
}

//设置鼠标
void gotoxy(int x, int y)
{
	COORD pos = { x,y };
	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hout, pos);
}

void startMap()
{
	printf("\n\n\n");
	printf("\t\t\t----------------------------------------------------------------------\n");
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t-                             开始游戏                               -\n");
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t----------------------------------------------------------------------\n\n\n");
	gotoxy(51, 15);
	system("pause");
	system("cls");
}

void endMap()
{

	system("cls");
	printf("\n\n\n");
	printf("\t\t\t----------------------------------------------------------------------\n");
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t-                             游戏结束                               -\n");
	printf("\t\t\t-                           你的得分为:%d                           -\n",score);
	printf("\t\t\t-                                                                    -\n");
	printf("\t\t\t----------------------------------------------------------------------\n\n\n");
	gotoxy(51, 15);
	system("pause");
	system("cls");
}

void selectMap()
{
	system("cls");
	printf("\n\n\n\n\n");
	printf("\t\t\t\t\t\t      请选择角色\n");
	printf("\n\n\n\n\n");
	
	printf("\t\t\t\t      *                                         *                     \n");
	printf("\t\t\t\t    * *                                         * *                      \n");
	printf("\t\t\t\t  * * *                                         * * *             \n");
	printf("\t\t\t\t    * *                                         * *              \n");
	printf("\t\t\t\t      *                                         *                     \n");
	
}
void printNewYear()
{
	system("cls");
	printf("\n\n\n\n\n");


	printf("\t         *                                  *                  *              *                          *    \n");
	printf("\t          *                 *             *                    *              *                       *      \n");
	printf("\t     * * * * * * *        *             * * * * * * * * *      *        * * * * * * *             *         \n");
	printf("\t       *      *        *              *        *               * *            *     *         *               \n");
	printf("\t         *  *        * * * * * *   *           *               *  *           *     *         *      *       \n");
	printf("\t    * * * * * * * *  *     *           * * * * * * * * *     * *   *         *      *         *      *       \n");
	printf("\t          *          *     *           *       *            *  *      * * * * * * * * * *     * * * * * * * *  \n");
	printf("\t      * * * * *      *     *           *       *           *   *           *   *                  *  *  *    \n");
	printf("\t        * * *        *     *       * * * * * * * * * * * *     *         *       *               *   *    *  \n");
	printf("\t       *  *  *       *     *                   *               *       *           *           *     *      * \n");
	printf("\t      *   *   *      *     *                   *               *     *               *       *       *        *   \n");
	printf("\t     *    *    *     *     *                   *               *   *                   *          *  *             \n");
	printf("\t          *          *     *                   *               *                                     *       \n");
	 
}
void selectRole()
{
	char role[10][5] = { "★","○","□" ,"=","@" };//“年兽”
	char name[10][10] = { "年兽星星","年兽圆圆","年兽方方","年兽等等","年兽艾特" };
	int flag = 0;
	while (1)
	{
		for (int i = 12; i < 15; i++)
		{
			gotoxy(59, i);
			printf("%s", role[flag]);
			for (int j = 0; j < 15; j++)
			{
				if (_kbhit())
				{
					//回车,ASCII码13;“键盘上下左右 方向键的键码(keyCode)是38、40、37和39,或者称虚拟ASCII值是38、40、37和39。”
					char ch = _getch();
					if (ch == 77 && flag < 4)//空格的ascil码为32
					{
						flag++;
					}
					else if (ch == 75 && flag > 0)
					{
						flag--;
					}
					else if (ch == 32)
					{
						system("cls");
						return;
					}
				}
				strcpy_s(flyBird.ch, role[flag]);
				Sleep(1);
			}
			gotoxy(59, i);
			printf("  ");
			gotoxy(56, 17);
			printf("%s", name[flag]);
			
			
		}
		
		
	}

}
void run()
{
	startMap();//开始界面 
	selectMap();
	selectRole();
	
	
	move = 0;
	arrayRand();//生成随机数
	while (1)
	{
		drawBird(flyBird.y);//初始化年兽
		creatPipe(move);//柱子初始化(在界面生成5条柱子) 
		for (int i = 0; i < 10; i++)//该循环可当作时间延迟
		{
			if (_kbhit())
			{
				//该出判断用来打断下降的时间循环,即刚按下按键就可让年兽向上升,不用等到每一次下降的时间结束在再上升
				//可让年兽的上升操作更顺畅
				char ch = _getch();
				if (ch == 32)//空格的ascil码为32
				{
					birdJump(flyBird.y);//让年兽上升
					break;
				}
				 
			}
			Sleep(1);//睡眠1毫秒,20次循环共20毫秒,但是可能里面的函数运行时会有时间延迟,所以总时间不止20毫秒
		}
		if (isHitFloor(flyBird.y) || isHitPipe())//判断是否会撞到边界或柱子
		{
			//printPipe();
			Sleep(1000);//死亡后,睡眠1秒
			break;
		}

		getScore();//得分

		deleteBird(flyBird.y);//覆盖掉上一个年兽的痕迹
		deletePipe(move);//覆盖掉上一个柱子的痕迹
		move++;//偏移量加1,即柱子向左移动

		if (move == 20)
		{
			//当第一条柱子移动了20个单位时(此刻此刻的年兽以及穿过柱子了),将偏移量move归零
			move = 0;
			//此刻将第二个随机数以后的数都向前移动一位,将第一个随机数覆盖掉,空出最后一个位置
			for (int i = 0; i < LENGTH - 1; i++)
			{
				Pipe[i].hight = Pipe[i + 1].hight;
			}
			//重新生成一个随机数放到最后一位
			Pipe[LENGTH - 1].hight = rand() % 10 + 10;

		}

		
		flyBird.y += 1;//下降1的单位
	}
	endMap();//结束界面
}

//这三个函数的使用要特别注意调用顺序
//画年兽
void drawBird(int y)
{
	gotoxy(flyBird.x, y);
	printf("%s", flyBird.ch);
}

//覆盖年兽
void deleteBird(int y)
{
	gotoxy(flyBird.x, y);
	printf("  ");
}
//年兽上升
void birdJump(int y)
{
	deleteBird(y);
	flyBird.y -= flyBird.speed;
}

//判断是否会撞到墙,撞到时返回1
int isHitFloor(int y)
{
	if (flyBird.y < 0 || flyBird.y > 28)
	{
		return 1;
	}
	else {
		return 0;
	}
}

//生成随机数,设置为并将上柱子的长度,生成的随机数放到数组中
void arrayRand()
{
	for (int i = 0; i < LENGTH; i++)
	{
		Pipe[i].hight = rand() % 10 + 10;
	}
}

void creatPipe(int move)
{
	int i = 0;
	int y = 0;
	int x = 0;
	for (x = 31-move ; x < 120; x += LEFT_RIGHT_DISTANCE)//循环五次,在指定位置生成五个柱子
	{
		
		//生成上半部分的柱子
		for (y = 0; y < Pipe[i].hight; y++) {
			gotoxy(x, y);
			printf("*");
		}
		
		//实时记录柱子的位置
		Pipe[i].x = x;
		Pipe[i].y_up = Pipe[i].hight;
		Pipe[i].y_down = y + UP_DOWN_DISTANCE;
		//生成下半部分的柱子
		for (y = y + UP_DOWN_DISTANCE; y < 30; y++)
		{
			gotoxy(x, y);
			printf("*");
		}
		i++;
	}
}
void printPipe()
{
	

	gotoxy(0, 2);
	printf("%d %d %d\n", Pipe[0].x, Pipe[0].y_up, Pipe[0].y_down);
	gotoxy(0, 3);
	printf("%d %d", flyBird.x, flyBird.y);
}
void deletePipe(int move)
{
	int i = 0;
	int y = 0;
	int x = 0;
	for (x = 31-move; x < 120; x += LEFT_RIGHT_DISTANCE)//循环五次,覆盖掉指定位置的柱子
	{

		//覆盖掉上半部分的柱子
		for (y = 0; y < Pipe[i].hight; y++) {
			gotoxy(x, y);
			printf(" ");
		}

		//覆盖掉下半部分的柱子
		for (y = y + UP_DOWN_DISTANCE; y < 30; y++)
		{
			gotoxy(x, y);
			printf(" ");
		}

		i++;
	}
}

void movePipe()
{
	move = 0;
	arrayRand();
	while (1)
	{
		creatPipe(move);
		Sleep(200);
		deletePipe(move);
		move++;

		//简单的来说,就是将第一个柱子接到第六条柱子后面,但第一条柱子再次出场时,数值发生了改变
		if (move == 20)
		{
			//当第一条柱子移动了20个单位时(此刻此刻的年兽以及穿过柱子了),将偏移量move归零
			move = 0;
			//此刻将第二个随机数以后的数都向前移动一位,将第一个随机数覆盖掉,空出最后一个位置
			for (int i = 0; i < LENGTH - 1; i++)
			{
				Pipe[i].hight = Pipe[i + 1].hight;
			}
			//重新生成一个随机数放到最后一位
			Pipe[LENGTH - 1].hight = rand() % 10 + 10;

		}
	}
}

int isHitPipe()
{
	if (flyBird.x+1 == Pipe[0].x || flyBird.x == Pipe[0].x)
	{
		if (flyBird.y >= Pipe[0].y_up&&flyBird.y <Pipe[0].y_down+1 )
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
	else {
		return 0;
	}
}

void getScore()
{
	gotoxy(0, 0);
	printf("得分:%d", score);
	if (Pipe[0].x == flyBird.x)
	{
		score++;
	}
}
上一篇:Pset_PackingInstructions


下一篇:Rust中变量的移动move