C 语言图形编程 | 界面 / 动画 / 字符特效

注:本文为 "C 语言图形编程" 相关文章合辑。

略作重排,如有内容异常,请看原文。


C 语言图形化界面------含图形、按钮、鼠标、进度条等部件制作(带详细代码、讲解及注释)

非线性光学元件于 2020-02-15 09:42:37 发布

0. 引言

在 CSDN 上,许多关于 C 程序图形化界面的介绍存在代码繁琐难解、不便调试修改或讲解不够详细的问题。本文提供的代码简单、易于移植且容易理解,希望对急需使用 C 语言制作图形化界面的读者有所帮助。

对于不熟悉 EasyX 的读者,只需 10 分钟即可上手,而它可能为您节省 3 个小时甚至更多的时间。

关于 EasyX 的简单应用,可参考作者之前关于 C 程序可视化的博文:C语言绘图实验-CSDN博客(附后)。

本文的讲解循序渐进,读者应重点关注每个步骤的理解以及两步之间代码的变化。

1. 素材准备

  1. EasyX 的下载链接如下(本文使用的版本是 2014 冬至版):EasyX Graphics Library for C++。使用 EasyX 需注意其兼容的编译器(下载的帮助文件中有说明),不同版本的 EasyX 兼容的编译器不同,但均与 Visual C++6 兼容(与字符编码有关)。本文以 Visual C++6 编译器为例编写代码。

  2. EasyX 的最新英文帮助文档链接(下载 2014 冬至版会自带中文帮助文档):EasyX 文档 - Basic introduction

  3. 如果成功下载了 EasyX 2014 冬至版,解压后将头文件(easyx.hgraphics.h)和 lib 文件(amd64)分别放在 VC 文件夹默认的 include 文件夹和 lib 文件夹中。右键点击 VC 程序,选择"打开文件所在位置",然后找到 MFC 文件夹。

    以下是两个文件夹的位置截图:

  4. 建议将编译的 C 文件以 .cpp 后缀保存。

2. 编程

2.1 创建界面

创建一个 480×360 的窗口,需要使用 initgraph() 函数。以下是代码示例:

c 复制代码
#include <graphics.h>              // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>               // 用到了定时函数 sleep()
#include <math.h>

int main()
{
    int i;
    short win_width, win_height;   // 定义窗口的宽度和高度
    win_width = 480;
    win_height = 360;
    initgraph(win_width, win_height);  // 初始化窗口(黑屏)
    for (i = 0; i < 256; i += 5)
    {
        setbkcolor(RGB(i, i, i)); // 设置背景色,原来默认黑色
        cleardevice();            // 清屏(取决于背景色)
        Sleep(15);                // 延时 15ms
    }
    closegraph();                 // 关闭绘图界面
    return 0;
}

这段代码运行后,屏幕会逐渐变亮。这是因为背景色不断刷新为 RGB(i, i, i)。C 语言中的颜色使用十六进制表示,RGB 函数可以将 0~255 范围内的三个整数三原色转换为十六进制。cleardevice() 函数用于清屏,通常只在初始化时出现。Sleep() 是毫秒级延迟,界面变亮时间不一定是准确的 15ms×255/5=0.765s,因为其他语句也需要执行时间。closegraph() 用于关闭绘图界面。如果初始化了绘图界面但未在主函数结束前关闭它,可能会引发一些莫名其妙的错误,因此该函数必不可少。

2.2 创建按钮

在界面中创建按钮需要绘制矩形和打印文字。以下是代码示例:

c 复制代码
#include <graphics.h>              // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>               // 用到了定时函数 sleep()
#include <math.h>

int r1[] = {30, 20, 130, 60};      // 输入按钮的矩形参数
int r2[] = {170, 20, 220, 60};     // 运行按钮的矩形参数
int r3[] = {260, 20, 310, 60};     // 退出按钮的矩形参数

int main()
{
    int i;
    short win_width, win_height;   // 定义窗口的宽度和高度
    win_width = 480;
    win_height = 360;
    initgraph(win_width, win_height);  // 初始化窗口(黑屏)
    for (i = 0; i < 256; i += 5)
    {
        setbkcolor(RGB(i, i, i)); // 设置背景色,原来默认黑色
        cleardevice();            // 清屏(取决于背景色)
        Sleep(15);                // 延时 15ms
    }
    RECT R1 = {r1[0], r1[1], r1[2], r1[3]};  // 矩形指针 R1
    RECT R2 = {r2[0], r2[1], r2[2], r2[3]};  // 矩形指针 R2
    RECT R3 = {r3[0], r3[1], r3[2], r3[3]};  // 矩形指针 R3
    LOGFONT f;                    // 字体样式指针
    gettextstyle(&f);             // 获取字体样式
    _tcscpy(f.lfFaceName, _T("宋体"));       // 设置字体为宋体
    f.lfQuality = ANTIALIASED_QUALITY;       // 设置输出效果为抗锯齿
    settextstyle(&f);             // 设置字体样式
    settextcolor(BLACK);          // BLACK 在 graphic.h 头文件中被定义为黑色的颜色常量
    drawtext("输入参数", &R1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);   // 在矩形区域 R1 内输入文字,水平居中,垂直居中,单行显示
    drawtext("运行", &R2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);       // 在矩形区域 R2 内输入文字,水平居中,垂直居中,单行显示
    drawtext("退出", &R3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);       // 在矩形区域 R3 内输入文字,水平居中,垂直居中,单行显示
    setlinecolor(BLACK);
    rectangle(r1[0], r1[1], r1[2], r1[3]);
    rectangle(r2[0], r2[1], r2[2], r2[3]);
    rectangle(r3[0], r3[1], r3[2], r3[3]);
    system("pause");              // 暂停,为了显示
    closegraph();
    return 0;
}

矩形指针 RECT 使用句柄定义,不可中途再次赋值。其格式为 RECT r = {X1, Y1, X2, Y2},其中 X1 和 X2 分别是矩形的左边和右边的横坐标,Y1 和 Y2 分别是矩形的上边和下边的纵坐标。DT_CENTER | DT_VCENTER | DT_SINGLELINE 是描述填充格式的常量。drawtext 函数用于在矩形区域内书写文字,无需再计算文字的坐标和设置大小,使用起来非常方便。LOGFONT 是字体样式指针,通过 gettextstyle 函数获取当前字体类型,再通过 settextstyle 函数加以设置。这里仅修改了字体名称和显示质量,还可以修改斜体、下划线等属性,更详细的内容请参考帮助文档。

2.3 鼠标操作

2.3.1 单击特效

