用C++写个简单的程序表白老妈

2023-10-25 19:12

本文主要是介绍用C++写个简单的程序表白老妈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

后天就是老妈的生日了,我打算写一个简单的程序表白老妈子,来肉麻一下她。在实现的过程中,有不少我没学过的知识,这些知识我都会予以补充。

创建图形窗口

创建图形窗口要包头文件:

#include<easyx.h>

这是简单的图形库,只要会写c语言就能用。

注意:只有先去官网下载这个图形库,再包才会生效!下载方法c站一搜就有。

包了这个图形库,我们以前运行程序出现的那个黑框窗口,就被图形窗口所取代了。

ok,现在要怎么创建图形窗口呢?用initgraph函数:初始化图形窗口。

#include<iostream>
#include<easyx.h>
​
int main() {initgraph(1000, 800);  //两个参数分别是 while(1){}return 0;
}

这里的while(1){}只是为了让图形窗口停留,不然它会一闪而过。

创建出来的图形窗口:

🚩补充:initgraph函数

initgraph(w,h,f);

用于初始化图形窗口。

三个参数分别为: width 绘图环境的宽度 height 绘图环境高度 flag 绘图环境样式(可省略)

播放音乐

🚩这里要介绍一个用于播放音乐的函数mciSendString(),它是用来播放多媒体文件的API指令,可以播放mp3、wma、wav、mid等文件。

我先来介绍一下函数名,帮助大家理解。mci媒体控制接口:media control interface

mciSendString可以理解为:向mci发送命令字符串

它在使用时一般按这个格式写:

mciSendString("open XX.mp3",NULL,0,NULL);

如果这样写编译不过去,就用这个格式:

mciSendString(_T("open XX.mp3"),NULL,0,NULL);   //注意XX.mp3要写明它的路径

只需要记忆第一个参数,后面三个就按照格式的来。

第一个参数重点记忆三个:open、play、close,分别对应打开、播放、关闭。

使用mciSendString()前要包含头文件:#include<mmsystem.h>

并导入库:#pragma comment<lib."winmm.lib">

实现:

#include<iostream>
#include<easyx.h>
#include<mmsystem.h>  
#pragma comment(lib,"winmm.lib")  
​
void Display() {//播放背景音乐   mciSendString(_T("open ./source/别看我只是一只羊.mp3 alias bgm "), NULL,0, NULL);   //alias给文件取别名,叫bgm,便于后续操作mciSendString(_T("play bgm "), NULL, 0, NULL);
}
int main() {initgraph(1000, 800);Display(); while(1){}return 0;
}

输出文字

🚩补充:

1.设置字体样式settextstyle()

我们在vs下是能看到这个函数的参数的,分别为:高度、宽度、样式。

2.设置字体颜色settextcolor()

settextcolor(BLUE);  //将字体设为蓝色
settextcolor(RGB(223,234,100));   //自选字体颜色

如何自选字体颜色?

打开画图软件,选择你喜欢的颜色,然后记住这三个参数:

因为所有颜色都是由红绿蓝(RGB) 三原色合成的,所以输入这三个参数就可以合成对应的颜色。

3.输出文字outtextxy()

outtextxy()函数,可以这样理解:out text x y,在坐标(x,y)输出文本信息。它是C++中的一个绘图函数,可以在屏幕上输出文本信息。它使用起来也很简单:

void outtextxy(int x,int y,const char* str);  //前两个参数是坐标信息,第三个参数是要输出的文本

图形窗口中的坐标轴,原点在左上角,x轴向右,y轴向下。

实现:

void Display() {mciSendString(_T("open ./source/别看我只是一只羊.mp3 alias bgm "), NULL,0, NULL);mciSendString(_T("play bgm "), NULL, 0, NULL);
​//设置字体样式settextstyle(40, 20, _T("仿宋"));//设置颜色settextcolor(RGB(100,216,234));//输出文字outtextxy(50, 50, _T("妈妈,我是宝宝!"));outtextxy(50, 100, _T("明天就是你的生日了,"));outtextxy(50, 150, _T("祝你生日快乐!"));outtextxy(50, 200, _T("我写了首诗,献给你:"));outtextxy(50, 250, _T("“鹅鹅鹅,红掌拨清波”"));
}

