C++控制台程序利用符号得到动态图像的经验

本文介绍了一种在C++控制台利用字符创建动态图像的方法,包括将视频转为字符图像、简化图像并实现动效。通过特定软件生成字符图像,然后用程序处理图像,如替换无效字符、调整尺寸,最终实现在控制台中展示动态效果,无需清屏操作。
摘要由CSDN通过智能技术生成

如果嫌字多,直接跳到猪头那里阅读。

一般写需要输出图像的程序我们并不会选择用控制台,因为控制台无法输出图片文件。但是在大学生涯写期末大作业或者实训写一个项目时,我们往往还没有接触过除了控制台以外的其它窗口的便程实现,但我们有时需要得到有图像的程序,甚至让图像能动起来。这个时候我们会想到自然就是通过利用输出符号来组成近似于某个东西的形状。但是具体怎么实现呢?
据我所知,大部分会使用在代码中直接输出符号的方式来组成图像,这种方法固然最容易被人接受,也最简单使用,但是存在的缺点更加明显,比如无法输出较为复杂的图像,更别说是动态的符号图像,同时,这样也会造成代码中大量输出符号的语句,让我们写的代码非常的不优雅。这个时候另辟新径就很有必要了。
在大一期末之后的实训中老师要求写一个宠物精灵的项目,其中就提到要求一定要用到符号图像来显示出宠物,并且要有动效。说实话这个要求让我足足折腾了半天,我百度想寻求解决办法,但是发现网上对于这方面的解答实在太少了,我最后只好自己摸索,差不多又是折腾了半天,总算是摸索出来了,现在将这个方法发到CSDN,希望能给后来者一点帮助!

?正文开始:
第一步:找到一个可以将视频转换为字符图像的软件。别问为什么不是自己写一个程序来转换,因为如果能做到这一点估计也不屑于来看我的博客了。如果找不到,我这里提供一个我找到的,不一定 很好用:链接:https://pan.baidu.com/s/1rN7gyFiVEAnXHMz4dJay-w 提取码:ercl 。用这个软件可以将视频转换位字符图像,那种一帧一帧的。转换之后得到的东西是一个gif文件(这个对我们没有用)和一个html文件,我们用浏览器打开这个html文件,会看到一个完全用字符组成的动态图像:在这里插入图片描述然后右键查看源码:在这里插入图片描述在这里插入图片描述往下翻就是按时间顺序出现的一帧一帧的字符图像。

第二步:
在这里插入图片描述
这么大的图像直接从控制台输出,可想而知会发生什么,所以我们需要简化这些字符图像。而处理这些图像,我们就可以自己写程序来处理了。
我们将需要的部分复制下来:在这里插入图片描述接下来我们需要做两个处理的操作,一是将上图的鱼周围没有用的字符给换成空格,必须换成空格,也不能什么也不换,至于为什么后面会有解释;二是进行读一行丢一行、读一列丢一列的操作,这是为了减小图像的尺寸,在控制台输出时就不会看起来很大,这一步操作具体看你需要实现什么来决定你需要放大还是缩小。

ok,第二步的第一小步:将鱼周围无效的字符读成空格。仔细看你会发现鱼周围的字符其实就只有那么几个相同的,所以采用循环结构加上枚举来把无效字符置换成空格就行。但是在处理之前我还需要提醒一点,就是我们之前从源代码中复制下来的第一帧的字符图像在每一行之间还有一行空的,我们处理图像的时候需要将空行跳过,也就是不读。这一步时实现可以参考以下代码,但是我的代码可能并不适合很大情况:

#include<iostream>
#include<fstream>
#include<Windows.h>
#include<string>
using namespace std;
string a[1000];
int main() {
   

	string op = "date.dat";

	ofstream filem(op, ios_base::out);
	system("mode con cols=320 lines=1000");
	for (int i = 0; i < 28; i++) {
   //1.112,56  2.118,59  3.116,59  4.116,59  5.110 55  6.58  7.59  8.118 59  9.112 56  
	//10.118 59 11.118 59这里代表15帧字符图像算上空行有多少行,不算空行有多少行(大概的计算)
		//12.118 59  13.114 56  14.120 60  15.120 60
		getline(cin,a[i],'\n');//读取一行一定要用这个函数,直接cin会出现问题,因为字符图像中有很多空格会中断cin的读取
		for (int j = 0; j < a[i].size(); j++) {
   
			if (a[i][j] == 'M' || a[i][j] == 'A' || a[i][j] == 'B' || a[i][j] == 'H' || a[i][j] == 'X' || a[i][j] == '&')a[i][j] = ' ';//这几个字符位无效的字符,将其替换为空格
		}
		if (i % 2 == 0) {
   
			filem << a[i] << endl;//这里将空格丢掉
		}
			
	}
	Sleep(1000);
	system("cls");
	for (int i = 0; i < 60; i++) {
   
		cout<<a[i]<<endl;
	}

	return 0}