鼠标是输入设备,只要发生以下事件,就会暂存于鼠标消息列表中,操作系统会依次响应列表中的鼠标消息事件。常用的鼠标事件如下:

  • WM_MOUSEMOVE:鼠标移动
  • WM_MOUSEWHEEL:鼠标滚轮滚动
  • WM_LBUTTONDOWN:鼠标左键按下
  • WM_LBUTTONUP:鼠标左键弹起
  • WM_LBUTTONDBLCLK:鼠标左键双击
  • WM_RBUTTONDOWN:鼠标右键按下
  • WM_RBUTTONUP:鼠标右键弹起
  • WM_RBUTTONDBLCLK:鼠标右键双击
  • WM_MBUTTONDOWN:鼠标中键按下
  • WM_MBUTTONUP:鼠标中键弹起
  • WM_MBUTTONDBLCLK:鼠标中键双击

以下是实现鼠标左键单击特效的代码示例:

c 复制代码
#include <graphics.h>              // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>               // 用到了定时函数 sleep()
#include <math.h>

int r1[] = {30, 20, 130, 60};      // 输入按钮的矩形参数
int r2[] = {170, 20, 220, 60};     // 运行按钮的矩形参数
int r3[] = {260, 20, 310, 60};     // 退出按钮的矩形参数

int main()
{
    int i;
    short win_width, win_height;   // 定义窗口的宽度和高度
    win_width = 480;
    win_height = 360;
    initgraph(win_width, win_height);  // 初始化窗口(黑屏)
    for (i = 0; i < 256; i += 5)
    {
        setbkcolor(RGB(i, i, i)); // 设置背景色,原来默认黑色
        cleardevice();            // 清屏(取决于背景色)
        Sleep(15);                // 延时 15ms
    }
    RECT R1 = {r1[0], r1[1], r1[2], r1[3]};  // 按钮 1 的矩形区域
    RECT R2 = {r2[0], r2[1], r2[2], r2[3]};  // 按钮 2 的矩形区域
    RECT R3 = {r3[0], r3[1], r3[2], r3[3]};  // 按钮 3 的矩形区域
    LOGFONT f;
    gettextstyle(&f);             // 获取字体样式
    _tcscpy(f.lfFaceName, _T("宋体"));       // 设置字体为宋体
    f.lfQuality = ANTIALIASED_QUALITY;       // 设置输出效果为抗锯齿
    settextstyle(&f);             // 设置字体样式
    settextcolor(BLACK);          // BLACK 在 graphic.h 头文件中被定义为黑色的颜色常量
    drawtext("输入参数", &R1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);   // 在矩形区域 R1 内输入文字,水平居中,垂直居中,单行显示
    drawtext("运行", &R2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);       // 在矩形区域 R2 内输入文字,水平居中,垂直居中,单行显示
    drawtext("退出", &R3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);       // 在矩形区域 R3 内输入文字,水平居中,垂直居中,单行显示
    setlinecolor(BLACK);
    rectangle(r1[0], r1[1], r1[2], r1[3]);
    rectangle(r2[0], r2[1], r2[2], r2[3]);
    rectangle(r3[0], r3[1], r3[2], r3[3]);
    MOUSEMSG m;                   // 鼠标指针
    setrop2(R2_NOTXORPEN);        // 二元光栅------NOT(屏幕颜色 XOR 当前颜色)
    while (true)
    {
        m = GetMouseMsg();        // 获取一条鼠标消息
        if (m.uMsg == WM_LBUTTONDOWN)
        {
            for (i = 0; i <= 10; i++)
            {
                setlinecolor(RGB(25 * i, 25 * i, 25 * i));  // 设置圆颜色
                circle(m.x, m.y, 2 * i);
                Sleep(25);          // 停顿 25ms
                circle(m.x, m.y, 2 * i);  // 抹去刚刚画的圆
            }
            FlushMouseMsgBuff();    // 清空鼠标消息缓存区
        }
    }
    system("pause");              // 暂停,为了显示
    closegraph();
    return 0;
}

每次点击鼠标左键时,鼠标点击处会出现一个逐渐扩大并淡出的圆。当循环体内 Sleep 的时间大于 20ms 时,视觉效果会更明显。每次响应鼠标左键单击事件后,都会调用一次清空鼠标消息缓存区的函数 FlushMouseMsgBuff()。如果没有这个函数,快速连续单击鼠标左键多次时,特效会重复播放,即使停止单击,程序仍会继续播放单击特效,因为鼠标消息队列中的消息尚未处理完毕。

这里需要解释的是二元光栅设置函数 setrop2()。二元光栅是混合背景色和当前颜色的模式。我们采用的是同或(NOT XOR)的方式,若底色为白色(1),则当前颜色不变;若底色是黑色(0),则当前颜色反色。采用这种方式的原因是,我们在第二次抹去原来的圆时不能使用白色,否则如果背景色原本为黑色(比如按钮和文字),也会被抹成白色。而背景色与任意一个颜色同或两次都为其本身,即可起到还原背景色的效果。这里的背景色与 cleardevice() 前面的背景色不同,它是指执行这一条绘画指令之前屏幕上的颜色。

2.3.2 光标感应

当鼠标移到按钮上时,按钮会有所变化,移开按钮时又会恢复原样。这里采用简单的填充颜色方法,即按钮变色。需要解决的问题是按钮变色后按钮的文字不能被覆盖,因此仍需使用二元光栅。为了方便起见,将三个按钮的数组合并为一个二维数组,在鼠标事件中更容易使用和分配任务。以下是代码示例:

c 复制代码
#include <graphics.h>              // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>               // 用到了定时函数 sleep()
#include <math.h>

int r[3][4] = {{30, 20, 130, 60}, {170, 20, 220, 60}, {260, 20, 310, 60}};  // 三个按钮的二维数组

int button_judge(int x, int y)
{
    if (x > r[0][0] && x < r[0][2] && y > r[0][1] && y < r[0][3]) return 1;
    if (x > r[1][0] && x < r[1][2] && y > r[1][1] && y < r[1][3]) return 2;
    if (x > r[2][0] && x < r[2][2] && y > r[2][1] && y < r[2][3]) return 3;
    return 0;
}

