ANSI Escape Sequence 下落的方块

news2025/3/15 10:55:40

ANSI Escape Sequence 下落的方块

1. ANSI Escape 的用途

无意中发现 B站有人讲解, 完全基于终端实现俄罗斯方块。 基本想法是借助于 ANSI Escape Sequence 实现方方块的绘制、 下落动态效果等。对于只了解 ansi escape sequence 用于 log 的颜色打印的人来说, 这无疑是拓宽了认识。

在这里插入图片描述

这一篇简单的列一下 ansi escape sequence 中的稀奇古怪的数字的含义, 并最终给出一个绿色方块下落的动态效果和对应的代码。 基于本篇给出的表格和代码, 可以把它拓展为自由落体的游戏效果, 也可以跟着 B 站视频更容易的写出终端里的俄罗斯方块。

同时也注意到, ansi escape sequence 有它的局限性, 无法绘制比较大的圆形, 使用 ansi escape sequence 会限制界面显示、 游戏开发的上限。

2. ANSI Escape Sequence 有什么用?

终端会把 ANSI Escape 序列的字符解释为命令,而不是原本的内容。这些命令在终端上控制如下内容:

  • 鼠标位置
  • 颜色
  • 字体样式
  • 其他选项

使用 ANSI Escape Sequence 做 log 打印的例子比较多, 但其实还可以那它用作绘图显示: 把终端当成是 256 色的图像, 在终端显示图像内容。

3. 形式