emmmm,挺丑的。现在我们来把它变好看一点。

如何做出颜色闪动效果

刚刚的颜色太单调了,只有一种。我们想要的效果是,每过几秒,它就能随机变幻颜色。要想生成随机值,就用rand()。

让颜色随机

🚩生成随机数rand():

rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数。

如果你要产生0~99这100个整数中的一个随机整数,可以表达为:int num = rand() %100; 这样,num的值就是一个0~99中的一个随机数了。

而RGB的参数值范围是0~255,所以就用rand()%256。

在用rand()的过程中,我遇到的几个问题:

1.连续生成的颜色都比较相近,不够随机!

这是因为没有设置种子。什么是种子?请听我说~

rand()产生的是 伪随机数,并不是真正的随机数。这个伪随机数 是根据种子推导得到的。

所谓种子,就是初值。打个比方,我给的初值是100,那这个100作为种子,推出的伪随机数是99。这个99再作为种子,推出的伪随机数是102。102再作为种子,……

现在,你能知道为啥rand()连续产生的数值都比较相近了吧!

只有初值变化,伪随机数才变。如果不涉及密码学,那用时间来当种子完全够了,因为时间是时时刻刻在变化的。

在rand()之前,用srand()播种:

srand((unsigned)time(NULL));   //用srand()设置种子,叫“播种”。以时间作为种子

但要注意:srand不能写在循环里,因为循环一次的时间间隔太短了,time十分相近,产生的种子就是相同的了。

srand写在循环外(前面),只设置一次就可以了。

对了,记得引头文件<time.h>

2.闪动得太快了!一秒变好几个颜色。

要想延迟,用Sleep()函数,注意S大写。

Sleep(1000);  //延迟1000ms

实现:

#include<iostream>
#include<easyx.h>
#include<time.h>
#include<mmsystem.h>   
#pragma comment(lib,"winmm.lib")  
​
void Display() {//每次循环开始前,要清屏cleardevice(); //播放背景音乐  mciSendString(_T("open ./source/别看我只是一只羊.mp3 alias bgm "), NULL,0, NULL);mciSendString(_T("play bgm "), NULL, 0, NULL);
​//设置字体样式settextstyle(40, 29, _T("仿宋"));//设置文字颜色//srand((unsigned)time(NULL));settextcolor(RGB(rand()%256, rand() % 256, rand() % 256));//输出文字outtextxy(50, 50, _T("妈妈,我是宝宝!"));outtextxy(50, 100, _T("明天就是你的生日了,"));outtextxy(50, 150, _T("祝你生日快乐!"));outtextxy(50, 200, _T("我写了首诗,献给你:"));outtextxy(50, 250, _T("“鹅鹅鹅,红掌拨清波”"));//再插入点图案for (int i = 0; i < 8; i++) {      settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));outtextxy(rand() % 1001, rand() % 651, _T("🤍"));outtextxy(rand() % 1001, rand() % 651, _T("🎈"));}Sleep(1000);
}
int main() {//创建图形窗口initgraph(1000, 650);srand((unsigned)time(NULL));while (1) {Display();}return 0;
}

让图案背景透明

但此时,我们会发现,字被图案遮挡了:

 

这是因为,图案的背景被填充上了颜色,这种颜色是不透明的。而此时我们希望透过图案背景看到下面的字。

这就需要我们在输出文字之前,设置背景为透明。

setbkmode函数(设置背景模式):

setbkmode(TRANSPARENT);

来看效果:

最终效果:

插入背景图

流程是这样的:

Step1.先创建一个IMAGE类型的数组,将你准备的几张背景图按个放进数组。

Step2.在Display函数中,选一张图片插入图形窗口。

🚩补充:

1.从图片文件获取图像loadimage

void loadimage(
IMAGE* p,     // 保存图像的 IMAGE 对象指针
LPCTSTR pImgFile,     // 图片文件名
int nWidth = 0,    // 图片的拉伸宽度
int nHeight = 0,     // 图片的拉伸高度
bool bResize = false     // 是否调整 IMAGE 的大小以适应图片
);