int main()
{
    int i, event = 0;
    short win_width, win_height;   // 定义窗口的宽度和高度
    win_width = 480;
    win_height = 360;
    initgraph(win_width, win_height);  // 初始化窗口(黑屏)
    for (i = 0; i < 256; i += 5)
    {
        setbkcolor(RGB(i, i, i)); // 设置背景色,原来默认黑色
        cleardevice();            // 清屏(取决于背景色)
        Sleep(15);                // 延时 15ms
    }
    RECT R1 = {r[0][0], r[0][1], r[0][2], r[0][3]};
    RECT R2 = {r[1][0], r[1][1], r[1][2], r[1][3]};
    RECT R3 = {r[2][0], r[2][1], r[2][2], r[2][3]};
    LOGFONT f;
    gettextstyle(&f);             // 获取字体样式
    _tcscpy(f.lfFaceName, _T("宋体"));       // 设置字体为宋体
    f.lfQuality = ANTIALIASED_QUALITY;       // 设置输出效果为抗锯齿
    settextstyle(&f);             // 设置字体样式
    settextcolor(BLACK);          // BLACK 在 graphic.h 头文件中被定义为黑色的颜色常量
    drawtext("输入参数", &R1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);   // 在矩形区域 R1 内输入文字,水平居中,垂直居中,单行显示
    drawtext("运行", &R2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);       // 在矩形区域 R2 内输入文字,水平居中,垂直居中,单行显示
    drawtext("退出", &R3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);       // 在矩形区域 R3 内输入文字,水平居中,垂直居中,单行显示
    setlinecolor(BLACK);
    rectangle(r[0][0], r[0][1], r[0][2], r[0][3]);
    rectangle(r[1][0], r[1][1], r[1][2], r[1][3]);
    rectangle(r[2][0], r[2][1], r[2][2], r[2][3]);
    MOUSEMSG m;                   // 鼠标指针

    while (true)
    {
        m = GetMouseMsg();        // 获取一条鼠标消息

        switch (m.uMsg)
        {
            case WM_MOUSEMOVE:
                setrop2(R2_XORPEN);
                setlinecolor(LIGHTCYAN);  // 线条颜色为亮青色
                setlinestyle(PS_SOLID, 3);  // 设置画线样式为实线,宽度为 3
                setfillcolor(WHITE);       // 填充颜色为白色
                if (button_judge(m.x, m.y) != 0)
                {
                    if (event != button_judge(m.x, m.y))
                    {
                        event = button_judge(m.x, m.y);  // 记录这一次触发的按钮
                        fillrectangle(r[event - 1][0], r[event - 1][1], r[event - 1][2], r[event - 1][3]);  // 有框填充矩形(X1, Y1, X2, Y2)
                    }
                }
                else
                {
                    if (event != 0)  // 上次触发的按钮未被修正为原来的颜色
                    {
                        fillrectangle(r[event - 1][0], r[event - 1][1], r[event - 1][2], r[event - 1][3]);  // 两次同或为原来颜色
                        event = 0;
                    }
                }
                break;
            case WM_LBUTTONDOWN:
                setrop2(R2_NOTXORPEN);  // 二元光栅------NOT(屏幕颜色 XOR 当前颜色)
                for (i = 0; i <= 10; i++)
                {
                    setlinecolor(RGB(25 * i, 25 * i, 25 * i));  // 设置圆颜色
                    circle(m.x, m.y, 2 * i);
                    Sleep(30);          // 停顿 30ms
                    circle(m.x, m.y, 2 * i);  // 抹去刚刚画的圆
                }
                break;
            FlushMouseMsgBuff();  // 清空鼠标消息缓存区
        }
    }
    system("pause");              // 暂停,为了显示
    return 0;
}

在鼠标移动事件(case WM_MOUSEMOVE)中,使用了屏幕颜色与当前颜色异或的方式。fillrectangle 函数用于绘制一个有框填充矩形,其大小与原按钮一致。由于线条颜色为亮青色,填充颜色为白色(1),白色填充颜色与屏幕颜色异或后,取的是屏幕颜色的反色。按钮的边框是黑色(0),它与亮青色异或后,会保留原来的亮青色。与同或一样,异或两次等于没有执行操作,因此可以还原到原屏幕画布的颜色。

2.3.3 进度条

涉及进度条时,通常会结合一个简单的程序来展示进度条的变化。这里设计了一个简单的弹性球轨迹作图程序。假设球的半径为 ( R ),初始高度为 ( h_0 ),初速度为 0(自由落体),非弹性碰撞时能量损失率为 ( \alpha )。计算部分子函数如下:

c 复制代码
int simulation()
{
    float dt = 0.01;  // 仿真间隔 10ms
    long int N = (long int)(sim_t / dt);  // 迭代次数
    float *h = (float *)calloc(N, sizeof(float));  // 高度
    float *v = (float *)calloc(N, sizeof(float));  // 速度(竖直方向)
    long int i;  // 迭代变量
    for (i = 1; i < N; i++)
    {
        if (h[i - 1] > R)  // 未发生碰撞
        {
            v[i] = v[i - 1] - 9.8 * dt;  // 速度计算
        }
        else  // 发生碰撞,动能损失 \( \alpha \),速度损失 \( \sqrt{\alpha} \)
        {
            v[i] = -sqrt(alpha) * v[i - 1];
        }
    }
    free(h);
    free(v);  // 释放内存
    return 0;
}

接下来,需要定义绘图网格的函数:

c 复制代码
void init_figure()
{
    int i;
    setrop2(R2_COPYPEN);  // 当前颜色
    setlinecolor(BLACK);
    setlinestyle(PS_SOLID);  // 实线
    rectangle(30, 100, 420, 330);  // 外框线
    setlinestyle(PS_DOT);  // 点线
    for (i = 30 + 39; i < 420; i += 39)
    {
        line(i, 100, i, 330);  // 竖直辅助线
    }
    for (i = 100 + 23; i < 330; i += 23)
    {
        line(30, i, 420, i);  // 水平辅助线
    }
}

使用 rectangle 函数绘制网格外框架,使用 line 函数依次画出辅助线。目标是将高度 ( h ) 的坐标转换到网格上,绘制出球心的轨迹。以下是改进后的 simulation 函数代码:

c 复制代码
int simulation()
{
    char t[3];  // 百分值的字符
    char *out_text;  // 带百分号的百分字符
    float dt = 0.01;  // 仿真间隔 10ms
    float dy = 230 / h0;  // 单位纵坐标
    long int N = (long int)(sim_t / dt);  // 迭代次数
    float *h = (float *)calloc(N, sizeof(float));  // 高度
    float *v = (float *)calloc(N, sizeof(float));  // 速度(竖直方向)
    long int i;  // 迭代变量
    float process_duty;  // 进度
    RECT r = {370, 35, 400, 65};  // 百分值显示区域的矩形指针
    init_figure();  // 初始化图像网格
    setrop2(R2_COPYPEN);  // 当前颜色
    setfillcolor(WHITE);
    setlinecolor(WHITE);
    fillrectangle(354, 19, 411, 81);  // 覆盖原进度条区域
    setlinestyle(PS_NULL);  // 无线条
    setbkmode(TRANSPARENT);  // 设置文字填充背景为透明
    // 计算步骤
    h[0] = h0;
    v[0] = 0;
    BeginBatchDraw();  // 开始缓存区
    for (i = 1; i < N; i++)
    {
        if (h[i - 1] > R)  // 未发生碰撞
        {
            v[i] = v[i - 1] - 9.8 * dt;  // 速度计算
        }
        else  // 发生碰撞,动能损失 \( \alpha \),速度损失 \( \sqrt{\alpha} \)
        {
            v[i] = -sqrt(alpha) * v[i - 1];
        }
        setfillcolor(WHITE);
        setlinecolor(WHITE);
        fillrectangle(354, 19, 416, 81);  // 覆盖原进度条区域
        h[i] = h[i - 1] + v[i] * dt;  // 高度计算
        process_duty = (i + 1) / (float)(N);
        setlinestyle(PS_SOLID);
        putpixel(30 + (int)(process_duty * 390), 330 - (int)(h[i] * dy), RED);  // 画点 putpixel(X, Y, color*)
        setfillcolor(BLUE);
        setlinestyle(PS_NULL);
        fillpie(355, 20, 415, 80, 0, process_duty * 2 * PI);  // 绘制环形进度条
        setfillcolor(WHITE);
        fillcircle(385, 50, 20);  // 覆盖中心部分
        sprintf(t, "%d", (int)(process_duty * 100.0));  // 整型转换为字符串
        out_text = strcat(t, "%");  // 添加一个百分号
        drawtext(out_text, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);  // 显示进度百分比
        Sleep(dt * 1000);  // 延时
        FlushBatchDraw();  // 刷新缓存区
    }
    EndBatchDraw();  // 结束缓存区
    free(h);
    free(v);
    return 0;
}

这里使用了 putpixel 函数绘制球心轨迹,fillpie 函数绘制环形进度条,fillcircle 函数覆盖中心部分以形成环形效果。FlushBatchDraw 函数用于刷新缓存区,与 BeginBatchDrawEndBatchDraw 一起使用,可以批量绘图后再刷新画板。

3. 完整代码及效果

以下是完整的代码示例,包含按钮、鼠标操作、进度条和弹性球轨迹作图功能:

c 复制代码
#include <graphics.h>              // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>               // 用到了定时函数 sleep()
#include <math.h>
#include <string.h>
#define PI 3.1416
int r[3][4] = {{30, 20, 130, 60}, {170, 20, 220, 60}, {260, 20, 310, 60}};  // 三个按钮的二维数组
float alpha, R, h0, sim_t;  // 碰撞时的能量损失率,球的半径、初始高度、仿真时间

// 按钮判断函数
int button_judge(int x, int y)
{
    if (x > r[0][0] && x < r[0][2] && y > r[0][1] && y < r[0][3]) return 1;
    if (x > r[1][0] && x < r[1][2] && y > r[1][1] && y < r[1][3]) return 2;
    if (x > r[2][0] && x < r[2][2] && y > r[2][1] && y < r[2][3]) return 3;
    return 0;
}

// 初始化图像
void init_figure()
{
    int i;
    setrop2(R2_COPYPEN);  // 当前颜色
    setlinecolor(BLACK);
    setlinestyle(PS_SOLID);  // 实线
    rectangle(30, 100, 420, 330);  // 外框线
    setlinestyle(PS_DOT);  // 点线
    for (i = 30 + 39; i < 420; i += 39)
    {
        line(i, 100, i, 330);  // 竖直辅助线
    }
    for (i = 100 + 23; i < 330; i += 23)
    {
        line(30, i, 420, i);  // 水平辅助线
    }
}

// 仿真运行
int simulation()
{
    char t[3];  // 百分值的字符
    char *out_text;
    float dt = 0.01;  // 仿真间隔 10ms
    float dy = 230 / h0;  // 单位纵坐标
    long int N = (long int)(sim_t / dt);  // 迭代次数
    float *h = (float *)calloc(N, sizeof(float));  // 高度
    float *v = (float *)calloc(N, sizeof(float));  // 速度(竖直方向)
    long int i;  // 迭代变量
    float process_duty;  // 进度
    RECT r = {370, 35, 400, 65};  // 百分值显示区域的矩形指针
    init_figure();  // 初始化图像网格
    setrop2(R2_COPYPEN);  // 当前颜色
    setfillcolor(WHITE);
    setlinecolor(WHITE);
    fillrectangle(354, 19, 411, 81);  // 覆盖原进度条区域
    setlinestyle(PS_NULL);  // 无线条
    setbkmode(TRANSPARENT);  // 设置文字填充背景为透明
    // 计算步骤
    h[0] = h0;
    v[0] = 0;
    BeginBatchDraw();  // 开始缓存区
    for (i = 1; i < N; i++)
    {
        if (h[i - 1] > R)  // 未发生碰撞
        {
            v[i] = v[i - 1] - 9.8 * dt;  // 速度计算
        }
        else  // 发生碰撞,动能损失 \( \alpha \),速度损失 \( \sqrt{\alpha} \)
        {
            v[i] = -sqrt(alpha) * v[i - 1];
        }
        setfillcolor(WHITE);
        setlinecolor(WHITE);
        fillrectangle(354, 19, 416, 81);  // 覆盖原进度条区域
        h[i] = h[i - 1] + v[i] * dt;  // 高度计算
        process_duty = (i + 1) / (float)(N);
        setlinestyle(PS_SOLID);
        putpixel(30 + (int)(process_duty * 390), 330 - (int)(h[i] * dy), RED);  // 画点 putpixel(X, Y, color*)
        setfillcolor(BLUE);
        setlinestyle(PS_NULL);
        fillpie(355, 20, 415, 80, 0, process_duty * 2 * PI);  // 绘制环形进度条
        setfillcolor(WHITE);
        fillcircle(385, 50, 20);  // 覆盖中心部分
        sprintf(t, "%d", (int)(process_duty * 100.0));  // 整型转换为字符串
        out_text = strcat(t, "%");  // 添加一个百分号
        drawtext(out_text, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);  // 显示进度百分比
        Sleep(dt * 1000);  // 延时
        FlushBatchDraw();  // 刷新缓存区
    }
    EndBatchDraw();  // 结束缓存区
    free(h);
    free(v);
    return 0;
}