这里的for循环里i 需要看你实际复制下来的符号图像有多少行。

第二小步:隔一行读一行,相当于缩小一倍,我进行了两次隔一行读一行的操作,相当于缩小为了四分之一。发现自己写的代码有点乱七八糟的,也不知道找到的代码有没有问题,所以这里就不贴代码了:

以上是处理一帧的过程,我们照这种方法继续处理接下来的几帧十几帧。就得到了十几个处理后文件,放着每一帧的字符图像。我那个时候处理了15帧,就有了15个文件分别叫作1.dat至15.dat
然后下面这个地方的代码是显示运行效果,运行这个程序,就会有一只鱼在屏幕中游动:

#include<iostream>
#include<fstream>
#include<Windows.h>
#include<string>
using namespace std;
string a[1000], bb[1000];
int main() {
   

	string op="date.dat";
	string op1 = "1.dat", op2 = "11.dat";
	int b[16] = {
    0,28 ,28 ,28,28,28 ,28,28,28,28,28,28,28,28,28,28 };//215
	system("mode con cols=320 lines=1000");
	for (int i = 1; i <= 15; i++) {
   
		if (i <= 9) {
   
			op1[0] = '0' + i;
			op = op1;
		}
		else {
   
			op2[0] = '1';
			op2[1] = '0' + i - 10;
			op = op2;
		}
		ifstream filem(op, ios_base::in);
		//cout << endl << endl << endl << endl;
		for (int j = 0; j < b[i]; j++) {
   
			getline(filem, a[j], '\n');
			cout << a[j] << endl;
		}
		Sleep(100);
		//system("cls");
		filem.close();
		for (int i = 0; i < b[i]; i++) {
   
			ofstream filem(op, ios_base::out);
			if (i % 2 == 0) {
   
				filem << bb[i] << endl;
			}
		}

		if (i == 15)i = 0;
	}

	return 0;
	}

上面的代码中我注释掉了system(“cls”);这样整个程序实际上是没有进行任何的清屏操作的,那有人可能会怀疑,15帧图像输出到屏幕上时不会出现前面的图像还在然后屏幕上一堆乱七八糟的东西呢,答案时不会的,这就是我之前留下的一个悬念,为什么把无效字符读成空格,因为空格可以将前一帧的图像盖掉,所以完全不需要清屏操作。
到了这里明显还不是最优的,我们肯定不能用15个文件来运行一个程序。这15个文件其实完全可以直接放一个文件里。通过下面这个代码,依次复制1.dat至15.dat文件中的内容但程序中进行处理。得到date。dat这一个文件:

#include<iostream>
#include<fstream>
#include<Windows.h>
#include<string>
using namespace std;
string a[1000],bb[1000];
int main() {
   

	string op = "date.dat";
	ofstream filem(op, ios_base::out);
	system("mode con cols=320 lines=1000");

	for (int i = 0; i < 14 * 15; i++) {
   //14代表每个文件14行,总共15个文件也就是15帧
		getline(cin, a[i], '\n');
		filem << a[i] << endl;
	}
	filem.close();
	return 0;
	}

最后得到了一个文件,包含所有的15帧字符图像的文件。
然后这样调用:

filem.open(op, ios_base::in);
	for (int i = 0; i < 15 * 14; i++) {
   
		getline(filem, a[i], '\n');
	}
	for (int i = 1; i <= 15; i++) {
   
			
			for (int j = 14*(i-1); j < i*14; j++) {
   
				cout << a[j] << endl;
			}
			if (i == 15)i = 0;
	}

大功告成!
最后将鱼的字符图像的素材分享给大家:

                               8   G                                                                     
       G8S                88S8SG339S5SSSS1S3                                                             
         G5s          GG3SS35h111riiii;;ri;sssi                                                          
          G951    88833S5h1s;;;:i;;;;;;-i;i;;;;i:r                                                       
          G33hr;  GG83hiis;r;i;;::-;;;::;;-:;i::;i;;s                                                    
         GG835r;i;iiir;i;s:;i-:;:,;::::--,-:::,-,:::i;;                                                  
          G 9hri:i;;:;::;:::,:-,:::-;:::-.,,,,---:::::irr5                                               
          G33hrrrsi;i;;,,:,:;:-;:-:..,::-:::,.;,.,,-:,:;rr18                                             
          G93hi;:rrrrr----,,-.,,;;-:;;-:.--;.-.-,-.,-:-sr;irs                                            
         G83hr1   G33Ss1i;i-:-.,.--,,,---,  ., ,     ih i.-:;iS                                          
         95r    9 GG33hh;;:i;i:-,.-..,-- .,.., . ..-.    . .--3                                          
       8S3         G955shri;-i1r:::-,-..-  . .  , ,   -   -,-r                                           
    399                          9s::---:.  .          .    8                                            
                                 Sri--:,:-.. .      .    5                                               
             GG                                                                                          
                SG                8G89S9339GS38                         
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值