2.输出图像putimage(int left,int right,void*buf,int ops);

参数(left,top)为输出屏幕图像的左上角,即输出图像的起始位置。buf指向要输出的内存中图像。参数ops控制图像以何种方式输出到屏幕上(可省略)。

实现:

IMAGE img[2];   //创建全局的数组。注:IMAGE是一个类型
​
int main() {//创建图形窗口initgraph(1000, 650);//将图片放进数组loadimage(img, _T("./source/1.jpg"), 1000, 650);loadimage(img+1, _T("./source/2.png"), 1000, 650);
​//展示效果srand((unsigned)time(NULL));while (1) {Display();}return 0;
}
oid Display() {//每次循环开始前,要清屏cleardevice();//插入背景putimage(0, 0, img+1);//播放背景音乐 mciSendString(_T("open ./source/别看我只是一只羊.mp3 alias bgm "), NULL,0, NULL);mciSendString(_T("play bgm "), NULL, 0, NULL);……
}

效果:

如果没看到效果,那可能是你图片的格式不行,我一开始那张图是.webp,不行。后来改属性变成.jpg或者.png,就可以了。

按任意键退出

为了展示效果,我们当前把程序写成了死循环。现在,我要达到 按任意键就能退出页面 的效果。这要用到函数_kbhit()。

包头文件:

#include<conio.h>

_kbhit()是用来检测有没有按键的,没有按键返回假。

那我们这样写,就可以让程序顺利运行,按键退出:

int main() {//创建图形窗口initgraph(1000, 650);//将图片放进数组loadimage(img, _T("./source/1.jpg"), 1000, 650);loadimage(img+1, _T("./source/2.png"), 1000, 650);
​//展示效果srand((unsigned)time(NULL));while (!_kbhit()) {     //没有按键返回真Display();}return 0;
}

那么最终效果呈现为:

(此处有bgm)

总代码

#include<iostream>
#include<easyx.h>
#include<conio.h>
#include<time.h>
#include<mmsystem.h>   
#pragma comment(lib,"winmm.lib")  
​
IMAGE img[2];
​
void Display() {//每次循环开始前,要清屏cleardevice();//插入背景putimage(0, 0, img+1);//播放背景音乐 mciSendString(_T("open ./source/别看我只是一只羊.mp3 alias bgm "), NULL,0, NULL);mciSendString(_T("play bgm "), NULL, 0, NULL);
​//设置字体样式settextstyle(40, 29, _T("仿宋"));//设置文字颜色settextcolor(RGB(rand()%256, rand() % 256, rand() % 256));//设置背景为透明setbkmode(TRANSPARENT);//输出文字outtextxy(50, 50, _T("妈妈,我是宝宝!"));outtextxy(50, 100, _T("明天就是你的生日了,"));outtextxy(50, 150, _T("祝你生日快乐!"));outtextxy(50, 200, _T("我写了首诗,献给你:"));outtextxy(50, 250, _T("“鹅鹅鹅,红掌拨清波”"));
​for (int i = 0; i < 8; i++) {settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));outtextxy(rand() % 1001, rand() % 651, _T("🤍"));outtextxy(rand() % 1001, rand() % 651, _T("🎈"));}Sleep(1000);
}
int main() {//创建图形窗口initgraph(1000, 650);//将图片放进数组loadimage(img, _T("./source/1.jpg"), 1000, 650);loadimage(img+1, _T("./source/2.png"), 1000, 650);
​//展示效果srand((unsigned)time(NULL));while (!_kbhit()) {Display();}return 0;
}

这篇关于用C++写个简单的程序表白老妈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/284638

相关文章

将java程序打包成可执行文件的实现方式

《将java程序打包成可执行文件的实现方式》本文介绍了将Java程序打包成可执行文件的三种方法:手动打包(将编译后的代码及JRE运行环境一起打包),使用第三方打包工具(如Launch4j)和JDK自带... 目录1.问题提出2.如何将Java程序打包成可执行文件2.1将编译后的代码及jre运行环境一起打包2

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解