int main()
{
    int i, event = 0;
    char s[30];  // 输入字符串变量
    short win_width, win_height;  // 定义窗口的宽度和高度
    win_width = 480;
    win_height = 360;
    initgraph(win_width, win_height);  // 初始化窗口(黑屏)
    for (i = 0; i < 256; i += 5)
    {
        setbkcolor(RGB(i, i, i));  // 设置背景色,原来默认黑色
        cleardevice();  // 清屏(取决于背景色)
        Sleep(30);  // 延时 30ms
    }
    RECT R1 = {r[0][0], r[0][1], r[0][2], r[0][3]};
    RECT R2 = {r[1][0], r[1][1], r[1][2], r[1][3]};
    RECT R3 = {r[2][0], r[2][1], r[2][2], r[2][3]};
    LOGFONT f;  // 字体样式指针
    gettextstyle(&f);  // 获取字体样式
    _tcscpy(f.lfFaceName, _T("宋体"));  // 设置字体为宋体
    f.lfQuality = ANTIALIASED_QUALITY;  // 设置输出效果为抗锯齿
    settextstyle(&f);  // 设置字体样式
    settextcolor(BLACK);  // BLACK 在 graphic.h 头文件中被定义为黑色的颜色常量
    drawtext("输入参数", &R1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);  // 在矩形区域 R1 内输入文字,水平居中,垂直居中,单行显示
    drawtext("运行", &R2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);  // 在矩形区域 R2 内输入文字,水平居中,垂直居中,单行显示
    drawtext("退出", &R3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);  // 在矩形区域 R3 内输入文字,水平居中,垂直居中,单行显示
    setlinecolor(BLACK);
    rectangle(r[0][0], r[0][1], r[0][2], r[0][3]);
    rectangle(r[1][0], r[1][1], r[1][2], r[1][3]);
    rectangle(r[2][0], r[2][1], r[2][2], r[2][3]);
    MOUSEMSG m;  // 鼠标指针

    while (true)
    {
        m = GetMouseMsg();  // 获取一条鼠标消息

        switch (m.uMsg)
        {
            case WM_MOUSEMOVE:
                setrop2(R2_XORPEN);
                setlinecolor(LIGHTCYAN);  // 线条颜色为亮青色
                setlinestyle(PS_SOLID, 3);  // 设置画线样式为实线,宽度为 3
                setfillcolor(WHITE);  // 填充颜色为白色
                if (button_judge(m.x, m.y) != 0)
                {
                    if (event != button_judge(m.x, m.y))
                    {
                        event = button_judge(m.x, m.y);  // 记录这一次触发的按钮
                        fillrectangle(r[event - 1][0], r[event - 1][1], r[event - 1][2], r[event - 1][3]);  // 有框填充矩形(X1, Y1, X2, Y2)
                    }
                }
                else
                {
                    if (event != 0)  // 上次触发的按钮未被修正为原来的颜色
                    {
                        fillrectangle(r[event - 1][0], r[event - 1][1], r[event - 1][2], r[event - 1][3]);  // 两次同或为原来颜色
                        event = 0;
                    }
                }
                break;
            case WM_LBUTTONDOWN:
                setrop2(R2_NOTXORPEN);  // 二元光栅------NOT(屏幕颜色 XOR 当前颜色)
                for (i = 0; i <= 10; i++)
                {
                    setlinecolor(RGB(25 * i, 25 * i, 25 * i));  // 设置圆颜色
                    circle(m.x, m.y, 2 * i);
                    Sleep(20);  // 停顿 20ms
                    circle(m.x, m.y, 2 * i);  // 抹去刚刚画的圆
                }
                // 按照按钮判断左键单击后的操作
                switch (button_judge(m.x, m.y))
                {
                    case 1:
                        InputBox(s, 30, "请输入碰撞时的能量损失率、球的半径、初始高度、仿真时间");
                        sscanf(s, "%f %f %f %f", &alpha, &R, &h0, &sim_t);  // 将输入字符串依次扫描到全局变量中
                        FlushMouseMsgBuffer();  // 单击事件后清空鼠标消息
                        break;
                    case 2:
                        simulation();  // 仿真运行
                        FlushMouseMsgBuffer();  // 单击事件后清空鼠标消息
                        break;
                    case 3:
                        closegraph();  // 关闭绘图环境
                        exit(0);  // 正常退出
                    default:
                        FlushMouseMsgBuffer();  // 单击事件后清空鼠标消息
                        break;
                }
                break;
        }
    }
    return 0;
}

希望本文对您有所帮助,谢谢阅读。


C 语言实现动画控制

非线性光学元件于 2018-12-22 20:47:28 发布

原材料

下载 EasyX 2014 冬至版,将 lib 文件放在编译器默认的 lib 文件夹中,h 头文件放在编译器默认的 include 文件夹中即可。下载链接:EasyX Graphics Library for C++

说明

C 语言可以使用系统内部的定时函数 sleepusleep 进行定时(需要 windows.h 头文件),但绘图窗口需要额外的图形库支持。EasyX 提供了绘图功能,可以为您的 C 编译器带来革命性的变化。

一场革命

EasyX 的压缩包中包含一个帮助文档,虽然内容丰富但不太方便查阅。希望正在使用 EasyX 的开发者能多分享一些资源。以下是一个沿着指定半径依次绘制 12 个不同颜色的圆并依次擦除的小动画程序。代码中对不太容易理解的部分加了注释,通过图形画法学习 C 语言语法,既生动又简单,可以快速跨越语法障碍。

c 复制代码
#include <graphics.h>              // 引用图形库头文件
#include <conio.h>
#include <stdio.h>
#include <windows.h>               // 用到了定时函数 sleep()
#include <math.h>
#define PI 3.14159265  // 画圆必备
int a[] = {0, 0xAA0000, 0x00AA00, 0xAAAA00, 0x0000AA, 0xAA00AA, 0x0055AA, 0xAAAAAA, 0x555555, 0xFF5555, 0x55FF55, 0xFFFF55, 0x5555FF, 0xFF55FF, 0x55FFFF, 0xFFFFFF};  // a[] 是颜色数组
// a 数组存放的颜色依次为
/*	|0:黑色		|1:蓝色		|2:绿色		|3:青色		|4:红色
	|5:紫色		|6:棕色		|7:浅灰		|8:深灰		|9:亮蓝
	|10:亮绿	|11:亮青	|12:亮红	|13:亮紫	|14:黄色	|15:白色
*/
int main()
{
    system("color 0B");  // 设置字体为亮蓝色,纯粹为了好看
    short x, y;  // 圆心坐标
    int R;  // 旋转半径
    int color[6] = {1, 2, 3, 4, 5, 6};  // 指定圆的颜色
    int i = 0;
    char t;
    printf("C 语言绘图实验:\n");
    printf("请选择画布大小(以空格分隔):\n");
    scanf("%d %d", &x, &y);
    initgraph(x, y, SHOWCONSOLE);  // 创建绘图窗口,大小为 640x480 像素
    printf("请输入旋转半径: ");
    scanf("%d", &R);
    printf("请选择 6 种圆的颜色:\n");
    printf("|0:黑色\n|1:蓝色\t|2:绿色\t|3:青色\t|4:红色\t|5:紫色\n|6:棕色\t|7:浅灰\t|8:深灰\t|9:亮蓝\t|10:亮绿\n|11:亮青\t|12:亮红\t|13:亮紫\t|14:黄色\t|15:白色\n");
    scanf("%d %d %d %d %d %d", &color[0], &color[1], &color[2], &color[3], &color[4], &color[5]);  // 录入 6 种不同的颜色
    printf("\r按任意键继续:\n");
    while (_getch())  // _getch() 是按下任意键即返回非零值的函数,与 getchar() 不同,不经过标准输入流的缓存区
    {
        for (i = 0; i < 12; i++)
        {
            setlinecolor(RGB(0, 0, 0));  // 设置当前线条颜色
            setfillcolor(a[color[i % 6]]);  // 设置当前填充颜色
            fillcircle(x / 2 + R * cos(i * PI / 6), y / 2 + R * sin(i * PI / 6), R * (PI / 12) * 0.9);  // 绘制填充圆
            Sleep(300);  // 延时 300ms
        }
        for (i = 0; i < 12; i++)
        {
            setlinecolor(RGB(0, 0, 0));  // 设置当前线条颜色
            setfillcolor(a[0]);  // 背景色(黑色)覆盖掉原来的图形
            fillcircle(x / 2 + R * cos(i * PI / 6), y / 2 + R * sin(i * PI / 6), R * (PI / 12) * 0.9);
            Sleep(300);  // 延时 300ms
        }
    }
    return 0;
}

