如何用 C++ 模拟一个点阵显示器
·
之前在外面看到的一个大一学生学习 C 语言,学到二维数组和多维数组那块的一个课后作业。
要求是利用控制台的等宽字体模拟一个 5×75\times 75×7 的点阵字体(其实就是单片机用的那种液晶屏)并按照这种方式输出系统时间。

(图片来源网络,侵删)
Solution
纯模拟,算法层面完全没什么难的,但是调试非常考验耐心 👇
- 如何对齐字符,如何保证输出不错乱都需要仔细调整;
- 控制台窗口宽度不够,同样会导致输出混乱;
- 打表 - 最枯燥的过程,没有之一。
参考实现
#if _MSVC_LANG
#pragma warning(disable:4996)
#endif
#include<windows.h>
#include<time.h>
#include<stdio.h>
#if !__cplusplus
#define constexpr const
#define bool int
#endif
// 枚举10个数码
constexpr bool num[10][7][5] = {
{ {0,1,1,1,0},{1,0,0,0,1},{1,0,0,1,1},{1,0,1,0,1},{1,1,0,0,1},{1,0,0,0,1},{0,1,1,1,0} },
{ {0,0,1,0,0},{0,1,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,1,1,1,0} },
{ {0,1,1,1,0},{1,0,0,0,1},{0,0,0,0,1},{0,0,0,1,0},{0,0,1,0,0},{0,1,0,0,0},{1,1,1,1,1} },
{ {0,1,1,1,0},{1,0,0,0,1},{0,0,0,0,1},{0,0,1,1,0},{0,0,0,0,1},{1,0,0,0,1},{0,1,1,1,0} },
{ {0,0,0,1,0},{0,0,1,1,0},{0,1,0,1,0},{1,0,0,1,0},{1,1,1,1,1},{0,0,0,1,0},{0,0,0,1,0} },
{ {1,1,1,1,1},{1,0,0,0,0},{1,1,1,1,0},{0,0,0,0,1},{0,0,0,0,1},{1,0,0,0,1},{0,1,1,1,0} },
{ {0,0,1,1,0},{0,1,0,0,0},{1,0,0,0,0},{1,1,1,1,0},{1,0,0,0,1},{1,0,0,0,1},{0,1,1,1,0} },
{ {1,1,1,1,1},{0,0,0,0,1},{0,0,0,1,0},{0,0,1,0,0},{0,1,0,0,0},{0,1,0,0,0},{0,1,0,0,0} },
{ {0,1,1,1,0},{1,0,0,0,1},{1,0,0,0,1},{0,1,1,1,0},{1,0,0,0,1},{1,0,0,0,1},{0,1,1,1,0} },
{ {0,1,1,1,0},{1,0,0,0,1},{1,0,0,0,1},{0,1,1,1,1},{0,0,0,0,1},{0,0,0,1,0},{0,1,1,0,0} } };
// 用bool数组表示六个时间数码以及两个冒号, 每两个字符之间有一个像素宽度的间隔, 因此6个数字加上两个冒号共8个字符有7个间隔, 需要一个7行47列的数组
bool time_display[7][48];
bool date_display[7][64];
// 每个数字的位置
constexpr int time_position[6] = { 0, 6, 18, 24, 36, 42 }, date_position[8] = { 0, 6, 12, 18, 30, 36, 48, 54 };
// 用中括号填充数字, xstart表示起始列(只可为0,6,18,24,36,42), number表示要填充的数字(-1表示冒号)
void insert_time(int xstart, int digit)
{
for (int i = 0; i <= 6; i += 1) for (int j = xstart; j <= xstart + 4; j += 1) time_display[i][j] = num[digit][i][j - xstart];
}
void insert_date(int xstart, int digit)
{
for (int i = 0; i <= 6; i += 1) for (int j = xstart; j <= xstart + 4; j += 1) date_display[i][j] = num[digit][i][j - xstart];
}
// 初始化操作
void init(void)
{
// 插入冒号
time_display[1][14] = time_display[5][14] = time_display[1][32] = time_display[5][32] = 1;
date_display[6][26] = date_display[6][25] = date_display[5][26] = date_display[5][25] =
date_display[6][43] = date_display[6][44] = date_display[5][43] = date_display[5][44] = 1;
// system("color ce");
}
// 获取时间填充数字
void input_time(void)
{
time_t tp;
time(&tp);
tm* p = localtime(&tp);
int digit[6] = { p->tm_hour / 10, p->tm_hour % 10, p->tm_min / 10, p->tm_min % 10, p->tm_sec / 10, p->tm_sec % 10 };
int date[8] = { (p->tm_year + 1900) / 1000, ((p->tm_year + 1900) % 1000) / 100, ((p->tm_year + 1900) % 100) / 10, (p->tm_year + 1900) % 10,
(p->tm_mon + 1) / 10, (p->tm_mon + 1) % 10, p->tm_mday / 10, p->tm_mday % 10 };
for (int i = 0; i <= 5; i += 1) insert_time(time_position[i], digit[i]);
for (int i = 0; i <= 7; i += 1) insert_date(date_position[i], date[i]);
}
// 输出与清屏
void print_time(void)
{
system("cls");
printf("\n");
for (int i = 0; i <= 6; i += 1)
{
printf(" ");
for (int j = 0; j <= 59; j += 1) printf(date_display[i][j] ?
#if _WIN32_WINNT == _WIN32_WINNT_WIN10
"\u2588\u2588"
#elif _WIN32_WINNT == _WIN32_WINNT_WIN7
"\u2588"
#elif _WIN32_WINNT == _WIN32_WINNT_WINXP
"[]"
#endif
: " ");
putchar(10);
}
printf("\n\n");
for (int i = 0; i <= 6; i += 1)
{
printf(" ");
for (int j = 0; j <= 46; j += 1) printf(time_display[i][j] ?
#if _WIN32_WINNT == _WIN32_WINNT_WIN10
"\u2588\u2588"
#elif _WIN32_WINNT == _WIN32_WINNT_WIN7
"\u2588"
#elif _WIN32_WINNT == _WIN32_WINNT_WINXP
"[]"
#endif
: " ");
putchar(10);
}
Sleep(950);
}
int main()
{
init();
while (1)
{
input_time();
print_time();
}
}
输出结果(例子):

一些闲话
P.S. 2024~2025 年以前的 AI 做不到从零开始构建出无 bug 的程序,主要问题都出在不知道怎么把点阵数字输出在一行。
不知道现在的能否从头完成这个作业。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)