实验题目
设计一个程序,演示美丽的“池塘夜雨”景色:色彩缤纷的雨点飘飘洒洒地从天而降,滴滴入水有声,溅起圈圈微澜。
操作环境和条件
VS2017,easyX图形库
代码
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
//conio是Console Input/Output(控制台输入输出)的简写,
//其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等
#include <time.h>
//从系统时钟获取时间方式
//ime_t time(time_t* timer)
//得到从标准计时点(一般是1970年1月1日午夜)到当前时间的秒数。
//clock_t clock(void)
//得到从程序启动到此次函数调用时累计的毫秒数。
#include <windows.h>
//WINDOWS.H是一个最重要的头文件,它包含了其他Windows头文件,这些头文件的某些也包含了其他头文件。这些头文件中最重要的和最基本的是:
//WINDEF.H 基本数据类型定义。
//WINNT.H 支持Unicode的类型定义。
//WINBASE.H Kernel(内核)函数。
//WINUSER.H 用户界面函数。
//WINGDI.H 图形设备接口函数。
#include <graphics.h>//如果您需要在vc及vs环境中使用graphics.h的功能
//您可以下载EasyX图形库(注意:这是一个C++的图形库 如果您一定要在C语言环境下使用 graphics.h 您可以使用windows gdi
#include <mmsystem.h>//windows中与多媒体有关的大多数接口
#pragma comment(lib, "winmm.lib")
#include <graphics.h>
struct rainDrop *head;头结点
MOUSEMSG m;///鼠标信息
int n = 100; //雨的数目
long msecond1, msecond2;
struct rainCircle //雨点落下造成的水圈
{
int x;
int y;
int r;//雨圈的最大半径
int curR;
int rainCircleStep; //水圈产生的步骤
};
struct rainDrop
{
int startX; //雨点开始的X值
int startY; //雨点开始的Y值
int endY; //雨点结束的Y值
int curX; //雨点降落中的X值
int curY; //雨点降落中的Y值
COLORREF rainColor; //雨点的颜色
//COLORREF是color和reference的缩写,表示颜色值,实际上是unsigned long类型。
//可以配合RGB()宏来设置。
int rainLineStep; //雨线的顺序
int rainLineLength; //雨线的长度
int status;
struct rainCircle water;//水圈结构体类型
struct rainDrop *next;//指向下一个雨滴下落的指针
};
struct rainDrop *creatDrop(void)//函数返回一个指向rainDrop类型的结构体
{
struct rainDrop *p;//定义结构体类型
p = (struct rainDrop *)malloc(sizeof(struct rainDrop));//动态分配内存
p->startY = 120;//雨点下落起始Y位置赋初值
p->startX = rand() % 1000; //rand()函数是产生随机数的一个随机函数,包涵在#include<stdlib.h>头文件中
p->startY = p->startY + rand() % 630;
p->endY = 590 + rand() % 50;//雨点结束位置赋值
p->curX = p->startX;//雨点降落过程中为X赋值
p->curY = p->startY;//雨点降落过程中为Y赋值
p->rainLineStep = 8;//雨线顺序赋初值
p->rainLineLength = 10;//雨线长度赋初值
p->status = 0;
p->rainColor = RGB(rand() % 256, rand() % 256, rand() % 256);
//RGB(red, green, blue)
//red 0 到 255 间的整数,代表颜色中的红色成分。
//green 0 到 255 间的整数,代表颜色中的绿色成分。
//blue 0 到 255 间的整数,代表颜色中的蓝色成分。
p->water.x = p->startX;//水圈开始的X是雨滴的X
p->water.y = p->endY;//水圈的Y是雨滴结束的Y
p->water.r = rand() % 30;//水圈的最大半径随机确定
p->water.curR = rand() % 2;
p->water.rainCircleStep = rand() % 2 + 1;
p->next = NULL;
return(p);
}
void recreatDrop(struct rainDrop *p)
{
p->startY = 120;
p->startX = rand() % 1000;
p->startY = p->startY + rand() % 630;
p->endY = 590 + rand() % 50;
p->curX = p->startX;
p->curY = p->startY;
p->rainLineStep = 8;
p->rainLineLength = 10;
p->status = 0;
p->rainColor = RGB(rand() % 256, rand() % 256, rand() % 256);
p->water.x = p->startX;
p->water.y = p->endY;
p->water.r = rand() % 30;
p->water.curR = rand() % 2;
p->water.rainCircleStep = rand() % 2 + 1;
}
void creatRain(void) //创建链表
{//创建的是循环链表,不断生成雨滴
struct rainDrop *p1, *p2;//定义两个指向rainDrop类型的结构体指针
int i;
p1 = p2 = creatDrop();
head = p1;
for (i = 0; i < n; i++)
{
p2 = creatDrop();
p1->next = p2;
p1 = p2;
}
p1->next = head;
}
//生成下一个雨点的位置
void updateRainLineData(struct rainDrop *p)
{
if (MouseHit())如果有鼠标信息就获取,没有就不获取
//检测当前是否有鼠标消息
m = GetMouseMsg();//获取一个鼠标消息。如果当前鼠标消息队列中没有,就一直等待。
p->curY += p->rainLineStep;//Y的增量为rainLineStep
if (m.y < 200)
p->curY -= p->rainLineStep / 2;
if (m.y > 450)
p->curY += p->rainLineStep;
p->startY = p->curY - p->rainLineLength;
//
if (m.x < 300)
{
p->curX -= p->rainLineStep;
p->startX = p->curX + p->rainLineLength;
}
if (m.x > 600)
{
p->curX += p->rainLineStep;
p->startX = p->curX - p->rainLineLength;
}
}
void drawRainLine(struct rainDrop *p) //画雨线
{
setlinestyle(PS_SOLID, 1);//设置当前画线样式(实线,宽度是1)
setcolor(p->rainColor);//设置雨线的颜色,实现彩色雨
line(p->startX, p->startY, p->curX, p->curY);//画直线
}
void clearRainLine(struct rainDrop *p) //以黑 or blue表示雨线消失
{
if (p->startY > 550)
setcolor(BLUE);//设置雨线的颜色,用蓝色表示雨消失
else
setcolor(BLACK);//设置雨线的颜色,黑色也可以表示雨消失
setlinestyle(PS_SOLID, 1);// 设置当前画线样式(实线,宽度是1)
line(p->startX, p->startY, p->curX, p->curY);//画直线
}
void thunder(struct rainDrop *p)
{
int x, y;
x = (rand() % 800) + 100;
y = (rand() % 200) + 200;
setfillcolor(WHITE);
bar(0, 250, 1000, 550);
Sleep(1);
setfillcolor(BLACK);
bar(0, 250, 1000, 550);
POINT pts[] = { {x - 30,y},{x,y},{x,y - 70},{x + 30,y},{x,y},{x,y + 70} };
setfillcolor(WHITE);
solidpolygon(pts, 6);
Sleep(1);
setfillcolor(BLACK);
solidpolygon(pts, 6);
PlaySound("C:\\thunder.wav", NULL, SND_FILENAME | SND_ASYNC); //vc++最简单的声音函数
}
void updateRainCircleData(struct rainDrop *p) //控制水圈的大小
{
p->water.curR += p->water.rainCircleStep;
}
void drawRainCircle(struct rainDrop *p) //画雨降落后的水圈
{
int x1, x2, y1, y2;
setcolor(p->rainColor);//画雨的颜色
x1 = p->water.x - p->water.curR - 5;
x2 = p->water.x + p->water.curR + 5;
y1 = p->water.y - p->water.curR + 5;
y2 = p->water.y + p->water.curR - 5;//确定雨滴下落后水圈椭圆的各个参数
ellipse(x1, y1, x2, y2); //画椭圆
}
###########void clearRainCircle(struct rainDrop *p) //以blue色表示水圈消失
{//清除水圈
int x1, x2, y1, y2;
setcolor(BLUE);//将绘图背景色设置成蓝色
x1 = p->water.x - p->water.curR - 5;
x2 = p->water.x + p->water.curR + 5;
y1 = p->water.y - p->water.curR + 5;
y2 = p->water.y + p->water.curR - 5;//和生成水圈椭圆的参数保持一致
ellipse(x1, y1, x2, y2);//将画出的椭圆的颜色与池塘的颜色保持一致,表示水圈消失
}
########void rainDropDown(struct rainDrop *p) //控制雨的路径
{
if (p->curY >= p->endY)//雨线的末尾到达产生水圈的位置
{
clearRainLine(p);//清除雨线
p->status = 1;//雨线的末尾到达产生水圈的位置
}
else
{
clearRainLine(p);//清除雨线
updateRainLineData(p);//更新雨线下落路径
drawRainLine(p);//画出雨线
///
if (m.mkLButton == true && p->curX % 999 == 1)//此处条件在于减少打雷的概率
thunder(p);
}
}
########void fallToWater(struct rainDrop *p) //控制雨圈雨点的衔接
{
if (p->water.curR >= p->water.r)
{
clearRainCircle(p);//清除水圈
recreatDrop(p);
}
else
{
clearRainCircle(p);
updateRainCircleData(p);//更新水圈
drawRainCircle(p);//画出水圈
}
}
void rain() //控制全程雨的开始到结束
{
struct rainDrop *p;
p = head;
while (!kbhit())
{
if (p->status == 0)
rainDropDown(p);//清除所有
else
fallToWater(p);
//PlaySound("C:\\rain.wav", NULL, SND_FILENAME | SND_ASYNC); //vc++最简单的声音函数
p = p->next;
}
}
void clearAll(void) //画图结束,释放空间
{
struct rainDrop *p, *pf;
p = head;
while (p != head)
{
pf = p;
p = p->next;
free(pf);
}
closegraph();
}
void wuyun()
{
setlinecolor(DARKGRAY); //定义画线颜色
setfillcolor(DARKGRAY); //设置填充颜色
fillellipse(20, 20, 200, 100); // (1)
fillcircle(50, 60, 40);
fillcircle(90, 70, 40);
fillcircle(140, 70, 40);
fillcircle(90, 35, 30);
fillcircle(140, 40, 30);
fillcircle(185, 60, 35);
fillellipse(270, 20, 450, 100);
fillcircle(300, 60, 40);
fillcircle(340, 70, 40);
fillcircle(390, 70, 40);
fillcircle(340, 35, 30);
fillcircle(390, 40, 30);
fillcircle(435, 60, 35);
fillellipse(520, 20, 700, 100);
fillcircle(550, 60, 40);
fillcircle(590, 70, 40);
fillcircle(640, 70, 40);
fillcircle(590, 35, 30);
fillcircle(640, 40, 30);
fillcircle(685, 60, 35);
fillellipse(770, 20, 950, 100);
fillcircle(800, 60, 40);
fillcircle(840, 70, 40);
fillcircle(890, 70, 40);
fillcircle(840, 35, 30);
fillcircle(890, 40, 30);
fillcircle(935, 60, 35);
//getch();
}
void pond()
{
setlinecolor(BLUE);
line(0, 680, 1000, 680);
setfillstyle(0, NULL, NULL);
setfillcolor(BLUE);
bar(0, 550, 1000, 680);
//池塘
}
int main()
{
initgraph(1000, 680);
pond();
creatRain();
wuyun();
rain();
clearAll();
return 0;
}
效果图
注意
安装easyX参照官网:https://www.easyx.cn/
出现了(“The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name:”) 的报错
https://blog.csdn.net/whappymanlynn/article/details/50930461
下载
实验报告 |
---|
链接:https://pan.baidu.com/s/1SQI48qpXkH6X7hha7mvmUA 提取码:o5bk |
点个赞?再走 |