首页 > 编程语言 >星号游走程序(流星雨):一个多彩的控制台动画

星号游走程序(流星雨):一个多彩的控制台动画

时间:2024-12-14 14:32:23浏览次数:5  
标签:std maxX 38 int 多彩的 maxY 033 控制台 流星雨

引言

在这个项目中,我将介绍一个名为“星号游走程序”的控制台应用程序。该程序通过控制台输出渐变色的星号,并支持多种游走模式和用户交互。本文将详细介绍程序的功能、实现方式以及如何使用它。

功能概述

1. 随机游走模式

在随机游走模式下,星号会在控制台内随机移动,形成一种动态的视觉效果。每个星号的颜色会随着时间逐渐变化,形成渐变效果。

2. 从上至下游走模式

在从上至下游走模式下,星号会从屏幕顶部生成并向下移动,到达底部后重新从顶部生成。这种模式模拟了雨滴或雪花的效果。

3. 清屏功能

用户可以随时按下数字键 3 来清屏,清除所有当前的星号。

4. 添加对象

用户可以通过按下空格键来添加一个新的星号对象,增加屏幕上的动态元素。

5. 全屏显示

程序启动时会自动将控制台窗口设置为全屏模式,提供更好的视觉体验。

实现细节

1. 控制台颜色设置

我们使用 ANSI 转义码来设置控制台输出的颜色。通过一个包含多种颜色代码的 std::vector,我们可以轻松地在不同颜色之间切换。

2. 光标移动

使用 ANSI 转义码 \033[y;xH 可以将光标移动到指定的位置 (x, y),从而实现星号在屏幕上的精确定位。

3. 随机游走对象

RandomWalker 类实现了随机游走的逻辑。每个对象在更新时会随机移动一小段距离,并且颜色会逐渐变化。当对象的生存时间超过 100 帧后,它会被标记为“死亡”并从列表中移除。

4. 从上至下游走对象

TopToBottomWalker 类实现了从上至下的游走逻辑。每个对象从屏幕顶部生成,向下移动,到达底部后重新从顶部生成。同样,颜色会逐渐变化,生存时间超过 100 帧后被移除。

5. 用户输入处理

使用 _kbhit() 和 _getch() 函数来检测用户的按键输入。根据不同的按键,程序会切换模式、清屏或添加新的对象。

6. 全屏设置

通过调用 Windows API,程序在启动时将控制台窗口设置为全屏模式。具体实现包括设置缓冲区大小、窗口区域和发送最大化消息。

代码结构

1. 主函数

int main() {
    const int maxX = 210;
    const int maxY = 51;
    std::vector<RandomWalker> randomWalkers;
    std::vector<TopToBottomWalker> topToBottomWalkers;
    bool randomMode = true;

    // 显示主界面说明规则
    clearScreen();
    std::cout << "欢迎来到星号游走程序!\n";
    std::cout << "1 - 随机游走模式\n";
    std::cout << "2 - 从上至下游走模式\n";
    std::cout << "3 - 清屏\n";
    std::cout << "空格 - 添加一个对象\n";
    std::cout << "按任意键开始...\n";
    _getch();

    while (true) {
        // 检测按键
        if (_kbhit()) {
            char key = _getch();
            switch (key) {
                case '1':
                    randomMode = true;
                    break;
                case '2':
                    randomMode = false;
                    break;
                case '3':
                    clearScreen();
                    randomWalkers.clear();
                    topToBottomWalkers.clear();
                    break;
                case ' ':
                    if (randomMode) {
                        randomWalkers.emplace_back(maxX, maxY);
                    } else {
                        topToBottomWalkers.emplace_back(maxX, maxY);
                    }
                    break;
            }
        }

        // 清除已死亡的对象
        randomWalkers.erase(std::remove_if(randomWalkers.begin(), randomWalkers.end(), [](const RandomWalker& w) { return w.isDead(); }), randomWalkers.end());
        topToBottomWalkers.erase(std::remove_if(topToBottomWalkers.begin(), topToBottomWalkers.end(), [](const TopToBottomWalker& w) { return w.isDead(); }), topToBottomWalkers.end());

        // 更新和绘制所有对象
        for (auto& walker : randomWalkers) {
            walker.update();
            walker.draw();
        }
        for (auto& walker : topToBottomWalkers) {
            walker.update();
            walker.draw();
        }

        // 延迟
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    return 0;
}

2. 辅助函数

// 设置控制台颜色
void setTextColor(const std::string& color) {
    std::cout << color;
}

// 清屏
void clearScreen() {
    std::cout << "\033[2J\033[1;1H";
}

// 移动光标到指定位置
void gotoxy(int x, int y) {
    std::cout << "\033[" << y << ";" << x << "H";
}

3. 随机游走对象类

class RandomWalker {
public:
    RandomWalker(int maxX, int maxY) : maxX(maxX), maxY(maxY), x(rand() % maxX), y(rand() % maxY), age(0) {
        colorIt = colors.begin();
    }

    void update() {
        // 随机移动
        x += (rand() % 3) - 1;
        y += (rand() % 3) - 1;

        // 限制在屏幕范围内
        x = std::max(0, std::min(x, maxX - 1));
        y = std::max(0, std::min(y, maxY - 1));

        // 增加年龄
        age++;
    }

    void draw() {
        gotoxy(x, y);
        setTextColor(*colorIt);
        std::cout << "*\033[0m";

        // 更新颜色
        if (++colorIt == colors.end()) {
            colorIt = colors.begin();
        }
    }

    bool isDead() const {
        return age > 100; // 生存时间超过100帧后消失
    }

private:
    int maxX, maxY;
    int x, y;
    int age;
    std::vector<std::string>::const_iterator colorIt;
};

4. 从上至下游走对象类

class TopToBottomWalker {
public:
    TopToBottomWalker(int maxX, int maxY) : maxX(maxX), maxY(maxY), x(rand() % maxX), y(0), age(0) {
        colorIt = colors.begin();
    }

    void update() {
        // 向下移动
        y++;

        // 限制在屏幕范围内
        if (y >= maxY) {
            y = 0;
            x = rand() % maxX;
        }

        // 增加年龄
        age++;
    }

    void draw() {
        gotoxy(x, y);
        setTextColor(*colorIt);
        std::cout << "*\033[0m";

        // 更新颜色
        if (++colorIt == colors.end()) {
            colorIt = colors.begin();
        }
    }

    bool isDead() const {
        return age > 100; // 生存时间超过100帧后消失
    }

private:
    int maxX, maxY;
    int x, y;
    int age;
    std::vector<std::string>::const_iterator colorIt;
};

使用方法

  1. 编译和运行

    • 使用支持 C++11 的编译器编译程序。
    • 在命令行中运行生成的可执行文件。
  2. 操作指南

    • 按 1 切换到随机游走模式。
    • 按 2 切换到从上至下游走模式。
    • 按 3 清屏。
    • 按空格键添加一个新的星号对象。

源码

#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <random>
#include <conio.h> // 用于检测按键

// ANSI颜色代码
const std::vector<std::string> colors = {
    "\033[38;5;0m",  "\033[38;5;1m",  "\033[38;5;2m",  "\033[38;5;3m",  "\033[38;5;4m",  "\033[38;5;5m",  "\033[38;5;6m",  "\033[38;5;7m",
    "\033[38;5;8m",  "\033[38;5;9m",  "\033[38;5;10m", "\033[38;5;11m", "\033[38;5;12m", "\033[38;5;13m", "\033[38;5;14m", "\033[38;5;15m",
    "\033[38;5;16m", "\033[38;5;17m", "\033[38;5;18m", "\033[38;5;19m", "\033[38;5;20m", "\033[38;5;21m", "\033[38;5;22m", "\033[38;5;23m",
    "\033[38;5;24m", "\033[38;5;25m", "\033[38;5;26m", "\033[38;5;27m", "\033[38;5;28m", "\033[38;5;29m", "\033[38;5;30m", "\033[38;5;31m",
    "\033[38;5;32m", "\033[38;5;33m", "\033[38;5;34m", "\033[38;5;35m", "\033[38;5;36m", "\033[38;5;37m", "\033[38;5;38m", "\033[38;5;39m",
    "\033[38;5;40m", "\033[38;5;41m", "\033[38;5;42m", "\033[38;5;43m", "\033[38;5;44m", "\033[38;5;45m", "\033[38;5;46m", "\033[38;5;47m",
    "\033[38;5;48m", "\033[38;5;49m", "\033[38;5;50m", "\033[38;5;51m", "\033[38;5;52m", "\033[38;5;53m", "\033[38;5;54m", "\033[38;5;55m",
    "\033[38;5;56m", "\033[38;5;57m", "\033[38;5;58m", "\033[38;5;59m", "\033[38;5;60m", "\033[38;5;61m", "\033[38;5;62m", "\033[38;5;63m",
    "\033[38;5;64m", "\033[38;5;65m", "\033[38;5;66m", "\033[38;5;67m", "\033[38;5;68m", "\033[38;5;69m", "\033[38;5;70m", "\033[38;5;71m",
    "\033[38;5;72m", "\033[38;5;73m", "\033[38;5;74m", "\033[38;5;75m", "\033[38;5;76m", "\033[38;5;77m", "\033[38;5;78m", "\033[38;5;79m",
    "\033[38;5;80m", "\033[38;5;81m", "\033[38;5;82m", "\033[38;5;83m", "\033[38;5;84m", "\033[38;5;85m", "\033[38;5;86m", "\033[38;5;87m",
    "\033[38;5;88m", "\033[38;5;89m", "\033[38;5;90m", "\033[38;5;91m", "\033[38;5;92m", "\033[38;5;93m", "\033[38;5;94m", "\033[38;5;95m",
    "\033[38;5;96m", "\033[38;5;97m", "\033[38;5;98m", "\033[38;5;99m", "\033[38;5;100m", "\033[38;5;101m", "\033[38;5;102m", "\033[38;5;103m",
    "\033[38;5;104m", "\033[38;5;105m", "\033[38;5;106m", "\033[38;5;107m", "\033[38;5;108m", "\033[38;5;109m", "\033[38;5;110m", "\033[38;5;111m",
    "\033[38;5;112m", "\033[38;5;113m", "\033[38;5;114m", "\033[38;5;115m", "\033[38;5;116m", "\033[38;5;117m", "\033[38;5;118m", "\033[38;5;119m",
    "\033[38;5;120m", "\033[38;5;121m", "\033[38;5;122m", "\033[38;5;123m", "\033[38;5;124m", "\033[38;5;125m", "\033[38;5;126m", "\033[38;5;127m",
    "\033[38;5;128m", "\033[38;5;129m", "\033[38;5;130m", "\033[38;5;131m", "\033[38;5;132m", "\033[38;5;133m", "\033[38;5;134m", "\033[38;5;135m",
    "\033[38;5;136m", "\033[38;5;137m", "\033[38;5;138m", "\033[38;5;139m", "\033[38;5;140m", "\033[38;5;141m", "\033[38;5;142m", "\033[38;5;143m",
    "\033[38;5;144m", "\033[38;5;145m", "\033[38;5;146m", "\033[38;5;147m", "\033[38;5;148m", "\033[38;5;149m", "\033[38;5;150m", "\033[38;5;151m",
    "\033[38;5;152m", "\033[38;5;153m", "\033[38;5;154m", "\033[38;5;155m", "\033[38;5;156m", "\033[38;5;157m", "\033[38;5;158m", "\033[38;5;159m",
    "\033[38;5;160m", "\033[38;5;161m", "\033[38;5;162m", "\033[38;5;163m", "\033[38;5;164m", "\033[38;5;165m", "\033[38;5;166m", "\033[38;5;167m",
    "\033[38;5;168m", "\033[38;5;169m", "\033[38;5;170m", "\033[38;5;171m", "\033[38;5;172m", "\033[38;5;173m", "\033[38;5;174m", "\033[38;5;175m",
    "\033[38;5;176m", "\033[38;5;177m", "\033[38;5;178m", "\033[38;5;179m", "\033[38;5;180m", "\033[38;5;181m", "\033[38;5;182m", "\033[38;5;183m",
    "\033[38;5;184m", "\033[38;5;185m", "\033[38;5;186m", "\033[38;5;187m", "\033[38;5;188m", "\033[38;5;189m", "\033[38;5;190m", "\033[38;5;191m",
    "\033[38;5;192m", "\033[38;5;193m", "\033[38;5;194m", "\033[38;5;195m", "\033[38;5;196m", "\033[38;5;197m", "\033[38;5;198m", "\033[38;5;199m",
    "\033[38;5;200m", "\033[38;5;201m", "\033[38;5;202m", "\033[38;5;203m", "\033[38;5;204m", "\033[38;5;205m", "\033[38;5;206m", "\033[38;5;207m",
    "\033[38;5;208m", "\033[38;5;209m", "\033[38;5;210m", "\033[38;5;211m", "\033[38;5;212m", "\033[38;5;213m", "\033[38;5;214m", "\033[38;5;215m",
    "\033[38;5;216m", "\033[38;5;217m", "\033[38;5;218m", "\033[38;5;219m", "\033[38;5;220m", "\033[38;5;221m", "\033[38;5;222m", "\033[38;5;223m",
    "\033[38;5;224m", "\033[38;5;225m", "\033[38;5;226m", "\033[38;5;227m", "\033[38;5;228m", "\033[38;5;229m", "\033[38;5;230m", "\033[38;5;231m",
    "\033[38;5;232m", "\033[38;5;233m", "\033[38;5;234m", "\033[38;5;235m", "\033[38;5;236m", "\033[38;5;237m", "\033[38;5;238m", "\033[38;5;239m",
    "\033[38;5;240m", "\033[38;5;241m", "\033[38;5;242m", "\033[38;5;243m", "\033[38;5;244m", "\033[38;5;245m", "\033[38;5;246m", "\033[38;5;247m",
    "\033[38;5;248m", "\033[38;5;249m", "\033[38;5;250m", "\033[38;5;251m", "\033[38;5;252m", "\033[38;5;253m", "\033[38;5;254m", "\033[38;5;255m"

};

// 设置控制台颜色
void setTextColor(const std::string& color) {
    std::cout << color;
}

// 清屏
void clearScreen() {
    std::cout << "\033[2J\033[1;1H";
}

// 移动光标到指定位置
void gotoxy(int x, int y) {
    std::cout << "\033[" << y << ";" << x << "H";
}

// 随机游走对象
class RandomWalker {
public:
    RandomWalker(int maxX, int maxY) : maxX(maxX), maxY(maxY), x(rand() % maxX), y(rand() % maxY), age(0) {
        colorIt = colors.begin();
    }

    void update() {
        // 随机移动
        x += (rand() % 3) - 1;
        y += (rand() % 3) - 1;

        // 限制在屏幕范围内
        x = std::max(0, std::min(x, maxX - 1));
        y = std::max(0, std::min(y, maxY - 1));

        // 增加年龄
        age++;
    }

    void draw() {
        gotoxy(x, y);
        setTextColor(*colorIt);
        std::cout << "*\033[0m";

        // 更新颜色
        if (++colorIt == colors.end()) {
            colorIt = colors.begin();
        }
    }

    bool isDead() const {
        return age > 100; // 生存时间超过100帧后消失
    }

private:
    int maxX, maxY;
    int x, y;
    int age;
    std::vector<std::string>::const_iterator colorIt;
};

// 从上至下游走对象
class TopToBottomWalker {
public:
    TopToBottomWalker(int maxX, int maxY) : maxX(maxX), maxY(maxY), x(rand() % maxX), y(0), age(0) {
        colorIt = colors.begin();
    }

    void update() {
        // 向下移动
        y++;

        // 限制在屏幕范围内
        if (y >= maxY) {
            y = 0;
            x = rand() % maxX;
        }

        // 增加年龄
        age++;
    }

    void draw() {
        gotoxy(x, y);
        setTextColor(*colorIt);
        std::cout << "*\033[0m";

        // 更新颜色
        if (++colorIt == colors.end()) {
            colorIt = colors.begin();
        }
    }

    bool isDead() const {
        return age > 100; // 生存时间超过100帧后消失
    }

private:
    int maxX, maxY;
    int x, y;
    int age;
    std::vector<std::string>::const_iterator colorIt;
};

int main() {
    const int maxX = 210;
    const int maxY = 51;
    std::vector<RandomWalker> randomWalkers;
    std::vector<TopToBottomWalker> topToBottomWalkers;
    bool randomMode = true;

    // 显示主界面说明规则
    clearScreen();
    std::cout << "欢迎来到星号游走程序!\n";
    std::cout << "1 - 随机游走模式\n";
    std::cout << "2 - 从上至下游走模式\n";
    std::cout << "3 - 清屏\n";
    std::cout << "空格 - 添加一个对象\n";
    std::cout << "按任意键开始...\n";
    _getch();

    while (true) {
        // 检测按键
        if (_kbhit()) {
            char key = _getch();
            switch (key) {
                case '1':
                    randomMode = true;
                    break;
                case '2':
                    randomMode = false;
                    break;
                case '3':
                    clearScreen();
                    randomWalkers.clear();
                    topToBottomWalkers.clear();
                    break;
                case ' ':
                    if (randomMode) {
                        randomWalkers.emplace_back(maxX, maxY);
                    } else {
                        topToBottomWalkers.emplace_back(maxX, maxY);
                    }
                    break;
            }
        }

        // 清除已死亡的对象
        randomWalkers.erase(std::remove_if(randomWalkers.begin(), randomWalkers.end(), [](const RandomWalker& w) { return w.isDead(); }), randomWalkers.end());
        topToBottomWalkers.erase(std::remove_if(topToBottomWalkers.begin(), topToBottomWalkers.end(), [](const TopToBottomWalker& w) { return w.isDead(); }), topToBottomWalkers.end());

        // 更新和绘制所有对象
        for (auto& walker : randomWalkers) {
            walker.update();
            walker.draw();
        }
        for (auto& walker : topToBottomWalkers) {
            walker.update();
            walker.draw();
        }

        // 延迟
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    return 0;
}

结论

通过这个项目,我们不仅实现了一个有趣的控制台动画程序,还学习了如何使用 ANSI 转义码、Windows API 以及 C++ 中的一些高级特性。希望这个项目能够激发你对控制台编程的兴趣,并为你提供一些实用的技术参考。

如果你有任何问题或建议,欢迎在评论区留言!

标签:std,maxX,38,int,多彩的,maxY,033,控制台,流星雨
From: https://blog.csdn.net/2301_81482480/article/details/144470482

相关文章

  • 【C++】控制台清空/清除部分字符
    目录清空整个屏幕:清空特定的某一行:(附录)一些常用的ANSI转义码清空整个屏幕:(头文件<cstdlib>)system(“cls”);*该方法容易造成闪屏等问题,可以尝试用WIN-API函数解决(?)      /待研究清空特定的某一行:若是清空方才输出的那一行     使用 \r  将......
  • [C++]常用的windows控制台操作
    目录一、光标1.隐藏光标2.移动光标二、窗口大小1.调整大小2、固定大小三、颜色1.cmd命令2.直接printf颜色四、控制台1.标题一些常用的控制台操作!注意:该文章全程需要:Windows.h头文件,因为使用了Windows的API一、光标1.隐藏光标voidHideCursor(){ CONSOLE_CURSOR_I......
  • python logger 控制台,滚动文件
    defsetup_logger(logger_name,level=logging.INFO):logging.basicConfig(format='%(asctime)s-%(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s',level=logging.DEBUG,filename='./l......
  • 爱心-控制台程序-极语言教程
    常量蓝色=9,绿色=10,青色=11,红色=12,紫色=13,黄色=14小程序初始启动整数输出=取控制台(标准输出)设置标题("文字颜色和位置")改光标位(输出,0x10010)改字属性(输出,青色)写控制台(输出,".........",9)改光标位(输出,0x10024)写控制台(输出,".........",9)改光标位......
  • 画图-控制台程序-极语言教程
    引入"lib\user32.lib","lib\gdi32.lib";整数窗体,设备,图像,图层,画刷,白笔,红笔,绿笔,蓝笔,弧=10;小数圆=3.14159265;小程序初始启动窗体=命令窗口移动窗口(窗体,0,0,850,800,假)图层=取设备(窗体)设备=创建设备(图层)图像=创建图像(图层,850,800)选择对象(设备,图......
  • 0015 判断输入的数是不是素数-控制台程序-极语言教程
    小程序初始启动写格式("请输入大于1并且小于等于2147483647的正整数进行素数判断:\r\n")循环{整数输入数,计数,判断数=1,开始时间=0,结束时间=0,需要时间=0读格式("%d",&输入数)开始时间=开机毫秒循环于(计数=2;计数<输入数;计数++){......
  • C++象棋代码 (控制台版)
    C++象棋代码 在win7写的 如果有疑问可以在评论区问有bug也可以在评论区反馈我会不定期修复的下面上代码:#include <windows.h>#include <string>#include <iostream>#include <cmath>using namespace std;int main(){    void Chinese_chees_Int_H......
  • window.onload没有效果,控制台也没有报错
    本来想用这个来展示用户信息,但加了这个没有任何效果,控制台也没有报错,其它也检查了感觉没有错误在网络那边发送的请求发现根本没有发送请求我的请求路径是这样的:这里就用绑定事件去完成:这一次就查出来了,发送了这个select请求。......
  • 信创改造 - TongRDS 安装方式之控制台安装【Window】
    安装前准备安装jdk1.8即可,并配上环境变量安装1)解压缩2)启动进入安装路径的console\bin目录,在cmd命令行窗口运行console.bat输入序号1如果想查看运行状态,可以重新执行console.bat,然后输入序号33)打开登录控制台默认8083端口,http://ip:8083访问,例如:h......
  • PTA 作业一 两分钟学会JAVA语言 7-3 Java程序设计-基本程序-摄氏温度转换为华氏温度
    7-3Java程序设计-基本程序-摄氏温度转换为华氏温度分数10全屏浏览切换布局作者 万静单位 北京化工大学这是一个编程题模板。编写程序,从控制台读入double型的摄氏温度值,然后转换为华氏温度,并且显示结果。转换公式如下:华氏温度=(9/5)*摄氏温度+32。输入格式:输入摄......