本文共 6282 字,大约阅读时间需要 20 分钟。
这次游戏项目的更新,比平时来得更晚一些~~~
前情提要:在做到弹跳的小球的课后题时,我被“按空格键发射新的小球”难住了。
宝书镇楼:
于是我想起了一个之前看网课学的“快速敲字母”游戏来类比我要实现的功能。
(详情可以看我的这篇博文:https://blog.csdn.net/bailichen800/article/details/115560127?spm=1001.2014.3001.5501)话不多说,实现的功能:
1.按空格键生成一个小球 2.每一关随机生成随机数目的砖块 3.挡板可以通过按awsd来左上下右自由移动 4.可以由玩家选择是否重复玩多关与快速敲字母游戏一样,本项目建议使用DEV C++运行,因为VS2019会报异常!!!!
与快速敲字母游戏一样,本项目建议使用DEV C++运行,因为VS2019会报异常!!!!
与快速敲字母游戏一样,本项目建议使用DEV C++运行,因为VS2019会报异常!!!!
因为电脑坏了,之前敲的书上初级代码不幸遗失,所以这次只有我完成的升级版代码了。
资源稍后放上,可在我个人主页自取。#include#include #include #include #include #include #define Height 15#define Width 20using namespace std;HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取句柄COORD crd;void gotoxy(int x, int y)//移动光标函数{ crd.X = x; crd.Y = y; SetConsoleCursorPosition(handle, crd);//设置光标位置为传入的参数x,y }struct Ball//球类 { private: int ball_x; int ball_y; int ball_vx = 1; int ball_vy = 1;public: Ball(int x, int y) { ball_x = x; ball_y = y; } int GetBall_x() { return ball_x; } int GetBall_y() { return ball_y; } void FallBall() { //获得小球原来的位置坐标,准备输出空格将其删除 gotoxy(GetBall_x(),GetBall_y()); cout << " ";//擦除当前小球的图案 ball_x += ball_vx; ball_y += ball_vy; } void ChangeXWay() { ball_vx = -ball_vx; } void ChangeYWay() { ball_vy = -ball_vy; }};class Block//砖块类{ private: int block_x; int block_y;public: Block(int x, int y) { block_x = x; block_y = y; } int GetBlock_x() { return block_x; } int GetBlock_y() { return block_y; }};class Plate//挡板类{ private: int ridus;//半径 int left = position_x - ridus;//左边界 int right = position_x + ridus;//右边界public: int position_x, position_y;//挡板中心坐标 Plate(int x, int y, int r) { position_x = x, position_y = y; ridus = r; ChangeBound(); }//调用构造函数时就要算一次左右边界 int GetLeft() { return left; } int GetRight() { return right; } void ChangeBound()//在圆心坐标改变的时候改变左右边界 { left = position_x - ridus;//左边界 right = position_x + ridus;//右边界 }};Plate plate((int)Width / 2, (int)Height - 1,5);class BallController//控制小球的下落、挡板的移动{ private: vector balls;//小球 vector blocks;//砖块 short delay;//保存延时时间 short score;//保存得分public: BallController() { score = 0; delay = 100; }//初始化得分为0 void GenerateBall()//按下空格,调用此函数,产生小球 { Ball ball(Width/2,Height/2);//初始位置从游戏中心区域发出 balls.push_back(ball);//加入动态数组 } void GenerateBlock()//无需输入,顶上三排每排自动生成10-19随机个数的砖块 { for (int i = 0; i < 3; i++)//i表示纵坐标,三排 { for (int j = 0; j < Width; j++)//j表示横坐标,哪一列 { if (j < rand() % 10 + 10)//Width是20,j如果小于10-19的数就生成砖块,否则生成空格 { Block block(j, i); blocks.push_back(block); } else { printf(" "); } } } } bool Ground(Ball* ball) { return ball->GetBall_y() >= Height-1;//看小球纵坐标是否大于等于高度,是则表示落地了 } short Fall()//判断小球是否正常下落,是返回0,不是返回-1(即落地,游戏结束) { vector ::iterator itr; for (itr = balls.begin(); itr != balls.end(); itr++) { //获得小球原来的位置坐标,准备输出空格将其删除 gotoxy(itr->GetBall_x(),itr->GetBall_y()); cout << " ";//擦除当前小球的图案 if (Ground(&(*itr)))//如果触地,游戏结束 { crd.X = 13; crd.Y = Height + 2; SetConsoleCursorPosition(handle, crd); SetConsoleTextAttribute(handle, BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);//白色背景 cout << "Game Over!" << endl; SetConsoleTextAttribute(handle, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);//恢复默认黑色背景 printf("\a"); return -1;//返回-1告知本函数的调用块:游戏已经结束 } if ((itr->GetBall_y() == 1)|| (itr->GetBall_y() == plate.position_y-1) && (itr->GetBall_x() >= plate.GetLeft() && itr->GetBall_x() <= plate.GetRight()))//小球的纵坐标等于0,碰到边界要反弹(如果等于Height的话就属于前面结束游戏的情况了) { //注意碰到挡板的情况也是只有y反向,如果写成x、y都反向,小球就会不停原路返回,详见下方else if被注释的错误代码 itr->ChangeYWay();//y方向反向 } if (itr->GetBall_x() == 0+1 || itr->GetBall_x() == Width-1)//边界是[0,Width] ,左右各自提前一格判断,这样小球输出的空格就不会影响边界,上面条件的 (itr->GetBall_y() == plate.position_y-1) 同理 { itr->ChangeXWay();//x方向反向 } //以下else if代码有问题,会导致小球始终原路返回 //else if ((itr->GetBall_y() == plate.position_y) && (itr->GetBall_x() >= plate.GetLeft() && itr->GetBall_x() <= plate.GetRight())|| (itr->GetBall_x() == 0 || itr->GetBall_x() == Width)|| (itr->GetBall_y() == 0)) //{//如果小球碰到挡板,那么X、Y方向都会反向(判断条件是纵坐标和挡板一样并且横坐标位于挡板左右边界(圆心+-半径)之间) // itr->ChangeXWay(); // itr->ChangeYWay(); //} vector ::iterator blockitr; for (blockitr = blocks.begin(); blockitr != blocks.end(); ) { //blockitr是砖块数组的迭代器,itr是小球数组的迭代器 if (blockitr->GetBlock_x() == itr->GetBall_x() && blockitr->GetBlock_y() == itr->GetBall_y())//如果这个砖块的坐标==小球的坐标 { gotoxy(blockitr->GetBlock_x(), blockitr->GetBlock_y());//坐标移到砖块处 cout << " ";//砖块被消除,变成空格 blocks.erase(blockitr);//消除这个砖块(此刻迭代器自动指向下一个元素了 score++;//得分+1 } else { blockitr++;//这个分支说明没消除砖块,迭代器手动后移 } } gotoxy(itr->GetBall_x(), itr->GetBall_y()); cout << "o";//在新位置画出小球 itr->FallBall();//只要未触地就继续下落,y坐标变化 ShowBall(); } Wait(); return 0; } void MovePlate(char input) { if (input == 'a' && plate.GetLeft() > 0)//挡板左移 { plate.position_x--; plate.ChangeBound();//重新设置左右边界 } else if (input == 'd' && plate.GetRight() < Width)//挡板右移 { plate.position_x++; plate.ChangeBound();//重新设置左右边界 } else if (input == 'w' && plate.position_y > 0)//挡板上移 { plate.position_y--; plate.ChangeBound();//重新设置左右边界 } else if (input == 's' && plate.position_y < Height-1)//挡板下移 { plate.position_y++; plate.ChangeBound();//重新设置左右边界 } } void ShowBlock()//绘制砖块 { vector ::iterator itr; for (itr = blocks.begin(); itr != blocks.end(); itr++) { gotoxy(itr->GetBlock_x(),itr->GetBlock_y()); cout << "#"; } } void ClearPlate()//绘制挡板 { gotoxy(plate.GetLeft(), plate.position_y); for (int i = plate.GetLeft(); i != plate.GetRight(); i++) { printf(" "); } } void ShowPlate()//绘制挡板 { gotoxy(plate.GetLeft(), plate.position_y); for (int i = plate.GetLeft(); i != plate.GetRight(); i++) { printf("*"); } } void ShowBall()//绘制小球 { vector ::iterator itr; for (itr = balls.begin(); itr != balls.end(); itr++) { gotoxy(itr->GetBall_x(), itr->GetBall_y()); cout << "o"; } } void SetDelay(short d)//设置延迟时间 { delay = d; } void Wait() { Sleep(delay);//按SetDelay中设定好的时间休眠 } void ShowScore()//在边界的下面两个单位处输出得分 { crd.X = 1; crd.Y = Height + 2; SetConsoleCursorPosition(handle, crd); cout << " Score: " << score << " ";//多输出几位空格来,防止上一次得分位数较多没有被完全遮挡 } void CleanAll()//清空上一局得分、砖块、小球的数组,平板移到原处 { score=0; blocks.clear(); balls.clear(); for(int i=0;i >choice; //choice=_getch();这种写法不用输入回车 }while (choice == 'y' || choice == 'Y'); return 0;}
下一道课后题是实现“接金币游戏”,emmm·····又要秃头了。(似乎就是把小球的挡板拿来接下落的字母,只不过把字母换成金币而已····?)
感谢你能看到这里,一起成为更好的自己吧~~~