模拟时钟转动程序课程设计报告

                 

华科学院计算机科学与技术专业

《程序设计综合课程设计》报告

   (2010/20##学年 第一学期)

学生姓名:           

学生班级:        

学生学号:      

指导教师:          

20##年 1 月 7 日


目 录

第一章 课程设计的目的和要求. 1

1.1  C语言课程设计的目的. 1

1.2  C语言课程设计实现的要求. 1

第二章 课程设计的任务内容. 2

第三章 详细设计说明. 3

3.1  程序系统的结构. 3

3.2  模块描述. 3

3.2.1  指针式时钟. 3

3.2.2  数字式时钟. 3

3.3  输出项. 3

3.4  算法. 3

3.5  流程图. 4

3.6  函数说明. 5

3.7  接口. 5

3.8  调试结果. 6

第四章 软件使用说明. 7

4.1  软件使用说明及出现的问题. 7

4.2  运行结果. 7

第五章 课程设计心得与体会. 8

附录1:参考文献. 10

附录2:程序清单. 11


模拟时钟转动程序

第一章 课程设计的目的和要求

1.1  C语言课程设计的目的

加深对讲授内容的理解,尤其是一些语法规定。通过课程设计,自然地、熟练地掌握。熟悉所用的计算机系统的操作方法,也就是熟悉语言程序开发的环境。学会上机调试程序。

1.2  C语言课程设计实现的要求

能模拟机械钟表行走;要准确地利用数字显示日期和时间;在屏幕上显示一个活动时钟;程序界面设计合理,色彩得体大方,显示正确;各指针运动规律正确;数字式时钟的时间显示与指针式时钟显示一致;按任意键时程序退出。

第二章 课程设计的任务内容

要熟练掌握C语言的基本知识:数据类型(整形、实型、字符型、指针、数组、结构等);运算类型(算术运算、逻辑运算、自增自减运算、赋值运算等);程序结构(顺序结构、判断选择结构、循环结构);大程序的功能分解方法(即函数的使用)等。用C语言实现一个模拟时钟转动程序。

提出总体方案的设计思想和原理,绘制程序流程图和描述程序的功能,并说明程序的特点和难点。

能模拟机械钟表行走;要准确地利用数字显示日期和时间;在屏幕上显示一个活动时钟;程序界面设计合理,色彩得体大方,显示正确;各指针运动规律正确;数字式时钟的时间显示与指针式时钟显示一致;按任意键时程序退出。

模拟时钟是一种集计时器和时钟显示于一体的程序。编写一个指针式时钟程序,此程序在屏幕正中有一个指针式钟面,窗口标题以数字方式显示日期和时间。指针式的时钟表盘为椭圆形或圆形,并且圆周上有分布均匀的12个刻度,刻度要求显示清楚,钟面上有长度不相同的指针,即时针、分针、秒针,指针的运动要求具有规律性,且为顺时针。数字钟显示时间的格式是年月日时分秒,小时为24进制,分钟和秒是60进制,指针式的时钟和数字式的时钟显示的时间同步,且两个时钟所显示的时间与计算机的系统时间一致。

第三章 详细设计说明

3.1  程序系统的结构

图3.1 功能模块图

3.2  模块描述

3.2.1  指针式时钟

指针式的时钟表盘为椭圆形,并且圆周上有分布均匀的12个刻度,刻度显示清楚,钟面上有长度不相同的指针,即时针、分针、秒针,指针的运动具有规律性,为顺时针。

3.2.2  数字式时钟

数字钟显示时间的格式是年月日时分秒,小时为24进制,分钟和秒是60进制,指针式的时钟和数字式的时钟显示的时间同步,且两个时钟所显示的时间与计算机的系统时间一致。窗口标题为数字钟。

3.3  输出项

数字式时钟输出“%d年%d月%d日%d时%d分%d秒”。

3.4  算法

不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。计算指针端点(x, y)的公式如下:x =圆心x坐标   指针长度 * cos (指针方向角)y =圆心y坐标   指针长度 * sin (指针方向角)注重,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可以跨越圆心,因此一个指针需要计算两个端点。三个指针的运动是相关联的,秒针转一圈引起分针运动一格,分针转一圈引起时针运动一格,因此应该使用一个定时器消息来处理指针的运动。

3.5  流程图

图3.2 程序流程图

3.6  函数说明

1.OnDraw()函数实现对系统时间的获取和绘制椭圆表面和时钟指针。

2.设置计时器,创建窗口时启动一个计时器不断发出WM_TIMER消息,调用SetTimer()函数。

3.用TextOut()函数显示数字钟。

画模拟时钟最重要的大约就是三角函数了。手机和电脑的默认坐标系都是原点在左上角。这样,我们确定了圆心位置后,就确定了表的位置,表针,表盘的位置坐标都在以圆心为中心的圆环上。其坐标可以通过三解函数推导出来。设圆心为(X,Y),半径为R,表上其他点的坐标为(X1,Y1),该点与圆心X轴夹角为A,大致可以推出该点坐标公式:

位于圆心右上角点的公式为:X1 = X + RcosA;Y1 = Y - RsinA;

位于圆心左上角点的公式为:X1 = X - RcosA;Y1 = Y - RsinA;

位于圆心左下角的公式为:X1 = X - RcosA;Y1 = Y + RsinA;

位于圆心右下角的公式为:X1 = X + RcosA;Y1 = Y + RsinA;

如果+ -使用角度来校正,公式就可以统一为X1 = X + RcosA;Y1 = Y + RsinA;

由于表是顺时针转动,我们的角度习惯上使用逆时针,所以我们使用自己校正后的角度值,从12点开始,按顺时针重新排列三角函数值,加入对角度正负的校正。

首先定义一些时钟常用的宏:

#define ANALOG_CENTER_X (227)          //时钟显示的中心位置的横坐标 227

#define ANALOG_CENTER_Y (178)          //时钟显示的中心位置的纵坐标 178

#define ANALOG_R (150)                             //时钟显示图的半径 150

#define ANALOG_CENTER_R (10)                //时钟显示中心图形的半径 10

#define ANALOG_HOUR_LEN (ANALOG_R-80)           //时针长短(半径)70

#define ANALOG_MINUTE_LEN (ANALOG_R-50)        //分针长短(半径)100

#define ANALOG_SECOND_LEN (ANALOG_R-30)        //秒针长短(半径)120

3.7  接口

1.<windows.h>是主要的头文件,它包含了其他Windows头文件。

2.<math.h>数学函数库,一些数学计算的公式的具体实现是放在math.h里。

3.8  调试结果

图3.3 运行结果

第四章 软件使用说明

4.1  软件使用说明及出现的问题

在vc++6.0中新建一个win32 application 项目, 然后新建一个C++文件 输入代码。运行后显示一个正在行走的机械时钟。将数字日期显示为窗口标题。按任意键退出。

4.2  运行结果

图4.1 运行结果

第五章 课程设计心得与体会

经过一个学期对《C++课程设计》的学习,我们学习了理论知识,了解了C++语言程序设计的思想,这些知识都为我们的下一步学习打下了坚实的基础。通过课程设计,一方面是为了检查我们一个学期来我们学习的成果,另一方面也是为了让我们进一步的掌握和运用它,同时也让我们认清自己的不足之处和薄弱环节,加以弥补和加强。通过对模拟时钟的设计进一步的巩固了用C++编写程序,并且有利于更好的掌握程序设计语言!

在模拟时钟的编写过程中也体会到了做事情一顶要细心、认真。更加知道了要掌握好基础知识。还有体会到了成功的感觉!

    通过本项课程设计也培养了我独立思考、 综合运用所学有关相应知识的能力,掌握工程软件设计的基本方法,强化上机动手编程能力,闯过理论与实践相结合的难关!

由于程序设计语言是近年在国内外得到迅速推广应用的一种语言。它功能丰富,表达能力强,使用灵活方便,应用面广,目标程序效率高,可移植性好,既具有高级语言的优点,又具有低级语言的许多特点。通过这次的程序设计更加了解了语言设计的好处和其可用性!

在这次课程设计中也知道了自己的动手能力不强有待进一部的提高!在设计过程中不能够把书本上的知识与实践相结合,这也就增加了设计不好该程序的想法!在设计过程中的一次次设计错误增加了我放弃的想法!不过经过自己的独立思考和同学的帮助终于完成了课程设计!完成该程序后想起自己以前的每一次对自己失去信心,就觉得并不是在知识掌握上打败了,而是自己对自己缺乏信心!只要自己对自己不失去信心相信就可以完成那些以前认为完成不了的事情!也让我懂得了要想成功首先就必须有很强的自信心!懂得了自己以后要在做任何事情时都要自信!当自己都不相信自己能够成功时还可能会获得成功吗?

在课程设计的过程中也知道了自己在以前的学习中有很大的不足导致在设计过程中出现了很多的问题,有些地方看不懂也不知道怎么去设计,但是在设计过程中也学习了很多,掌握了自己以前没有学好的知识,虽然一时可以掌握完以前没有学好的知识,不过也给自己敲响了警钟,在学习中不可以伏于表面,要想学好每一门课程都要踏踏实实,做什么都不是给别人看的!都是要更好的掌握该门知识,提高自己的自身的修养,提高自己的能力!为以后的工作打下良好的知识基础和技能基础!

附录1:参考文献

[1]、田淑清, C语言程序设计,北京:高等教育出版社,20##年1月

[2]、David J.Kruglinski,Scot Wingo,George Shepherd,Visual C++6.0技术内幕(第五版),希望图书室译,北京:北京希望电子出版社,2001 年1月

附录2:程序清单

#include<windows.h>

#include<math.h>

#define TWOPI (2*3.14159)

#define IDTIMER 1

#define ANGLE TWOPI/360

LRESULT CALLBACK WindowProc(

    HWND hwnd,

    UINT uMsg,

    WPARAM wParam,

    LPARAM lParam

);

int WINAPI WinMain(

    HINSTANCE hInstance,

    HINSTANCE hPrevInstance,

    LPSTR lpCmdLine,

    int nCmdShow

)

{

 TCHAR szClassName[] = TEXT("analogCloc");

 MSG msg;

 HWND hwnd;

 WNDCLASS wndclass;

 wndclass.cbClsExtra = 0;

 wndclass.cbWndExtra = 0;

 wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);

 wndclass.hCursor = NULL;

 wndclass.hIcon = NULL;

 wndclass.hInstance = hInstance;

 wndclass.lpfnWndProc = WindowProc;

 wndclass.lpszClassName = szClassName;

 wndclass.lpszMenuName = NULL;

 wndclass.style = CS_HREDRAW | CS_VREDRAW ;

 ::RegisterClass(&wndclass);

 hwnd = ::CreateWindow(szClassName,TEXT("Clock"),WS_OVERLAPPEDWINDOW,

   CW_USEDEFAULT,CW_USEDEFAULT,

            CW_USEDEFAULT,CW_USEDEFAULT,

   NULL, NULL, hInstance, NULL);

 ::ShowWindow(hwnd,nCmdShow);

     ::UpdateWindow(hwnd);

 while(::GetMessage(&msg,NULL,0,0))

 {

  ::TranslateMessage(&msg);

  ::DispatchMessage(&msg);

 }

 return msg.wParam;

}

void setISOTROPIC(HDC hdc,int cxClient,int cyClient)//设置映射模式,使之成为笛卡尔坐标系的映射模式

{

 ::SetMapMode(hdc,MM_ISOTROPIC);

 ::SetWindowExtEx(hdc,1000,1000,NULL);   // 逻辑单位与设备单位比1/2

 ::SetViewportExtEx(hdc,cxClient/2,-cyClient/2,NULL);

 ::SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);     // 竖坐标向上为正,下为负

}

void drawClock(HDC hdc)

{

 int x, y, radius;  

 ::SelectObject(hdc,::CreateSolidBrush(RGB(1,148,138)));

 for(int i=0;i<360;i+=6)

 {

  x = (int)(cos(TWOPI/360*i)*900);

  y = (int)(sin(TWOPI/360*i)*900);

  radius = !(i%5)?40:10;

  Ellipse(hdc,x-radius,y-radius,x+radius,y+radius);

 }

}

void drawHands(HDC hdc,SYSTEMTIME *pst,BOOL hChange)

{

 int radius[3] = {500,700,850};

 int angle[3]; 

 angle[0] = pst->wHour*30+pst->wMinute/12*6;   

 angle[1] = pst->wMinute*6;

 angle[2] = pst->wSecond*6;

 for(int i=hChange?0:2;i<3;i++)

 {

  MoveToEx(hdc,0,0,NULL);

  LineTo(hdc,(int)(radius[i]*cos(ANGLE*(90-angle[i]))),

         (int)(radius[i]*sin(ANGLE*(90-angle[i]))));

 }

}

LRESULT CALLBACK WindowProc(

    HWND hwnd,  

    UINT message,

    WPARAM wParam,

    LPARAM lParam 

)

{

 TCHAR time[40];

 PAINTSTRUCT ps;

 HDC hdc;

 static int cxClient, cyClient;

 SYSTEMTIME st;

 static SYSTEMTIME preSt;

 BOOL hChange;

 switch(message)

 {

  case WM_CREATE:

  ::SetTimer(hwnd,IDTIMER,1000,NULL);

  ::GetLocalTime(&st);

  wsprintf(time,TEXT("%d年%d月%d日%d时%d分%d秒"),

       st.wYear,

       st.wMonth,

       st.wDay,

       st.wHour,

       st.wMinute,

       st.wSecond);

  SetWindowText(hwnd,time);

  preSt = st;

  return 0;

     case WM_SIZE:

  cxClient = LOWORD(lParam);

  cyClient = HIWORD(lParam);

  return 0;

  case WM_TIMER:

  ::GetLocalTime(&st);  //每次都要获取当前时间

  hChange = st.wHour!=preSt.wHour||st.wMinute!=preSt.wMinute;

  hdc = GetDC(hwnd);

  setISOTROPIC(hdc,cxClient,cyClient);

  ::SelectObject(hdc,::GetStockObject(WHITE_PEN));

  drawHands(hdc,&preSt,hChange);

  ::SelectObject(hdc,::GetStockObject(BLACK_PEN));

  drawHands(hdc,&st,TRUE);

  ReleaseDC(hwnd,hdc);

  wsprintf(time,TEXT("%d年%d月%d日%d时%d分%d秒"),

       st.wYear,

       st.wMonth,

       st.wDay,

       st.wHour,

       st.wMinute,

       st.wSecond);

  SetWindowText(hwnd,time);

  preSt = st;          // 更新完毕后记录前一次的状态

  return 0;

  case WM_KEYDOWN:

  case WM_CHAR:

  ::DestroyWindow(hwnd);

  return 0;

  case WM_PAINT:

  hdc = ::BeginPaint(hwnd,&ps);

  setISOTROPIC(hdc,cxClient,cyClient);

  drawClock(hdc);

  drawHands(hdc,&preSt,TRUE); 

  ::EndPaint(hwnd,&ps);

  return 0;

  case WM_DESTROY:

  ::PostQuitMessage(0);

  return 0;

 }

 return DefWindowProc(hwnd,message,wParam,lParam);

}

相关推荐