创建常量
#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++;
}
}