用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

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直