以下是程序运行主界面:

以下是绘图界面:


C 语言写字符动画

Z.IA 已于 2024-12-01 14:26:02 修改

用 C 在控制台写了一个动画,代码没做优化,十分简单粗暴。

新版本 win 系统需使用老版本 cmd。

以管理员身份运行 exe 文件即可。

cpp 复制代码
 #include <stdio.h>
 #include <windows.h>
 void color (int x)
 {
   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x);	
 }
 int main()
{
	int i,j,q=28,xxl=22,h=27,m=33,cc=2,xxx=1;
	char s[68][53];
	char z[140][53];
	char zx[148][100];
	
	 for(i=0;i<35;i++)
	{
	   for(j=0;j<28;j++)
	   zx[i][j]=' ';
       for(j=28;j<=35;j++)
	   zx[i][j]='O';
	   for(j=36;j<100;j++)
	   zx[i][j]=' ';	
	}	
	
	for(i=35;i<134;i++)
	{
	   for(j=0;j<h;j++)
	   zx[i][j]=' ';
       for(j=h;j<h+4;j++)
	   zx[i][j]='O';
	   for(j=h+4;j<=m;j++)
	   zx[i][j]=' ';
	   for(j=m;j<m+4;j++)
	   zx[i][j]='O';
	   for(j=m+4;j<100;j++)
	   zx[i][j]=' ';
	   if(i<57)
	   {
	   	h--;
	   	m++;
	   }
	   if(i>110)
	   {
	   	h++;
	   	m--;
	   }
	}
	
	  for(i=134;i<148;i++)
	{
	   for(j=0;j<28;j++)
	   zx[i][j]=' ';
       for(j=28;j<=35;j++)
	   zx[i][j]='O';
	   for(j=36;j<100;j++)
	   zx[i][j]=' ';	
	}	
	
	
	for(i=48;i<=51;i++)
	for(j=31;j<=35;j++)
	zx[i][j]='*';
	
	for(i=129;i<=133;i++)
	{
	for(j=15;j<=17;j++)
	zx[i][j]='*';
	for(j=46;j<=48;j++)
	zx[i][j]='*';
    }
    
    
	
	for(i=0;i<40;i++)  //直行 
	{
	for(j=0;j<28;j++)
	z[i][j]=' ';
	for(j=28;j<36;j++)
	z[i][j]='O';
	for(j=36;j<53;j++)
	z[i][j]=' ';
   }
   
   for(i=40;i<61;i++)   //拐弯+回; 
	{
		for(j=0;j<q;j++)
		z[i][j]=' ';
		for(j=q;j<q+8;j++)
		z[i][j]='O';
	    for(j=q+8;j<60;j++)
	    z[i][j]=' ';
	    if(i<53)                 //右移长度控制 
	    q-=2;               
	    if(i>53&&i<60)             //回长度控制 
	    q++;
	}
		for(i=61;i<101;i++)  //直行 
	{
	for(j=0;j<8;j++)
	z[i][j]=' ';
	for(j=8;j<16;j++)
	z[i][j]='O';
	for(j=16;j<53;j++)
	z[i][j]=' ';
   }
	
	
	for(i=101;i<124;i++)   //拐弯+回; 
	{
		for(j=0;j<q;j++)
		z[i][j]=' ';
		for(j=q;j<q+8;j++)
		z[i][j]='O';
	    for(j=q+8;j<60;j++)
	    z[i][j]=' ';
	    if(i<114)                 //右移长度控制 
	    q+=2;               
	    if(i>114&&i<121)             //回长度控制 
	    q--;
	}
	
	 for(i=124;i<140;i++)
	{
	   for(j=0;j<28;j++)
	   z[i][j]=' ';
       for(j=28;j<=35;j++)
	   z[i][j]='O';
	   for(j=36;j<100;j++)
	   z[i][j]=' ';	
	}	
	
	
	for(i=54;i<=57;i++)
	z[i][30]=z[i][31]=z[i][32]='*';
	for(i=116;i<=119;i++)
	z[i][14]=z[i][15]=z[i][16]='*';
	
	
		for(i=0;i<40;i++)  //直行 
	{
	for(j=0;j<22;j++)
	s[i][j]=' ';
	for(j=22;j<29;j++)
	s[i][j]='O';
	for(j=29;j<53;j++)
	s[i][j]=' ';
   }
	for(i=40;i<68;i++)   //拐弯+回; 
	{
		for(j=0;j<xxl;j++)
		s[i][j]=' ';
		for(j=xxl;j<xxl+8;j++)
		s[i][j]='O';
	    for(j=xxl+8;j<53;j++)
	    s[i][j]=' ';
	    if(i<53)                 //右移长度控制 
	    xxl++;               
	    if(i>53&&i<60)             //回长度控制 
	    xxl--;
	}
	


int k,c=28,begin=28,end=39;
q=39;
  char x[104][40];	
  for(i=0;i<=10;i++)
  {
  for(j=0;j<q;j++)
  x[i][j]=' ';
  for(j=q;j<=39;j++)
  x[i][j]='O';
  if(q>27)
  q--;
  }
   for(i=90;i<=101;i++)
  {
  for(j=0;j<=c;j++)
  x[i][j]=' ';
  for(j=c+1;j<=39;j++)
  x[i][j]='O';
  if(c<39)
  c++;
  }
  for (i=11;i<=50;i++)
  {
  	for (j=0;j<begin;j++)
  	x[i][j]=' ';
  	for (j=begin;j<=end;j++)
  	x[i][j]='O';
  	for (j=end+1;j<=39;j++)
  	x[i][j]=' ';
  	if(begin>0)
  	begin--;
  	if(end>0)
  	end--;
  }
  end++;
  for (i=51;i<=89;i++)
  {
  	for (j=0;j<begin;j++)
  	x[i][j]=' ';
  	for (j=begin;j<=end;j++)
  	x[i][j]='O';
  	for (j=end+1;j<=39;j++)
  	x[i][j]=' ';
  	if(end>=11)
  	begin++;
  	if(end<39)
  	end++;
  }
  
  //扭动组赋值 
	

char kd[100][40];
for(i=0;i<100;i++)
{
	for(j=0;j<38;j++)
	kd[i][j]=' ';
	kd[i][39]='O';
}
	

	
	int p=1,g=1,xs=3;
  char wy[200][120];
  for(i=0;i<200;i++)
  for(j=0;j<120;j++)
  wy[i][j]=' ';
  
  
  for(i=0;i<40;i++)
  {
  	for(j=0;j<8;j++)
  	wy[i][j]=' ';
  	for(j=8;j<16;j++)
  	wy[i][j]='O';
  	for(j=16;j<100;j++)
  	wy[i][j]=' ';
  }
  
  /*直行赋值*/ 
  j=16;
  for(i=40;i<76;i++)
  {
	 wy[i][j]='O';	
	 if((i-39)%4==0&&i>=43)
	 g+=p;
	 j+=g;
     if(i==55)
     p=-p;
  } 
  
  j=15;
  p=1;
  g=1;
  for(i=42;i<78;i++)
  {
	 wy[i][j]='O';	
	 if((i-41)%4==0&&i>=45)
	 g+=p;
	 j+=g;
     if(i==57)
     p=-p;
  } 
  
   j=14;
  p=1;
  g=1;
  for(i=44;i<80;i++)
  {
	 wy[i][j]='O';	
	 if((i-43)%4==0&&i>=47)
	 g+=p;
	 j+=g;
     if(i==59)
     p=-p;
  } 
  
  
   j=13;
  p=1;
  g=1;
  for(i=46;i<82;i++)
  {
	 wy[i][j]='O';	
	 if((i-45)%4==0&&i>=49)
	 g+=p;
	 j+=g;
     if(i==61)
     p=-p;
  } 
  
  j=12;
  p=1;
  g=1;
  for(i=48;i<84;i++)
  {
	 wy[i][j]='O';	
	 if((i-47)%4==0&&i>=51)
	 g+=p;
	 j+=g;
     if(i==63)
     p=-p;
  } 
  // 第5组; 
  
  j=11;
  p=1;
  g=1;
  for(i=50;i<86;i++)
  {
	 wy[i][j]='O';	
	 if((i-49)%4==0&&i>=53)
	 g+=p;
	 j+=g;
     if(i==65)
     p=-p;
  } 
  
   j=10;
  p=1;
  g=1;
  for(i=52;i<88;i++)
  {
	 wy[i][j]='O';	
	 if((i-51)%4==0&&i>=55)
	 g+=p;
	 j+=g;
     if(i==67)
     p=-p;
  } 
  
   j=9;
  p=1;
  g=1;
  for(i=54;i<90;i++)
  {
	 wy[i][j]='O';	
	 if((i-53)%4==0&&i>=57)
	 g+=p;
	 j+=g;
     if(i==69)
     p=-p;
  } 
   p=54;
    for(j=8;j<16;j++)
    {
    	for(i=40;i<p;i++)
    	wy[i][j]='O';
    	p-=2;
	}
	//补充 O 
	
	p=75;
 for(j=116;j>=110;j--)
 {
 	for(i=89;i>p;i--)
 	wy[i][j]='O';
 	p+=2;
 }
 
 for(i=90;i<130;i++)
  {
  	for(j=109;j<117;j++)
  	wy[i][j]='O';
  }
  
  j=108;
p=-1;
g=-1;
  for(i=130;i<166;i++)
  {
	 wy[i][j]='O';	
	 if((i-129)%4==0&&i>=133)
	 g+=p;
	 j+=g;
     if(i==145)
     p=-p;
  } 
  
   j=109;
p=-1;
g=-1;
  for(i=132;i<168;i++)
  {
	 wy[i][j]='O';	
	 if((i-131)%4==0&&i>=135)
	 g+=p;
	 j+=g;
     if(i==147)
     p=-p;
  } 
  
      j=110;
p=-1;
g=-1;
  for(i=134;i<170;i++)
  {
	 wy[i][j]='O';	
	 if((i-133)%4==0&&i>=137)
	 g+=p;
	 j+=g;
     if(i==149)
     p=-p;
  } 
  
  
     j=111;
p=-1;
g=-1;
  for(i=136;i<172;i++)
  {
	 wy[i][j]='O';	
	 if((i-135)%4==0&&i>=139)
	 g+=p;
	 j+=g;
     if(i==151)
     p=-p;
  } 
  
       j=112;
p=-1;
g=-1;
  for(i=138;i<174;i++)
  {
	 wy[i][j]='O';	
	 if((i-137)%4==0&&i>=141)
	 g+=p;
	 j+=g;
     if(i==153)
     p=-p;
  } 
  
  
  j=113;
  p=-1;
  g=-1;
  for(i=140;i<176;i++)
  {
	 wy[i][j]='O';	
	 if((i-139)%4==0&&i>=143)
	 g+=p;
	 j+=g;
     if(i==155)
     p=-p;
  } 
  
  
  j=114;
  p=-1;
  g=-1;
  for(i=142;i<178;i++)
  {
	 wy[i][j]='O';	
	 if((i-141)%4==0&&i>=145)
	 g+=p;
	 j+=g;
     if(i==157)
     p=-p;
  } 
  
  
   j=115;
  p=-1;
  g=-1;
  for(i=144;i<180;i++)
  {
	 wy[i][j]='O';	
	 if((i-143)%4==0&&i>=147)
	 g+=p;
	 j+=g;
     if(i==159)
     p=-p;
  } 
  
  p=165;
  for(j=8;j<16;j++)
  {
  	for(i=179;i>p;i--)
  	wy[i][j]='O';
  	p+=2;
  }
  
  p=144;
  for(j=116;j>=110;j--)
  {
  	for(i=130;i<p;i++)
  	wy[i][j]='O';
  	p-=2;
  }
  
    for(i=180;i<200;i++)
  {
  	for(j=0;j<8;j++)
  	wy[i][j]=' ';
  	for(j=8;j<16;j++)
  	wy[i][j]='O';
  	for(j=16;j<100;j++)
  	wy[i][j]=' ';
  }
  
  
  
 //菱形部分 
  char a[50][54];
  k=15;
  begin=24;
  end=27;
  for(i=0;i<=49;i++)
  for(j=24;j<=27;j++)
  a[i][j]='O';
  for(i=0;i<=24;i++)
  {
  	for(j=0;j<begin;j++)
  	a[i][j]=' ';
  	for(j=begin;j<24;j++)
  	a[i][j]='i';
  	for(j=28;j<=end;j++)
  	a[i][j]='i';
  	for(j=end+1;j<=51;j++)
  	a[i][j]=' ';
  	begin-=1;end+=1;
  }
    begin+=1;end-=1;
   for(i=25;i<=49;i++)
  {
  	for(j=0;j<begin;j++)
  	a[i][j]=' ';
  	for(j=begin;j<24;j++)
  	a[i][j]='i';
  	for(j=28;j<=end;j++)
  	a[i][j]='i';
  	for(j=end+1;j<=51;j++)
  	a[i][j]=' ';
  	begin+=1;end-=1;
  }
  
  system("color f3");
  for(i=0;i<100;i++)
  {
  	for(j=0;j<40;j++)
  	printf("%c",kd[i][j]);
  	printf("\n\n");
  	Sleep(2);
  }  
  
  
  int yans=2;
   system("color f3");
   while(yans--)
{
   for(i=0;i<=100;i++)
   {
     for (j=0;j<=39;j++)
	 printf("%c",x[i][j]);
	 if(i<=100)
	 printf("\n\n");
	 Sleep(1);
   } 
}



k=3;
 while (k--)
 {
   for(i=0;i<=49;i++)
   {
   	for(j=0;j<24;j++)
   	{
   	color(3);
   	printf("%c",a[i][j]);
    }
    for(j=24;j<=27;j++)
    {
    color(7);
    printf("%c",a[i][j]);
    }
    for(j=28;j<=51;j++)
    {
	 color(3);
	 printf("%c",a[i][j]);
	}
   	printf("\n\n");
   	Sleep(1);
   }
 }
 
 
	
	color(7);
	for(i=47;i<=50;i++)
	s[i][8]=s[i][9]=s[i][10]='*';
	for(i=0;i<47;i++)
	{ 
	for(j=0;j<53;j++)
	printf("%c",s[i][j]);
	printf("\n\n");
	Sleep(1);
}
	for(i=47;i<=50;i++)
	{
	for(j=0;j<=10;j++)
	{
		color(4);
		printf("%c",s[i][j]);
	}
       for(j=11;j<53;j++)
       {
       	color(7);
       	printf("%c",s[i][j]);
	   }
  printf("\n\n");
    }
    for(i=51;i<68;i++)
    {
    for(j=0;j<53;j++)
    printf("%c",s[i][j]);
    printf("\n\n");
    Sleep(1);
}


	while(cc--)
{
	for(i=0;i<54;i++)
{ 
	for(j=0;j<53;j++)
	printf("%c",z[i][j]);
	printf("\n\n");
	Sleep(1);
}
	for(i=54;i<=57;i++)
	{
     	for(j=0;j<=29;j++)
     	{
     		color(7);
		printf("%c",z[i][j]);
     	}
    	for(j=30;j<33;j++)
    	{
    		color(4);
		printf("%c",z[i][j]);
	    }
		printf("\n\n"); 
		Sleep(1);
    }
       color(7); 
       for(i=58;i<116;i++)
     {  
        for(j=0;j<53;j++)
       	printf("%c",z[i][j]);
       	printf("\n\n");
       	Sleep(1);
	 }
     
     	for(i=116;i<=119;i++)
	{
     	for(j=0;j<=16;j++)
    	{
		color(4);
		printf("%c",z[i][j]);
    	}
    	for(j=17;j<53;j++)
    	{
    		color(7);
		printf("%c",z[i][j]);
	    }
		printf("\n\n"); 
		Sleep(1);
    }
    for(i=120;i<140;i++)
    {
    for(j=0;j<53;j++)
    printf("%c",z[i][j]);
    printf("\n\n");
    Sleep(1);
    }
}


  
     while(xxx--)
{
     for(i=0;i<48;i++)
     {
     for(j=0;j<100;j++)
     printf("%c",zx[i][j]);
     printf("\n\n");
     Sleep(1);
     }
     
     for(i=48;i<52;i++)
     {
     	for(j=0;j<31;j++)
     	printf("%c",zx[i][j]);
     	color(4);
     	for(j=31;j<=35;j++)
     	printf("%c",zx[i][j]);
     	color(7);
     	for(j=36;j<100;j++)
     	printf("%c",zx[i][j]);
     	printf("\n\n");
     	Sleep(1);
	 }
	 
	 for(i=52;i<129;i++)
	 {
	 	for(j=0;j<100;j++)
	 	printf("%c",zx[i][j]);
	 	printf("\n\n");
	 	Sleep(1);
	 }
	 
	 for(i=129;i<134;i++)
	 {
	 	color(4);
	 	for(j=0;j<=17;j++)
	 	printf("%c",zx[i][j]);
	 	color(7);
	 	for(j=18;j<46;j++)
	 	printf("%c",zx[i][j]);
	 	color(4);
	 	for(j=46;j<100;j++)
	 	printf("%c",zx[i][j]);
	 	printf("\n\n");
	 	Sleep(1);
	 }
	 
	 color(7);
	 for(i=134;i<148;i++)
	 {
	 	for(j=0;j<100;j++)
	 	printf("%c",zx[i][j]);
	 	printf("\n\n");
	 	Sleep(1);
	 }
	 
}



	for(i=0;i<54;i++)
{ 
	for(j=0;j<53;j++)
	printf("%c",z[i][j]);
	printf("\n\n");
	Sleep(1);
}
	for(i=54;i<=57;i++)
	{
     	for(j=0;j<=29;j++)
     	{
     		color(7);
		printf("%c",z[i][j]);
     	}
    	for(j=30;j<33;j++)
    	{
    		color(4);
		printf("%c",z[i][j]);
	    }
		printf("\n\n"); 
		Sleep(1);
    }
       color(7); 
       for(i=58;i<102;i++)
     {  
        for(j=0;j<53;j++)
       	printf("%c",z[i][j]);
       	printf("\n\n");
       	Sleep(1);
	 }



 while(xs--)
{
   for(i=0;i<200;i++)
    {
    	for(j=0;j<120;j++)
    	{
    	color(xs+2);
    	printf("%c",wy[i][j]);
        }
    	printf("\n\n");
    	Sleep(2);
	}
}
}

via: