Archive for the ‘在键盘上冥想’ Category
最近的计划
一直以来就想用.NET做中间件。已经完成的是一个小型应用程序框架,可以减轻很多做程序的工作。当然,第一个版本(我现在还只是觉得是一个雏形, 所以版本也都还是内部测试)主要关注的是数据库操作和配置文件操作,用户安全和异常处理都只是有所涉及。关于这个框架,我下面还有很多想法,当然也要去借 鉴现在比较成熟的一些东西,比如DotNetNuke和NHibernate之类的东西。
最近的计划是做一个页面引擎。所谓页面引擎就是说网页完全又模版生成,可以实现页面样式与逻辑层的完全分离。当然,这也不是什么新鲜的东西了。我做这个目的还是简单为好。初步的想法是先完全兼容DotNetNuke的模版格式。
用.NET做应用的确方便,但是我现在也很难判断自己做的这些东西的价值。也全当做是一种学习罢了。
为什么微软?
昨天我又买了《MSDN开发精选》。这个杂志从它创刊到现在,我每一期都买。虽然我每一期都在等待有什么特别重要或者说是特别有价值的东西,但是事实是每一期的立意都是相同的,那就是全力去介绍根本还没有推出的微软技术。
没 有推出的微软技术。关于这一点,我觉得还是可以理解的。如果开发者在产品推出之前就已经很依赖或者是非常喜爱你的产品,那么他肯定就要购买你的产品了,这 一点是毫无疑问的。但是,对于一个杂志来说,我们最希望得到什么东西?那肯定是最大程度上能够获取对现在开发有帮助的东西。当然,这一点说的有一点偏激 了。可是,当我看到满篇介绍Visual Studio Team System的时候,我真的有一点愤怒。如果这个软件真的那么好,我也非常想用,但是,现在,就是不能用,以后要用,也得付出高额的代价。那么,这些介绍 的文章是不是一种变相的广告呢?
我承认,我平时都是用微软的软件。我也承认,微软的产品不管是技术还是性能上都是一流的。但是,我还是想说,我不希望别人来教我评判事物的标准。
然而,事情就是那么矛盾。我已经安装了Visual Studio 2005 Feb CTP。对于一个开发工具来说,每一个测试版都能引起如此的轰动,我看,也只有微软能够这样了。
另:我昨天还买了一本《计算几何》。
Macromedia梦
Adobe收购Macromedia。一个在业界并没有引起太多波澜的收购。既没有什么大的战略意义,也没有巨额资金的引诱。38亿美元,对于IT业的收购来说,数目并不是巨大的。
现 在就说这样打造了平面设计的旗舰还为时尚早,虽然这两家公司在已经拥有的领域里都已经举足轻重。Macromedia一直都想往企业级网站架构转 型,Flex就是一个很好的例证。Adobe也非常需要动画制作软件和网页设计软件来为它的Photoshop打开更广阔的天空。这一次,大家似乎都有了 一定的收获。
强强联手?
但愿是吧。
与老师探讨问题
彭老师:
又来麻烦您了,上次您给我说了关于“约瑟夫问题”的程序以后,我开始注意自己的程序结构的合理性安排。两次上机作业“多项式操作”和“表达式计算”都做好了,这些天终于把“银行的模拟”做好了,请老师看看。我下面大体说一下程序的思路。
首先,我当然用到了“队列”,因为这个程序是“队列”的应用嘛。我使用了2种队列,分别装“刚进入银行的人”和“在某个队上排队的人”,在程序里面是BankIndoor和BankQueue。关于事件的驱动,我思考了很久,最终我采用了一个存放“函数指针”的链表:
1 2 3 4 5 6 | typedef struct MethodStruct { METHODCALLBACK (*todo)(); METHODSTATE state; MethodStruct *next; }MethodNode; |
把 每一次要触发的事件都存在这个链表里面,而每一个基本时间段里,都由EnumerateAllMethod()这个函数通过遍历链表来达到出发所有事件的 作用。EnumerateAllMethod通过这个链表每一个节点的state值来判断当前是否激发这个事件。通过这个方法就很容易随机地产生顾客。比 如CustomerArrival()这个函数,每次都产生一个随机数,用于EnumerateAllMethod()判断下一次调用它的时间。关于这种 思路,其实我是参考了Windows的消息触发机制。
在这个事件的链表里面,有三个很重要的事件是CustomerArrival()、 CustomerQueue()、CustomerTODO()。分别处理顾客到来,顾客分队,顾客办理事务这三个事件。这三个函数互相不影响。都由 EnumerateAllMethod统一调用,并且各自监视各自的队列。
最后要说的是关于银行关门的处理,银行到达运营时间的时候产生 READYFORCLOSED的标识,这个时候CustomerArrival()就不触发了,而只触发CustomerQueue()、 CustomerTODO()。当CustomerTODO()检查到所有队列都没有顾客了的时候,就把银行标识改为CLOSED,这样就解决了这个问 题。
通过这次练习,我学到了很多东西,不过也萌发了用C语言来实现事件机制的想法,呵呵,但是我还是觉得有一些难。
程序在Visual C++.NET 2003和Dev-C++下均调试通过。程序运行时间为30秒(可以通过修改#define CLOSETIME 30来进行更改)。
源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | #include <stdio.h> #include <time.h> #include <stdlib.h> //**************************************** #define WAIT_INDOOR 1 #define WAIT_QUEUE 2 #define QUEUES 5 #define FAILED 0 #define SUCCEEDED 1 #define OPEN 1 #define CLOSED 0 #define READYFORCLOSED 2 #define OVERFLOW 2 #define CLOSETIME 30 #define MINTIMEARRIVAL 2 #define MINTIMETODO 10 typedef int EVENTTYPE; typedef int METHODSTATE; typedef int METHODCALLBACK; typedef long SYSTEMTIME; typedef int STATUS; typedef int BANKSTATE; typedef int CustomerID; //**************************************** typedef struct EventStruct { EVENTTYPE detail; SYSTEMTIME occurtime; CustomerID ID; }EventNode; typedef EventNode *Event; typedef struct QueueStruct { EventNode item; QueueStruct *next; }QueueNode; typedef QueueNode *QueuePtr; typedef struct{ QueuePtr front; QueuePtr rear; }LinkQueue; typedef struct CustomerStruct { SYSTEMTIME arrivaltime; SYSTEMTIME duration; }CustomerNode; typedef struct MethodStruct { METHODCALLBACK (*todo)(); METHODSTATE state; MethodStruct *next; }MethodNode; typedef MethodNode *MethodLink; //***************************************** LinkQueue BankIndoor; LinkQueue BankQueue[QUEUES]; MethodLink Methods; SYSTEMTIME BankClock; BANKSTATE BankState; time_t StartTime,EndTime; CustomerID IDSeed; //***************************************** STATUS InitQueue(LinkQueue &Q) { Q.front=Q.rear=new QueueNode; if (!Q.front) exit(OVERFLOW); Q.front->next=NULL; return SUCCEEDED; } STATUS DestroyQueue(LinkQueue &Q) { while(Q.front) { Q.rear=Q.front->next; delete Q.front; Q.front=Q.rear; } return SUCCEEDED; } STATUS EnQueue(LinkQueue &Q,Event e) { QueuePtr p; p=new QueueNode; if (!p) exit(OVERFLOW); p->item=*e;p->next=NULL; Q.rear->next=p; Q.rear=p; return SUCCEEDED; } STATUS DeQueue(LinkQueue &Q,Event &e) { QueuePtr p; if(Q.front==Q.rear) return FAILED; p=Q.front->next; *e=p->item; Q.front->next=p->next; if (Q.rear==p) Q.rear=Q.front; delete p; return SUCCEEDED; } int QueueLength(LinkQueue Q) { int numbers=0; while(Q.front!=Q.rear) { Q.front=Q.front->next; numbers++; } return numbers; } int PlaceCustomer() { int min=0; for (int i=0;i<QUEUES;i++) { if(QueueLength(BankQueue[i])<=QueueLength(BankQueue[min])) min=i; } return min; } //***************************************** METHODCALLBACK CustomerArrival() { SYSTEMTIME nexttime; Event node; if (BankState==READYFORCLOSED) return 32767; node=new EventNode; node->detail=WAIT_INDOOR; node->occurtime=BankClock; node->ID=IDSeed++; srand((unsigned)time(0)); nexttime=rand()%MINTIMEARRIVAL; EnQueue(BankIndoor,node); printf("Customer %d arrived in %d\n",node->ID,BankClock); delete node; return nexttime; } METHODCALLBACK CustomerQueue() { Event node; int nexttime; node=new EventNode; if (DeQueue(BankIndoor,node)!=FAILED) { node->detail=WAIT_QUEUE; srand((unsigned)time(0)); nexttime=rand()%MINTIMETODO+1; node->occurtime=nexttime; printf("Customer %d placed in queue %d(%d)\n",node->ID,PlaceCustomer(),nexttime); EnQueue(BankQueue[PlaceCustomer()],node); } delete node; return 0; } METHODCALLBACK CustomerTODO() { Event node; int counter=0; node=new EventNode; for (int i=0;i<QUEUES;i++) { if (DeQueue(BankQueue[i],node)!=FAILED) { //printf("%d\n",node->occurtime); if (node->occurtime<=0) { printf("Customer %d has left from queue %d\n",node->ID,i); } else { node->occurtime--; EnQueue(BankQueue[i],node); } counter++; } } delete node; if (counter==0&&BankState==READYFORCLOSED) BankState=CLOSED; return 0; } //判断是否到了停止营业的时间 METHODCALLBACK CheckForClose() { if(BankClock==CLOSETIME) { BankState=READYFORCLOSED; printf("The bank is ready for close.\n"); } return 0; } //时钟 METHODCALLBACK Clock() { BankClock++; return 0; } //**************************************** STATUS InitMethods() { if (Methods==NULL) { Methods=new MethodNode; Methods->state=0; Methods->next=NULL; Methods->todo=Clock; return SUCCEEDED; } else return FAILED; } STATUS RegisterMethod(METHODCALLBACK (*m)()) { MethodLink pointer; MethodLink node; pointer=Methods; while(pointer->next!=NULL) pointer=pointer->next; node=new MethodNode; if (node==NULL) return FAILED; node->state=0; node->next=NULL; node->todo=m; pointer->next=node; return SUCCEEDED; } STATUS RegisterAllMethod() { RegisterMethod(CheckForClose); RegisterMethod(CustomerArrival); RegisterMethod(CustomerQueue); RegisterMethod(CustomerTODO); return SUCCEEDED; } STATUS DeleteAllMethod() { MethodLink pointer; MethodLink node; pointer=Methods; while(pointer->next!=NULL) { node=pointer; pointer=pointer->next; delete node; } return SUCCEEDED; } STATUS EnumerateAllMethod() { MethodLink pointer; pointer=Methods; time(&EndTime); if (difftime(EndTime,StartTime)>=1.0) { time(&StartTime); while(pointer!=NULL) { if(pointer->state==0) pointer->state=pointer->todo(); else pointer->state--; pointer=pointer->next; } } return SUCCEEDED; } STATUS OpenForTheDay() { BankClock=0; BankState=OPEN; IDSeed=0; //********************** InitMethods(); RegisterAllMethod(); InitQueue(BankIndoor); for (int i=0;i<QUEUES;i++) InitQueue(BankQueue[i]); time(&StartTime); printf("The bank is open.\n"); return SUCCEEDED; } STATUS CloseForTheDay() { DestroyQueue(BankIndoor); for(int i=0;i<QUEUES;i++) DestroyQueue(BankQueue[i]); DeleteAllMethod(); printf("The bank is closed.\n"); return SUCCEEDED; } //***************************************** int main() { OpenForTheDay(); while(BankState!=CLOSED) { EnumerateAllMethod(); } CloseForTheDay(); system("PAUSE"); return 0; } |
什么才是我们需要的?
用户需要什么?
对于普通用户来说,美丽的界面、易用的操作和强大的功能才是真正的上帝!而架构、模式、API都是他们所不想关心,也没办法 关心的。我们现在很多问题都在了架构上,都在了具体的编程上,但是我们产品的用户体验实在是差。我们的操作实在是不简便。这一点上我们应该好好学习微软。 的确,微软很多软件不是功能最强大的,但一定是最好用的。
想到这里,我个人还是十分看好未来几年的Web applications。网络应用不仅仅是网站,而是全新的架构,全新的用户体验。我们应该做的是,打开思路。
他们的肖邦
你听的最多的肖邦的唱片都是谁演奏的?
波利尼?齐默尔曼?还是阿格丽姬的?是的,名家的肖邦实在是太多了。不管是冷峻的,还是热情的,抑或是有些人所谓的“肖邦化”的演奏,总之我们能够听到无数的著名的演奏家著名的版本。可事实上,在现代唱片工业时代,有才华的演奏却不一定能够传到我们音乐爱好者的耳朵里。我就很偶然聆听到了这样一个让我眼睛一亮的“肖邦”。
要说演奏得奇怪,波格雷利奇的肖邦无疑是最奇怪的,但也是最具效果的。不过钢琴家弗莱迪 肯佩夫的肖邦才真正有一种冷峻和古怪的美。说实话,这是一种真正现代意义上的演奏,有力度,有棱角,绝没有那种拖泥带水。而另一位钢琴家罗兰 彭蒂宁则出奇得将《船歌》充分演绎。老实说我听过很多版本的《船歌》,但是都有一个问题,那就是浪漫不足。为什么这么讲呢?因为肖邦的《船歌》众所周知是一部充满了浪漫气息的爱情篇章。很难得有人能够把这首曲子演奏得既典雅又富有青春的爱。彭蒂宁做到了,而且每个细节都安排得恰当而又不失分寸。当然,这些钢琴家的肖邦并不能做到每一首都能够演奏得具有说服力。这也是很正常的,我想大家和普通钢琴家的区别就在这里吧。
但事实也是告诉我们,音乐没有权威。每个人都能够体会到属于他那份特有的情感。
贪吃蛇进度(1)
现在实现了计时器机制和事件机制。下一步是怎么去实现贪吃蛇的走动。
现在分为两个文件:snake.h和snake.c
如下:snake.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | #define NEWEVENT (EventLink)malloc(sizeof(event)) #define MAXSNAKELEN 30 /* Max length of the snake */ #define DEFAULTSNAKECOLOR WHITE /* The default snake color */ #define DEFAULTSPEED 100000 /* The start speed of the snake */ #define DEFAULTSTARTX 100 /* The start x of the snake */ #define DEFAULTSTARTY 100 /* The start y of the snake */ #define MAXEVENT 1 /* The startup event number */ /* Keyboard definition */ #define ENTER 13 /* The prototype of bool type */ typedef enum { true, false } bool; /* The prototype of directions */ typedef enum { up, right, down, left } direction; /* The prototype of a point of the snake */ typedef struct { int posx; int posy; direction dir; /* The current direction of this point */ } point; /* The prototype of the snake */ typedef struct { point dots[MAXSNAKELEN]; } snake; #ifndef __SNAKE /* prevent multiple includes */ #define __SNAKE /* The prototype of the event */ typedef struct { long interval; /* The interval of the event occurs */ long timer; void (*invoke)(); /* The function pointer to the invoke action */ } event; /* The prototype of the eventlist */ struct eventlist { event *eventnow; struct eventlist *next; }; typedef struct eventlist Node; typedef Node *Link; typedef event *EventLink; int screenx = 0; int screeny = 0; void Init(snake *s); void EventHandler(Link); void EventInsert(Link, EventLink); Link EventCreater(Link); void EventFree(Link); /* Registry Events */ void Controler(); /* The main keyboard controler */ void DrawPoint(); void DrawLine(); void DrawSnake(snake *s); void EventInsert(Link eventhead, EventLink newevent) { Link pointer; Link newlist; pointer = eventhead; while (1) { if (pointer->next == NULL) { newlist = (Link) malloc(sizeof (Node)); newlist->eventnow = newevent; newlist->next = NULL; pointer->next = newlist; break; } pointer = pointer->next; } } Link EventCreater(Link eventhead) { Link newevent; EventLink tempevent; int i; eventhead = (Link) malloc(sizeof (Node)); /* Create event list */ if (eventhead == NULL) { printf("Memory allocate Failure!!\n"); } else { tempevent = (EventLink) malloc(sizeof (event)); tempevent->interval = 1; tempevent->timer = 0; tempevent->invoke = Controler; eventhead->eventnow = tempevent; eventhead->next = NULL; } return eventhead; } void EventFree(Link eventhead) { Link pointer; EventLink tempevent; while (eventhead != NULL) { pointer = eventhead; eventhead = eventhead->next; tempevent = eventhead->eventnow; free(pointer); free(tempevent); } } #endif |
Snake.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <graphics.h> #include <dos.h> #include <snake.h> /* To return the head pointer of the eventlist */ int main(void) { snake me; Link head; int gdriver = DETECT, gmode; EventLink tempevent; /* Init graphic mode */ initgraph(&gdriver, &gmode, ""); Init(&me); head = EventCreater(head); tempevent = NEWEVENT; tempevent->interval = 10000; tempevent->timer = 0; tempevent->invoke = DrawPoint; EventInsert(head, tempevent); EventHandler(head); EventFree(head); closegraph(); clrscr(); return 0; } void DrawLine() { int x; int y; x = random(500); y = random(500); circle(x, y, 20); } void DrawPoint() { int x1, x2; int y1, y2; x1 = random(200); x2 = random(100); y1 = random(200); y2 = random(100); line(x1, y1, x2, y2); } void Controler() { } void Init(snake *s) { int i, j; int sx = DEFAULTSTARTX, sy = DEFAULTSTARTY; randomize(); for (i = 0; i < MAXSNAKELEN; i++) { s->dots[i].posx = sx; s->dots[i].posy = sy; s->dots[i].dir = up; sy++; } screenx = getmaxx(); screeny = getmaxy(); } /* Draw snake */ void DrawSnake(snake *s) { int i; for (i = 0; i < MAXSNAKELEN; i++) { putpixel(s->dots[i].posx, s->dots[i].posy, DEFAULTSNAKECOLOR); } } void EventHandler(Link eventhead) { int i; Link pointer; while (1) { delay(1); pointer = eventhead; while (pointer != NULL) { pointer->eventnow->timer++; if ((pointer->eventnow->timer) >= (pointer->eventnow->interval)) { /* Invoke current event */ pointer->eventnow->invoke(); pointer->eventnow->timer = 0; } pointer = pointer->next; } if (kbhit()) { if (getch() == ENTER) break; } } } |
解决了动态加载的问题
果然,在网上查了一些资料以后,终于动态加载了dll并且调用了里面的方法。其实搞懂了以后还是很简单的。具体实现的代码如下:
1 2 3 4 5 6 7 8 9 | Assembly ass; ass=Assembly.LoadFrom(Server.MapPath("")+"\\bin\\kernel.dll"); Type myType=ass.GetType("Kernel.DbControl"); MethodInfo mi=myType.GetMethod("ViewAllData"); Object[] arg=new object[1]; arg[0]=Server.MapPath(""); Object obj = Activator.CreateInstance(myType,arg); Test.DataSource=(DataSet)mi.Invoke(obj,null); Test.DataBind(); |
首先要把dll加载进来。然后得到特定的类名。再就是得到这个类里里面某个方法。最重要的一句就是:Object obj = Activator.CreateInstance(myType,arg); 这句的作用就是使这个类实例化。注意,实例化可以带上参数(这要看构造函数是什么样子的)。实例化了类以后就是调用方法,也和实例化类一样,要有参数的传递。当然,最好强制转换一下类型。
开始工作
今天正式开始工作了。应该说,两个人在一起的效率的确很高,至少要比一个人要高很多。第一天还是有一些收获的。比如先是做了一个dll,然后把数据库操作封装到了这个dll里面。再在一个web application里面调用这个dll。这个做的还是很成功的。中间有一个小问题就是,在dll里面,如何得到当前的工作路径。没有解决!只有从web application里面把这个路径传过去。当然这也是一种折中的方法。然后开始试验动态载入程序集。应该说,动态载入本身是没有难度的,关键是如何运行类里面的方法。这个就不是那么容易了。试验了很多,都不行。在网上查了一下,发现有很多类似的问题被大家都讨论过了。看看明天能不能解决这个问题。
C语言的问题
昨天把下雨的题终于编完了。对Graphics.h里面的一些函数有了一个初步的了解。我觉得我设计的这个程序是一种多线程的程序的雏形,因为两个雨滴是相互独立的,互不影响。这是放在一个数组里面实现的。目前的问题是如果把间隔时间设置的相对短些的话,动画要光滑些,但是有闪烁的感觉。这也是所有编程语言的擦坪函数所带来的,怎么解决,确实是一个问题。
附上源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #include <stdio.h> #include <math.h> #include <graphics.h> #include <stdlib.h> #include <time.h> #include <dos.h> #include <conio.h> #define PI 3.1415926 #define RAINDROPLEN 15 /* The length of a raindrop */ #define RAINTANGLE 0 /* The tangle of each raindrop */ #define RAINDROPZ 0 /* The internal of each raindrop */ #define RAINCOLOR white /* The color of each raindrop */ #define RAINWAVELEVEL 40 /* The level of each wave */ #define DELAYTIME 2000 /* The internal of each flash of the screen */ /* Calculate the next X,Y of a raindrop */ #define RAINDROPNEXTX(n,m) (int)((RAINDROPLEN/m+n)*sin(RAINTANGLE*(PI/180))) #define RAINDROPNEXTY(n,m) (int)((RAINDROPLEN/m+n)*cos(RAINTANGLE*(PI/180))) #define RAINDROPS 100 /* The total numbers of raindrops */ struct raindrop { int posx; int posy; int state; /* The current state of raindrop. 1 for raindrop. 2 for wave. */ int wavelevel; /* The current wave level */ }; void Init(struct raindrop *drops); void DrawDrops(struct raindrop *drops); /* Draw all the raindrops */ void CalDrops(struct raindrop *drops); /* Calculate the next raindrops position */ int main(void) { struct raindrop drops[RAINDROPS]; int gdriver=DETECT,gmode,i=0; initgraph(&gdriver,&gmode,""); /* Init graphic mode */ Init(drops); setbkcolor(0); while(!kbhit()) { cleardevice(); DrawDrops(drops); delay(DELAYTIME); CalDrops(drops); } return 0; } void Init(struct raindrop *drops) { int i; randomize(); for(i=0;i<RAINDROPS;i++,drops++) { drops->posx=random(600); drops->posy=random(300); drops->state=1; drops->wavelevel=0; } } void DrawDrops(struct raindrop *drops) { int i; int endx,endy; setcolor(WHITE); for(i=0;i<RAINDROPS;i++,drops++) { if (drops->state==1) { endx=RAINDROPNEXTX(0,1); endy=RAINDROPNEXTY(0,1); line(drops->posx,drops->posy,drops->posx+endx,drops->posy+endy); } else { ellipse(drops->posx,drops->posy,0,360,1+(drops->wavelevel)*0.75,0.05+(drops->wavelevel)*0.15); } } } void CalDrops(struct raindrop *drops) { int i; int endx,endy; int temp; for(i=0;i<RAINDROPS;i++,drops++) { if (drops->state==1) { endx=RAINDROPNEXTX(RAINDROPZ,10); endy=RAINDROPNEXTY(RAINDROPZ,10); if ((endx+drops->posx)>=640||(endy+drops->posy)>=400) { temp=random(100); if (temp%2==0||(endx+drops->posx)>=680||(endy+drops->posy)>=550) { drops->state=2; drops->wavelevel=1; } else { drops->posx=drops->posx+endx; drops->posy=drops->posy+endy; } } else { drops->posx=drops->posx+endx; drops->posy=drops->posy+endy; } } else { if ((drops->wavelevel)<RAINWAVELEVEL) { drops->wavelevel++; } else { drops->posx=random(600); drops->posy=random(100); drops->wavelevel=0; drops->state=1; } } } |
近期评论