IE盒子

搜索
查看: 128|回复: 1

C语言橘子钟表

[复制链接]

2

主题

11

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2022-12-9 20:04:02 | 显示全部楼层 |阅读模式
程序简介

这个橘子钟表程序主要分成三个部分:画表盘、画表针、显示当前时间。画表盘部分运用到了三次贝塞尔曲线、HSL 颜色模型以及字符串格式化命令,其中三次贝塞尔曲线确定点的坐标比较复杂。画表针主要涉及到计算各表针运动的弧度。显示当前时间所用字体为等宽字体,其作用在于居中后效果更均匀。
程序当中计算三次贝塞尔曲线坐标部分,我定义了 13 个点,其中 0 点和 11 点 12 点重合,3 点和 4 点重合,5 点和 6 点重合,10 点和 9 点重合。这样做的目的是便于确定起始点、控制点和终点。
程序中用到了 Broadway 字体,好像是装 Office 的时候带的字体。如果看不到文字效果,请先安装这个字体。
程序截图



程序源码:

/////////////////////////////////////////////////////////
// 程序名称:橘子钟表
// 编译环境:Visual C++ 2010,Unicode 字符集,EasyX_20220610
//
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>

const double PI = 3.141592654;        // 定义圆周率


// 画表盘
void dial()
{
        // 画蓝色背景
        setbkcolor(0xe6cdb4);                // 设置背景色
        cleardevice();                                // 清屏

        // 画黄色外圆
        setlinestyle(PS_SOLID, 10);        // 设置线宽为十个像素
        setlinecolor(YELLOW);                // 设置画线颜色为黄色
        setfillcolor(WHITE);                // 设置填充颜色为白色
        fillcircle(0, 0, 170);                // 画圆

        // 填充扇形颜色
        int r = 150;                                // 定义半径为 150
        setlinestyle(PS_SOLID, 2);        // 设置线宽为两像素
        for (int n = 0; n < 10; n++)
        {
                // 画橘子瓣的三次贝塞尔曲线
                POINT pts[13];                                // 定义数组,起始点、控制点 1、控制点 2、终点(起点)、控制点 1、控制点 2、终点(起点)……
                double a = 2 * PI * n / 10;        // 橘子瓣弧度
                pts[0].x = int(r / 8 * cos(a + 2 * PI / 22));
                pts[0].y = int(r / 8 * sin(a + 2 * PI / 22));        pts[12] = pts[11] = pts[0];
                pts[1].x = int(r / 12 * cos(a + 2 * PI / 22));        pts[2].x = int(r / 12 * cos(a - 2 * PI / 22));
                pts[1].y = int(r / 12 * sin(a + 2 * PI / 22));        pts[2].y = int(r / 12 * sin(a - 2 * PI / 22));
                pts[3].x = int(r / 8 * cos(a - 2 * PI / 22));
                pts[3].y = int(r / 8 * sin(a - 2 * PI / 22));        pts[4] = pts[3];
                pts[5].x = int(r * cos(a - 2 * PI / 22));
                pts[5].y = int(r * sin(a - 2 * PI / 22));                pts[6] = pts[5];
                pts[9].x = int(r * cos(a + 2 * PI / 22));
                pts[9].y = int(r * sin(a + 2 * PI / 22));                pts[10] = pts[9];
                pts[7].x = int(r * 1.1 * cos(a - 2 * PI / 30));        pts[8].x = int(r * 1.1 * cos(a + 2 * PI / 30));
                pts[7].y = int(r * 1.1 * sin(a - 2 * PI / 30));        pts[8].y = int(r * 1.1 * sin(a + 2 * PI / 30));

                int c = HSLtoRGB(36.0f * n, 0.8f, 0.8f);                                // 设置彩虹色
                setlinecolor(c);                                                                                // 设置画线颜色为彩虹色
                polybezier(pts, 13);                                                                        // 画三次贝塞尔曲线       

                setfillcolor(c);                                                                                // 设置填充色为彩虹色
                floodfill(int(r / 2 * cos(a)), int(r / 2 * sin(a)), c);        // 填充橘子瓣
        }

        // 显示表盘细节
        settextcolor(BLACK);                                // 设置字体颜色
        setbkmode(TRANSPARENT);                                // 设置背景色为透明
        for (int n = 0; n < 12; n++)
        {
                // 整点刻度
                setfillcolor(BLACK);
                solidcircle(int(145 * cos(n * 2 * PI / 12)), -int(145 * sin(n * 2 * PI / 12)), 2);
                solidcircle(int(145 * cos(n * 2 * PI / 4)),  -int(145 * sin(n * 2 * PI / 4)),  4);

                // 显示数字
                wchar_t s[10];
                swprintf_s(s, 10, L"%d", 12 - n);                // int 类型转换成 char 类型

                // 设置字体、大小及输出
                if ((12 - n) % 3 == 0)        settextstyle(48, 0, L"Broadway");
                else                                        settextstyle(24, 0, L"Broadway");

                // 定义字符串长和宽,居中
                int w, h;
                w = textwidth(s);
                h = textheight(s);
                outtextxy(int(125 * cos(n * 2 * PI / 12 + PI / 2) - w / 2),
                                 -int(125 * sin(n * 2 * PI / 12 + PI / 2) - h / 2),
                                  s);
        }
}


// 显示数字时钟
void digital(int h, int m, int s)
{
        // 画显示当前时间的三个小矩形
        setlinecolor(LIGHTGRAY);        // 设置边框颜色为浅灰色
        setfillcolor(WHITE);                // 设置填充颜色为白色
        fillrectangle(-40 - 13, 50, -40 + 13, 50 + 26);
        fillrectangle(     -13, 50,       13, 50 + 26);
        fillrectangle( 40 - 13, 50,  40 + 13, 50 + 26);

        // 显示当前时间
        settextstyle(24, 0, L"Consolas");
        wchar_t a[10];
        int w;
        swprintf_s(a, 10, L"%d", h);        w = textwidth(a);        outtextxy(-40 - w / 2, 50, a);
        swprintf_s(a, 10, L"%d", m);        w = textwidth(a);        outtextxy(     -w / 2, 50, a);
        swprintf_s(a, 10, L"%d", s);        w = textwidth(a);        outtextxy( 40 - w / 2, 50, a);
}


// 画表针
void needles(int h, int m, int s)
{
        double a = PI / 2 - (2 * PI * h / 12 + 2 * PI * 1 / 12 * m / 60);        // 时针所走弧度
        double b = PI / 2 - (2 * PI * m / 60 + 2 * PI * 1 / 60 * s / 60);        // 分针所走弧度
        double c = PI / 2 - 2 * PI * s / 60;                                                                // 秒针所走弧度

        setlinecolor(BLACK);                                                                                                // 设置画线颜色为黑色
        setlinestyle(PS_SOLID, 9);                                                                                        // 设置线宽为九像素
        line(0, 0, int(50 * cos(a)), int(-50 * sin(a)));                                        // 画时针

        setlinestyle(PS_SOLID, 6);                                                                                        // 设置线宽为六像素
        line(0, 0, int(100 * cos(b)), int(-100 * sin(b)));                                        // 画分针

        setlinecolor(RED);                                                                                                        // 设置画线颜色为红色
        setlinestyle(PS_SOLID, 3);                                                                                        // 设置线宽为三像素
        line(int(20 * cos(c + PI)), -int(20 * sin(c + PI)), int(130 * cos(c)), -int(130 * sin(c)));        // 画秒针
}


// 主函数
int main()
{
        // 创建绘图窗口
        initgraph(640, 480);
        BeginBatchDraw();                // 开启批量绘图
        setorigin(320, 240);        // 设置原点

        while (true)
        {
                // 计算
                SYSTEMTIME ti;                // 定义变量保存当前时间
                GetLocalTime(&ti);        // 获取当前时间

                // 绘画
                cleardevice();
                dial();                                                                                // 画表盘
                digital(ti.wHour, ti.wMinute, ti.wSecond);        // 画数字时钟
                needles(ti.wHour, ti.wMinute, ti.wSecond);        // 画表针

                // 延时
                FlushBatchDraw();
                Sleep(1000);
        }

        _getch();
        EndBatchDraw();
        closegraph();
        return 0;
}想学习更多实战项目的可以看看

点击链接加入群聊【C语言/C++编程基地㈢】:
回复

使用道具 举报

1

主题

14

帖子

21

积分

新手上路

Rank: 1

积分
21
发表于 2025-5-6 18:52:29 | 显示全部楼层
在撸一遍。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表