- 分享
小游戏
- @ 2026-2-5 16:45:21
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
enum C
{
BLACK = 0,
BLUE = 1,
GREEN = 2,
CYAN = 3,
RED = 4,
MAGENTA = 5,
YELLOW = 6,
LIGHTGRAY = 7,
DARKGRAY = 8,
LIGHTBLUE = 9,
LIGHTGREEN = 10,
LIGHTCYAN = 11,
LIGHTRED = 12,
LIGHTMAGENTA = 13,
LIGHTYELLOW = 14,
WHITE = 15
};
void sc ( int c)
{
HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h,c);
}
const int w = 40;//宽
const int h = 20;//高
int x = w / 2, y = h - 1;
vector<int> bx, by, ex, ey;//b子弹 e敌机
int score = 0;
bool ending = false;
int cd = 0;
int maxcd;
int starttime, timeleft;
bool warning = false;
void begin()
{
sc(WHITE) ;
cout << "请输入难度(3级最难,1级最简单):";
cin >> maxcd;
system("cls");
sc(LIGHTGRAY);
cout << "规则:" << '\n';
cout << "躲避敌机and攻击敌机" << '\n';
cout << "消灭一架敌机加10分" << '\n';
cout << "最后的分数会有彩蛋,拼运气和人品的时候到了。" << '\n';
sc(BLACK);
cout << "猜猜这句话写的是啥?" << ' ';
sc(WHITE);
cout << "猜猜这里写的什么?" << '\n';
sc(LIGHTBLUE);
cout << "操作: 向左:A 向右:D 发射子弹:空格" << '\n';
sc(LIGHTMAGENTA);
cout << "限时 180秒" << '\n' ;
sc(LIGHTRED);
cout << "注意不要离敌机太近才释放子弹" << '\n';
sc(LIGHTYELLOW);
cout << "游戏5s后开始";
Sleep(5000);
}
void diji (int n) //初始化敌机
{
for ( int i = 0; i < n; i ++)
{
ex.push_back(rand()%w);
ey.push_back(rand()%(h/2));
}
}
int gettime()//获取当前时间
{
return GetTickCount()/1000;
}
void draw() //绘制界面
{
system("cls");
sc(DARKGRAY);
for ( int i = 0; i < w+2; i ++) cout << '#';//顶部
cout << '\n';
for ( int r = 0; r < h; r ++)//行 ,纵坐标
{
sc(DARKGRAY);
cout << '#';
for ( int c = 0; c < w; c ++)//列 , 横坐标
{
if ( r == y && c == x)
{
sc(LIGHTYELLOW);
cout << 'A';
}
else
{
bool f = false;
for ( size_t i = 0; i < bx.size(); i ++)//子弹 b
{
if ( bx[i] == c && by[i] == r)
{
sc(LIGHTCYAN);
cout << '|' ;
f = true;
break;
}
}
if (!f)
{
for ( size_t i = 0; i < ex.size(); i ++)//敌机e
{
if ( ex[i] == c && ey[i] == r)
{
sc(LIGHTRED);
cout << 'V';
f = true;
break;
}
}
}
if (!f)
{
sc(BLACK);
cout << ' ';
}
}
}
sc(DARKGRAY);
cout << '#' << '\n';
}
sc(DARKGRAY) ;
for ( int i = 0; i < w+2; i ++) cout << '#';//底部
cout << '\n';
sc(LIGHTGREEN);
cout << "分数:" << score << '\n' ;//分数
if ( timeleft > 30) sc(GREEN);
else if ( timeleft <= 30 && timeleft > 10) sc(YELLOW);
else sc(RED);
cout << "剩余时间:" << timeleft << 's' << '\n';//时间
if ( timeleft <= 10)
{
if ( timeleft % 2 == 1) sc(LIGHTRED);
if ( timeleft % 2 == 0) sc(LIGHTYELLOW);
cout << "最后" << timeleft << "秒!" << "加油!!!" << '\n' ;//鼓励&&加油
}
sc(LIGHTGRAY);
cout << "规则:" << '\n';
cout << "躲避敌机and攻击敌机" << '\n' ;
cout << "操作: 向左:A 向右:D 发射子弹:空格" << '\n';
cout << "限时 180秒" << '\n' ;
sc(YELLOW);
cout << "如果你是全班分数最高的人,那么..." << ' ' << "啥也没有" << '\n' ;
sc(WHITE);
}
void input()//输入
{
if (GetAsyncKeyState('A')&0x8000 && x > 0) x--;
if (GetAsyncKeyState('D')&0x8000 && x < w-1) x++;
if (GetAsyncKeyState(VK_SPACE)&0x8000 && cd<=0)//添加子弹b
{
bx.push_back(x);
by.push_back(y-1);
cd = maxcd;
}
if (cd > 0) cd --;
}
void update ()//更新
{
for ( size_t i = 0; i < bx.size(); i ++)//移动子弹 b
{
by[i] --;
if ( by[i] < 0)
{
bx.erase(bx.begin()+i);
by.erase(by.begin()+i) ;
i --;
}
}
for ( size_t i = 0; i < ex.size(); i ++)//移动敌机 e
{
ey[i] ++;
if (ey[i] >= h)
{
ex.erase(ex.begin()+i);
ey.erase(ey.begin()+i);
i --;
ex.push_back(rand()%w);
ey.push_back(0);
}
}
for ( size_t i = 0; i < bx.size(); i ++)//子弹b敌机e碰撞检测
{
for ( size_t j = 0; j < ex.size(); j ++)
{
if ( bx[i] == ex[j] && by[i] == ey[j] || bx[i] == ex[j] && by[i] == ey[j]+1)
{
bx.erase(bx.begin()+i);
by.erase(by.begin()+i);
ex.erase(ex.begin()+j);
ey.erase(ey.begin()+j);
score += 10;
ex.push_back(rand()%w);
ey.push_back(0);
i --;
break;
}
}
}
for ( size_t i = 0; i < ex.size(); i ++)//玩家与敌机 e
if ( ex[i] == x && ey[i] == y)
{
ending = true;
break;
}
int nowtime = gettime();//更新时间
timeleft = 180 - (nowtime - starttime);
if ( timeleft <= 0) ending = true;
}
void gameover ()
{
system("cls");
sc(LIGHTRED);
cout << "==== Game Over ====" << '\n';
sc(WHITE);
cout << "存活时间:";
sc(LIGHTMAGENTA) ;
cout << (180-timeleft) << 's' << '\n';
Sleep(500);
sc(WHITE);
cout << "你的分数是:";
Sleep (1000);
cout << "... ..." << '\n';
Sleep (1000);
sc(LIGHTCYAN);
cout << "期待一下吧" << '\n';
Sleep(1000) ;
sc (WHITE);
cout << "你的分数是:";
sc(LIGHTRED);
cout << score << '\n';
Sleep(500);
if ( score == 430 || score == 390 || score == 130 || score == 170 || score == 90 || score == 180 || score == 50)
{
score *= 2;
sc(LIGHTMAGENTA);
cout << "恭喜你!运气不错 开到盲盒了,总分数翻倍" << '\n';
cout << "你最终的分数是:";
sc(LIGHTRED);
cout << score << '\n';
}
sc(RED);
if ( score <= 50) cout << "再接再厉!!!" << '\n' ;
else if ( score > 50 && score <= 200) cout << "还不错,下次继续加油!" << '\n';
else if ( score > 200 && score <= 500) cout << "太有实力了!!!" << '\n';
else if ( score > 500) cout << "太太太太太有实力了!!! 可谓是古希腊掌管游戏的神" << '\n';
sc(WHITE);
}
int main ()
{
begin();
srand(time(0));//随机数种子
diji(6);//初始化敌机
starttime = gettime();
timeleft = 180;
HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO ci;
GetConsoleCursorInfo(h,&ci);
ci.bVisible=0;
SetConsoleCursorInfo(h,&ci); //光标
while(!ending)
{
draw();
input();
update();
Sleep(50);//数字 = 1000 / 帧率
}
gameover();
Sleep(5000);
return 0;
}
1 comments
-
Myobot @ 2026-2-5 16:46:02
同学你好,很高兴看到你分享自己编写的游戏代码。这是一个用控制台实现的飞行射击小游戏,整体结构清晰,包含了游戏循环、绘制、输入、更新和结束逻辑。作为竞赛教练,我会从代码质量、算法效率和可维护性的角度给你一些建议,帮助你提升编程水平。
一、代码结构分析
你的代码将游戏逻辑(
draw,update,input)与界面绘制、状态管理混合在一起。在较大项目中,这会导致维护困难。建议采用模块化设计:- 将游戏状态(玩家位置、子弹、敌机、分数等)封装为一个结构体或类。
- 将不同功能(如碰撞检测、敌机生成)拆分为独立函数。
思考题:如果让你添加“敌机类型”(有的需要击中多次),现在的代码结构容易修改吗?
二、算法效率问题
-
碰撞检测复杂度:
for (size_t i = 0; i < bx.size(); i++) // O(b) for (size_t j = 0; j < ex.size(); j++) // O(e)当前复杂度为 ,在子弹和敌机数量较多时可能成为瓶颈。虽然当前游戏规模不大,但养成优化意识很重要。
优化思路:能否用空间换时间?例如维护一个二维数组记录每个位置是否有敌机,将碰撞检测降至 。
-
容器删除操作:
bx.erase(bx.begin()+i); // 线性时间复杂度在
vector中间删除元素会导致后续元素移动,当容器较大时影响性能。考虑:- 使用“标记-清除”策略,先标记待删除元素,再统一删除。
- 或用
list存储动态变化的数据(但需注意缓存不友好)。
三、游戏逻辑细节
-
敌机生成算法:
ex.push_back(rand()%w); // 可能生成在同一列这可能导致敌机堆叠,降低游戏性。可以记录每列最近生成的敌机位置,避免过于密集。
-
时间管理:
- 使用
GetTickCount()在长时间运行后可能溢出(约49.7天),虽然对游戏影响不大,但在工程中建议使用std::chrono。 - 帧率控制
Sleep(50)在不同机器上可能不一致,考虑计算每帧耗时动态调整。
- 使用
四、代码规范与可读性
-
魔法数字:代码中多次出现
180(时间)、10(分数)等字面量。应定义为常量,如:const int TOTAL_TIME = 180; const int SCORE_PER_ENEMY = 10; -
函数职责:
update()函数同时处理子弹移动、敌机移动、碰撞检测、时间更新,过于臃肿。建议拆分为:moveBullets()moveEnemies()checkCollisions()updateTime()
-
全局变量:大量全局变量增加了耦合度。尝试将它们封装到类或结构体中。
五、扩展思考(算法角度)
如果这是一个算法题,可能会这样描述:
在一个 的网格中,玩家位于底部。每帧玩家可以左右移动或发射子弹(子弹垂直向上)。敌机从顶部随机位置生成并垂直向下移动。子弹与敌机在同一格或相邻格时发生碰撞。求 帧后的最大得分。
考点:
- 状态表示:如何用数据结构高效维护动态对象?
- 碰撞检测:如何优化到 或 ?
- 动态规划:如果子弹有冷却时间,如何规划发射时机最大化收益?
六、建议改进步骤
- 重构代码结构,将数据与逻辑分离。
- 实现更高效的碰撞检测,尝试用哈希表存储位置到敌机的映射。
- 添加测试用例,例如模拟大量敌机测试性能。
- 考虑异常情况:如输入非法字符、窗口大小变化等。
最后:你已经掌握了游戏开发的基本循环,这是很好的起点。下一步可以尝试:
- 用面向对象的方式重写代码。
- 实现更复杂的功能(如多种武器、Boss战)。
- 学习使用游戏引擎(如Unity)理解更系统的游戏架构。
如果对某个优化点有疑问,或想讨论具体实现细节,可以继续提问。记住,优秀的程序员不仅是写出能运行的代码,更要写出高效、可维护、可扩展的代码。
- 1