3.1 格式概况

  • 绝大多数有用的序列: ESC[ 开头
  • 序列的重置: ESC[0m, 意思是各种设置的属性都撤销掉,恢复为没有设置时的状态

一些“黑话”:

  • CSI (Control Sequence Introducer): ESC[ 的别名, ASCII escape 数值是27, 实际使用时 ESC 换成 \x1b(16进制), \033(8进制) 或 \e
  • SGR (Select Graphic Rendition): CSI n m 的别名,用于设定字符的颜色和风格。其中:
    • CSI 要换成 \x1b[, \033[\e[
    • n 要换成具体的数字,在 0~107 之间

根据 wikipedia 得到的解释:

  • 起始: ESC[ (这个组合又叫做 CSI, Control Sequence Introducer)
  • parameter bytes: 任意数量的 0x30-0x3F 范围的字符, 也就是 0-9:;<=>?
  • intermediate bytes: 任意数量的 0x20-0x2F 范围的字符,也就是 !"#$%&'()*+,-./
  • final bytes: 任意数量的 0x40-0x7E 范围的字符,也就是 “@A–Z[]^_`a–z{|}~”
  • private bytes: 包含 <=>? 或 0x70-0x7E 范围(p-z{|}~) 的字符, 各厂商自行定义和使用的
  • 设定多个属性: ; 分隔的单个属性
  • 重置: ESC[0m

而网上其他资料, 以及实际验证, 发现维基百科有遗漏内容, ESC[ (CSI) 之后可以紧跟着 0~0x2F 范围的数字, 例如 n=1 对应到 “字体加粗” 的属性。

3.2 格式的具体情况

n名字含义、作用
0Reset or normal重置所有属性
1Bold or increased intensity字体加粗
2Faint, decresed intensity, or dim字体变暗
3Italic斜体。据说没有被广泛使用
4Underline下划线. 算是扩展, 在 Kitty, VTE, mintty, iTERM2, Konsole 里有效
5Slow blink设定光标闪烁时间在每分钟内小于150次(暂时不会用)
6Rapid blink光标闪烁加速,每分钟内超过150次; 没有被广泛支持
7Reverse video or invert对调背景和前景的颜色
8Conceal or hide没有被广泛的支持,iTerm2 上没有效果
9Crossed-out, or strike让字符带有删除线
10Primary(default) font默认字体
11~19Alternative font选择编号为 n-10 的字体
20Fraktur(Gothic)很少使用。iTerm2 上没有效果
21Doubly underlined; or: not bold双下划线、或者不要加粗
22Normal intensity既不加粗、也不变暗
23Neither italic, nor blackletter既不斜体, 也不黑色字母
24Not underlined不要有单个下划线, 也不要有双下划线
25Not blinking不要闪烁光标
26Proportional spacing终端上没有在使用
27Not reservediTerm2 上没有效果
28Reveal不要"隐瞒"
29Not crossed out去掉“删除线"
30-37Set foreground color设置前景颜色
30Black 黑色前景
31Red 红色前景
32Green 绿色前景
33Yellow 黄色前景
34Blue 蓝色前景
35Magenta 紫色前景
36Cyan 靛蓝色前景
37White 白色前景
38Set foreground color设置前景颜色, 接下来的参数是 5;n2;r;g;b
39Default foreground color默认前景颜色
40-47设置背景颜色
40Black 黑色背景
41Red 红色背景
42Green 绿色背景
43Yellow 黄色背景
44Blue 蓝色背景
45Magenta 紫色背景
46Cyan 靛蓝色背景
47White 白色背景
48Set background color设置前景颜色, 接下来的参数是 5;n2;r;g;b
49默认背景颜色
50Disable proportional spacing禁用等比例空格
51Framedmintty 中被实现为 emoji 选择器(?)
52Encircled同上
53Overlinked没效果
54Neither framed nor encircled
55Not overlined
58Set underline color设置下划线颜色。不是标准规定的。Kitty, VTE, iTerm2里有实现;下一个参数需要是 5;n2;r;g;b 形式
59Default underline color默认下划线颜色. 非标准。在 Kitty, VTE, iTerm2里有实现
60~65通常没有实现
73-74Superscript, Subscript上标和下标。只在 mintty 里有实现
75-76Neither superscript nor subscript取消上标和下标
90-97Set bright foreground color设置前景颜色亮度。非标准. iTerm2里有效
90Bright Black亮黑色前景色
91Bright Red亮红色前景色
92Bright Green亮绿色前景色
93Bright Yellow亮黄色前景色
94Bright Blue亮蓝色前景色
95Bright Magenta亮紫色前景色
96Bright Cyan亮靛蓝色前景色
97Bright White亮白色前景色
100-107Set bright background color背景颜色亮度. iTerm2里有效
100Bright Black亮黑色背景色
101Bright Red亮红色背景色
102Bright Green亮绿色背景色
103Bright Yellow亮黄色背景色
104Bright Blue亮蓝色背景色
105Bright Magenta亮紫色背景色
106Bright Cyan亮靛蓝色背景色
107Bright White亮白色背景色

其中 n 为 38 是设置前景颜色 ESC[38;5;{ID}m, n 为 48 是设置背景颜色 ESC[48;5;{ID}m, ID 是具体的颜色, 见下图:

在这里插入图片描述

3.3 常见私有模式 (Common Private Modes)

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797

ESC 代码序列描述
ESC[?25l]隐藏光标
ESC[?25h]显示光标
ESC[?47l]恢复屏幕
ESC[?47h]保存屏幕
ESC[?1049h]启用可选buffer
ESC[?1049l]禁用可选bufer

3.4 控制光标

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#cursor-controls

ESC 代码序列描述
ESC[H光标移动到 (0, 0) 位置
ESC[#A光标向上移动 #
ESC[#B光标向下移动 #

3.5 擦除功能 (Erase Functions)

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#erase-functions

ESC CodeDescription
ESC[J清除光标位置到屏幕结束位置
ESC[0JESC[J
ESC[1J清除光标位置到屏幕开始
ESC[2J清除整个屏幕
ESC[3J清除保存的行
ESC[K清除当前光标位置到当前行末尾
ESC[0KESC[K
ESC[1K删除当前光标位置到当前行首
ESC[2K删除整行

4. 简单例子

在这里插入图片描述

#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <numeric>

int main()
{
    std::vector<int> codes = {
        1, 2, 3, 4, 7, 8, 9
    };
    std::generate_n(std::back_inserter(codes), 8, [n = 30]() mutable { return n++; });
    std::generate_n(std::back_inserter(codes), 8, [n = 40]() mutable { return n++; });
    std::generate_n(std::back_inserter(codes), 8, [n = 90]() mutable { return n++; });
    std::generate_n(std::back_inserter(codes), 8, [n = 100]() mutable { return n++; });

    for (const auto code : codes)
    {
        printf("\e[%dmHello\e[mworld  (n=%d)\n", code, code);
    }

    printf("\e[1;34mHello\e[0mworld  (n=1;34)\n");

    printf("\e[38;5;2mHello\e[0mworld  (n=38;5;2)\n");
    printf("\e[48;5;2mHello\e[0mworld  (n=48;5;2)\n");

    return 0;
}

5. 复杂例子 - 方块下落

绘制最小的绿色矩形: 打印“空格” 字符, 并且让空格字符的前景颜色红色的:

printf("\e[42m \e[0m\n"); 

绘制较大的红色矩形: 每一行打印多个空格, 连续打印多行; 每一行打印时使用转义字符。

printf("\e[42m    \e[0m\n"); 

绘制会下落的红色矩形框: 先绘制一个,长度持续增加的。

void draw_box()
{
    for (int i = 0; i < 10; i++)
    {
        printf("\e[42m    \e[0m\n");
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

通过 ANSI Escape Sequence, 修改光标位置, 然后再绘制矩形:

void draw_box2()
{
    printf("\e[H");     // 光标移动到 (0,0) 位置
    printf("\e[42m    \e[0m"); // 绘制绿色背景的空格
    printf("\e[1B");  // 光标往下一行。 注意此时 column 方向上, 光标不是在0位置
    printf("\e[43m    \e[0m"); // 绘制黄色背景的空格
}

让每一行的绘制, 都从第 6 列开始绘制, 并且每次绘制后, 等待 100 毫秒:

void draw_box6()
{
    printf("\e[?25l"); // 隐藏光标, 避免光标导致的白色小方框
    for (int i = 0; i < 10; i++)
    {
        printf("\e[2J");    // 清空整个屏幕
        printf("\x1b[%d;%dH\e[0m", i, 6); // 光标一定到第i 行,第 6 列
        printf("\e[42m    \e[0m"); // 绘制绿色矩形: 也就是绘制绿色背景的空格
        fflush(stdout); // 确保绘制到控制台
        std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 暂停 500 毫秒,营造下落的视觉效果
    }
    printf("\e[?25h"); // 恢复光标的可见性
}

在这里插入图片描述

6. ANSI Escape 的局限

无法绘制圆形。 因为终端绘制的最小单位, 是单个字符,每个字符通常是竖条而不是正方形, 并且竖条比较大, 大于通常看到的图像像素。 这就导致, 稍微复杂的图形无法绘制, 需要选择其他的方案:

  • 使用 opencv 的 Mat 绘制, 用 imshow 显示
  • 使用 SFML / SDL / Dear imgui / Qt 绘制和显示

7. References

  • 手把手教你写俄罗斯方块:2-如何在终端上绘图
  • ANSI Escape Codes
  • C语言实现 log 库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1441862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第10章 项目进度管理(四)

博主2023年11月通过了信息系统项目管理的考试&#xff0c;考试过程中发现考试的内容全部是教材中的内容&#xff0c;非常符合我学习的思路&#xff0c;因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家&#xff0c;希望更多的人能够通过考试&a…

【Java EE】----SpringBoot的日志文件

1.SpringBoot使用日志 先得到日志对象通过日志对象提供的方法进行打印 2.打印日志的信息 3.日志级别 作用&#xff1a; 可以筛选出重要的信息不同环境实现不同日志级别的需求 ⽇志的级别分为&#xff1a;&#xff08;1-6级别从低到高&#xff09; trace&#xff1a;微量&#…

高级数据结构与算法 | 布谷鸟过滤器(Cuckoo Filter):原理、实现、LSM Tree 优化

文章目录 Cuckoo Filter基本介绍布隆过滤器局限变体 布谷鸟哈希布谷鸟过滤器 实现数据结构优化项Victim Cache备用位置计算半排序桶 插入查找删除 应用场景&#xff1a;LSM 优化 Cuckoo Filter 基本介绍 如果对布隆过滤器不太了解&#xff0c;可以看看往期博客&#xff1a;海量…

CentOS 7安装Nodejs

说明&#xff1a;本文介绍如何在云服务器上CentOS 7操作系统上安装Nodejs。以及安装过程中遇到的问题。 下载压缩包&解压 首先&#xff0c;先去官网下载Linux版本的Node。 将下载下来的压缩包&#xff0c;上传到云服务器上&#xff0c;解压。配置环境变量。 &#xff08…

VScode为什么选择了Electron,而不是QT?

选择Electron而不是QT可能是基于以下几个原因&#xff1a; Web技术的普及和开发者生态系统&#xff1a;Web技术如HTML、CSS和JavaScript在开发者中非常普及&#xff0c;开发者生态系统庞大且活跃。使用Electron可以利用这些熟悉的Web技术和丰富的开发者社区资源。跨平台支持&am…

蓝桥杯(Web大学组)2022国赛真题:水果消消乐

思路&#xff1a; 记录点击次数&#xff0c;点击次数为1时&#xff0c;记录点击下标&#xff08;用于隐藏or消除&#xff09;、点击种类&#xff0c;点击次数为2时&#xff0c;判断该下标所对应种类与第一次是否相同 相同&#xff1a;两个都visibility:hidden &#xff08;占…

黄金交易策略(EA):三个仓位的设计是确保可以不停息做单

完整EA&#xff1a;Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客

MacOS 查AirPods 电量技巧:可实现低电量提醒、自动弹窗

要怎么透过macOS 来查询AirPods 电量呢&#xff1f;当AirPods 和Mac 配对后&#xff0c;有的朋友想通过Mac来查询AirPods有多少电量&#xff0c;这个里有几个技巧&#xff0c;下面我们来介绍一下。 透过Mac 查AirPods 电量技巧 技巧1. 利用状态列上音量功能查询 如要使用此功能…

在django中集成markdown文本框

首先需要下载开源组件&#xff1a;http://editor.md.ipandao.com/&#xff0c;可能需要挂梯子。 百度网盘&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1D9o3P8EQDqSqfhAw10kYkw 提取码&#xff1a;eric 1.在html代码中生成一个div&#xff0c;ideditor <div c…

【玩转408数据结构】线性表——定义和基本操作

考点剖析 线性表是算法题命题的重点&#xff0c;该类题目实现相对容易且代码量不高&#xff0c;但需要最优的性能&#xff08;也就是其时间复杂度以及空间复杂度最优&#xff09;&#xff0c;这样才可以获得满分。所以在考研复习中&#xff0c;我们需要掌握线性表的基本操作&am…

Peter算法小课堂—枚举优化

哈哈哈&#xff0c;新年快乐&#xff01;这一次Peter将要给大家讲一讲轻松、摆烂的算法—枚举&#xff01;咋就是说呀&#xff0c;枚举这个玩意我语法就会了。但大家想想&#xff0c;咱们CSP考试时&#xff08;除了没过初赛的&#xff09;只给1秒&#xff0c;大家想想&#xff…

跟着cherno手搓游戏引擎【23】项目维护、2D引擎之前的一些准备

项目维护&#xff1a; 修改文件结构&#xff1a; 头文件自己改改就好了 创建2DRendererLayer&#xff1a; Sandbox2D.h: #pragma once #include "YOTO.h" class Sandbox2D :public YOTO::Layer {public:Sandbox2D();virtual ~Sandbox2D() default;virtual void O…

【lesson46】进程通信之system V(共享内存)

文章目录 共享内存通信原理用共享内存通信shmServer.ccshmClient.cc 完整通信代码common.hppLog.hppshmServer.ccshmClient.cc通信测试 共享内存借助管道添加访问控制common.hppshmServer.ccshmClient.cc 共享内存通信原理 两个进程将一块system V的物理地址通过页表映射到自己…

JSP编程

JSP编程 您需要理解在JSP API的类和接口中定义的用于创建JSP应用程序的各种方法的用法。此外,还要了解各种JSP组件,如在前一部分中学习的JSP动作、JSP指令及JSP脚本。JSP API中定义的类提供了可借助隐式对象通过JSP页面访问的方法。 1. JSP API的类 JSP API是一个可用于创建…

大模型学习 一

https://www.bilibili.com/video/BV1Kz4y1x7AK/?spm_id_from333.337.search-card.all.click GPU 计算单元多 并行计算能力强 指数更重要 A100 80G V100 A100 海外 100元/时 单卡 多卡并行&#xff1a; 单机多卡 模型并行 有资源的浪费 反向传播 反向传播&#xff08;B…

第6章 智能租房——前期准备

学习目标 了解智能租房项目&#xff0c;能够说出项目中各模块包含的功能 熟悉智能租房项目的开发模式与运行机制&#xff0c;能够复述项目的开发模式与运行机制 掌握智能租房项目的创建&#xff0c;能够独立创建智能租房项目 掌握智能租房项目的配置&#xff0c;能够为智能租…

教师考试,搜题软件哪个好用?大学生必备工具:搜题软件推荐 #微信#学习方法

在大学生的学习过程中&#xff0c;我们经常会遇到各种难题和疑惑。有时候&#xff0c;我们可能会花费大量的时间和精力去寻找答案&#xff0c;但结果却并不尽如人意。为了帮助大家更好地解决这个问题&#xff0c;今天我要向大家介绍几款备受大学生欢迎的搜题软件&#xff0c;它…

【NICN】探索牛客之求阶乘

1.题目描述 递归和非递归分别实现求n的阶乘&#xff08;不考虑溢出的问题&#xff09; 2.代码解题 2.1递归 递归思想&#xff1a; Fac(N) 1*2*3*……*N递归方式实现&#xff1a;1 N < 1 Fac(N)Fac(N-1)*N N > 2 long long Fac(int N) {if(N < 1)return 1;retu…

欢度春节,祝福万家。

值此春节佳节来临之际,新年问候如一道灯光&#xff0c;照亮我们前行的路。在这光芒中&#xff0c;期待与你携手走过新的一年。 春节是中华民族最重要的传统节日,它代表着新的开始和希望。在这个特殊的时刻,让我们放下过去的烦恼和忧虑,迎接新的挑战和机遇。让我们珍惜和家人团…

使用 Elasticsearch 和 OpenAI 构建生成式 AI 应用程序

本笔记本演示了如何&#xff1a; 将 OpenAI Wikipedia 向量数据集索引到 Elasticsearch 中使用 Streamlit 构建一个简单的 Gen AI 应用程序&#xff0c;该应用程序使用 Elasticsearch 检索上下文并使用 OpenAI 制定答案 安装 安装 Elasticsearch 及 Kibana 如果你还没有安装好…