//***********************************************************
版本04
程序功能:实现两个球的随机运动
显示方式:实时打印球的坐标和速度
增加内容:软件延时代码
修改说明:利用随机数函数创建一个双精度比率,来设置ySpeed用以控制小球的运动方向
说明 :该程序仅在一个球的基础上增加一个球,然后对输出做一下修改
//***********************************************************
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
Int main()
{
//定义边框的宽
Int TableWidth = 100;
//定义边框的高
int TableHight = 100;
//定义球的尺寸
int BallSize = 10;
//定义球纵坐标的速度
Int ySpeed01 = 5;
Int ySpeed02 = 5;
//使用time(0)作为随机数种子
Srand((int) time(0));
//定义球横坐标的速度
//这里用到了drand48()函数,用以产生一个正的浮点随机数
Int xSpeed01 =(int) ySpeed01*(drand48()-0.5)*2;
Int xSpeed02 = (int)ySpeed02*(drand48()-0.5)*2;
//定义球的横坐标
Int BallX01 = 1+(int)(20.0*rand()/(RAND_MAX+1.0));
Int BallX02 = 50+(int)(20.0*rand()/(RAND_MAX+1.0));
//定义球的纵坐标
Int BallY01= 50+(int)(20.0*rand()/(RAND_MAX+1.0));
Int BallY02= 1+(int)(20.0*rand()/(RAND_MAX+1.0));
Unsigned Int t;
Unsigned int flag =0;
While(1){
for(t=0;t<600000000;t++);//软件延时
if(((BallX01-BallX02)*(Ball01-BallX02)+(BallY01-BallY02)*(BallY01-BallY02)<400))
{
xSpeed01 = -xSpeed01;
ySpeed01=-ySpeed01;
xSpeed02 =-xSpeed02;
ySpeed02 =-ySpeed02;
flag++;
}
else
{
If(BallX01<0|| BallX01 >= TableWidth - BallSize)
xSpeed01 =-xSpeed01;
if(BallY01<0|| BallX01 >=TableHight - BallSize)
ySpeed01 = -ySpeed01;
If(BallX02<0|| BallX02 >= TableWidth - BallSize)
xSpeed02 =-xSpeed02;
if(BallY02<0|| BallX02 >=TableHight - BallSize)
ySpeed02 = -ySpeed02;
}
BallX01 +=xSpeed01;
BallY01+=ySpeed01;
BallX02 +=xSpeed02;
BallY02+=ySpeed02;
Printf(“Thestate of Ball01 is %d,%d,%d,%d\n”,BallX01,BallY01,xSpeed01,ySpeed01);
Printf(“Thestate of Ball02 is %d,%d,%d,%d\n”,BallX02,BallY02,xSpeed02,ySpeed02);
Printf(“flag=%d\n”,flag);
Printf(“\n”);
t=0;
}
}
以上程序存在的问题或需要考虑的问题:
1) 首先,定时打印,软件延时行不行?还有没有更好的方法实现定时打印?
2) 产生随机数函数的用法是不是正确?参考别人的程序看看
3) 程序里第二个球的横坐标越界,这是什么问题造成的,有没有想清楚?
4) 程序里第一个球在原地转圈,这种情况在andorid开发也有类似情况,是如何造成的?需要琢磨下?
5) 以上是基于C的源代码,是否可以用C++来实现呢?可以在C的基础上实现C++的算法和代码
6) 程序缺少—help,这是一个查看函数作用的帮助文件,需要添加,这个还要具体查查看,怎么加上去。
//***********************************************************
由于以上问题之间的联系是比较紧密的,可能换成C++语言,就可以解决多个问题,下面可以多多探索下
//创建时间:2014年4月23日星期三
定时器这一块可以写一个定时器函数,然后替代软件延时,但函数写完后程序是不执行计时循环的,不清楚为什么
下面是网友博客地址和源代码内容:
http://blog.csdn.net/onelight1997/article/details/6270180
使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务。要达到这一目的,一般有两个常见的比较有效的方法。一个是用linux内部的三个定时器,另一个是用sleep, usleep函数让进程睡眠一段时间,其实,还有一个方法,那就是用gettimeofday, difftime等自己来计算时间间隔,然后时间到了就执行某一任务,但是这种方法效率低,所以不常用。
首先来看看linux操作系统为每一个进程提供的3个内部计时器。
ITIMER_REAL: 给一个指定的时间间隔,按照实际的时间来减少这个计数,当时间间隔为0的时候发出SIGALRM信号
ITIMER_VIRTUAL: 给定一个时间间隔,当进程执行的时候才减少计数,时间间隔为0的时候发出SIGVTALRM信号
ITIMER_PROF: 给定一个时间间隔,当进程执行或者是系统为进程调度的时候,减少计数,时间到了,发出SIGPROF信号,这个和ITIMER_VIRTUAL联合,常用来计算系统内核时间和用户时间。
用到的函数有:
#include<sys/time.h>
int getitimer(int which, struct itimerval *value);
int setitimer(int which, struct itimerval*newvalue, struct itimerval* oldvalue);
strcut timeval
{
long tv_sec; /*秒*/
long tv_usec; /*微秒*/
};
struct itimerval
{
struct timeval it_interval; /*时间间隔*/
struct timeval it_value; /*当前时间计数*/
};
it_interval用来指定每隔多长时间执行任务, it_value用来保存当前时间离执行任务还有多长时间。比如说, 你指定it_interval为2秒(微秒为0),开始的时候我们把it_value的时间也设定为2秒(微秒为0),当过了一秒, it_value就减少一个为1, 再过1秒,则it_value又减少1,变为0,这个时候发出信号(告诉用户时间到了,可以执行任务了),并且系统自动把it_value的时间重置为 it_interval的值,即2秒,再重新计数。
为了帮助你理解这个问题,我们来看一个例子:
#include<sys/time.h>
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
static char msg[]= “time is running out/n”;
static int len;
// 向标准错误输出信息,告诉用户时间到了
voidprompt_info(int signo)
{
write(STDERR_FILENO,msg, len);
}
// 建立信号处理机制
voidinit_sigaction(void)
{
struct sigactiontact;
/*信号到了要执行的任务处理函数为prompt_info*/
tact.sa_handler =prompt_info;
tact.sa_flags = 0;
/*初始化信号集*/
sigemptyset(&tact.sa_mask);
/*建立信号处理机制*/
sigaction(SIGALRM,&tact, NULL);
}
void init_time()
{
struct itimervalvalue;
/*设定执行任务的时间间隔为2秒0微秒*/
value.it_value.tv_sec= 2;
value.it_value.tv_usec= 0;
/*设定初始时间计数也为2秒0微秒*/
value.it_interval= value.it_value;
/*设置计时器ITIMER_REAL*/
setitimer(ITIMER_REAL,&value, NULL);
}
int main()
{
len = strlen(msg);
init_sigaction();
init_time();
while ( 1 );
exit(0);
}
该程序的ITMER_REAL定时器,每隔2秒钟都会发送一个SIGALRM信号,当主函数接收到了这个信号之后,调用信号处理函数 prompt_info在标准错误上输出time is running out这个字符串。
对于ITIMER_VIRTUAL和ITIMER_PROF的使用方法类似,当你在setitimer里面设置的定时器为 ITIMER_VIRTUAL的时候,你把sigaction里面的SIGALRM改为SIGVTALARM, 同理,ITIMER_PROF对应SIGPROF。
不过,你可能会注意到,当你用ITIMER_VIRTUAL和ITIMER_PROF的时候,你拿一个秒表,你会发现程序输出字符串的时间间隔会不止2秒,甚至5-6秒才会输出一个,至于为什么,自己好好琢磨一下^_^
下面我们来看看用sleep以及usleep怎么实现定时执行任务。
#include<signal.h>
#include<unistd.h>
#include<string.h>
#include<stdio.h>
static char msg[]= “I received a msg./n”;
int len;
void show_msg(intsigno)
{
write(STDERR_FILENO,msg, len);
}
int main()
{
struct sigactionact;
union sigvaltsval;
act.sa_handler =show_msg;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(50,&act, NULL);
len = strlen(msg);
while ( 1 )
{
sleep(2); /*睡眠2秒*/
/*向主进程发送信号,实际上是自己给自己发信号*/
sigqueue(getpid(),50, tsval);
}
return 0;
}
看到了吧,这个要比上面的简单多了,而且你用秒表测一下,时间很准,指定2秒到了就给你输出一个字符串。所以,如果你只做一般的定时,到了时间去执行一个任务,这种方法是最简单的。
下面我们来看看,通过自己计算时间差的方法来定时:
#include<signal.h>
#include <unistd.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
static char msg[]= “I received a msg./n”;
int len;
static time_tlasttime;
void show_msg(intsigno)
{
write(STDERR_FILENO,msg, len);
}
int main()
{
struct sigactionact;
union sigvaltsval;
act.sa_handler =show_msg;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(50,&act, NULL);
len = strlen(msg);
time(&lasttime);
while ( 1 )
{
time_t nowtime;
/*获取当前时间*/
time(&nowtime);
/*和上一次的时间做比较,如果大于等于2秒,则立刻发送信号*/
if (nowtime – lasttime >= 2)
{
/*向主进程发送信号,实际上是自己给自己发信号*/
sigqueue(getpid(),50, tsval);
lasttime =nowtime;
}
}
return 0;
}
这个和上面不同之处在于,是自己手工计算时间差的,如果你想更精确的计算时间差,你可以把 time 函数换成gettimeofday,这个可以精确到微妙。
上面介绍的几种定时方法各有千秋,在计时效率上、方法上和时间的精确度上也各有不同,采用哪种方法,就看你程序的需要
#include<stdio.h>
#include<signal.h>
#include<sys/time.h>//itimerval结构体的定义
int handle_count=0;
void set_time(void)
{
struct itimerval itv;
itv.it_interval.tv_sec=10;//自动装载,之后每10秒响应一次
itv.it_interval.tv_usec=0;
itv.it_value.tv_sec=5;//第一次定时的时间
itv.it_value.tv_usec=0;
setitimer(ITIMER_REAL,&itv,NULL);
}
void alarm_handle(int sig)
{
handle_count++;
printf("have handle count is %d/n",handle_count);
}
void main(void)
{
struct itimerval itv;
signal(SIGALRM,alarm_handle);
set_time();
while(1){
getitimer(ITIMER_REAL,&itv);
printf("pass second is %d/n",(int)itv.it_value.tv_sec);
sleep(1);
}
return;
}