用DELPHI实现比赛用抢答器

| 对于一般的知识竞赛而言,抢答计时装置是必不少的。在缺少制式的电子抢答器的时候,我们也可以利用相关的软件开发工具设计抢答器。DELPHI开发工具一向以其快速、高效和功能强大著称。在其开发环境中给程序设计人员提供了大量的网络应用开发组件,如WEB组件、INTERNET组件、TCP组件和UDP组件等。利用这些组件,可以进行网络通信的开发设计。下面将利用DELPHI提供的TNMUDP组件,实现基于UDP协议的网络应用程序—抢答计时器。 |
| 1.竞赛用抢答计时器的功能设计 |
| 比赛用抢答计时器的主要功能是实现计时前提下的抢答功能。知识竞赛的规则通常是在主持人宣布开始竞赛的时刻,参赛选手进行比赛抢答。对于其工作流,可以理解为授权、抢答、显示的三步曲。当主持人出示竞赛题目并宣布开始竞赛时,启动相关计时并授权参赛选手可以抢答。在给定时间内若有选手抢答,则显示抢答成功选手。若超过计时则给以相应处理,如题目作废或留给观众等。 |
| 在软件实现上,抢答计时器主要包括服务器和客户机两大组成部分。在服务器端主要实现抢答的授权、计时和结果显示功能。而客户端主要是获得授权后的抢答功能。在具体实现中,以三个场点实现软件的功能。场点一是服务器端的竞赛题目显示、抢答授权、抢答结果显示和选手成绩排行;场点二是记录员的成绩统计模块,完成评委打分计算与成绩传送;场点三是客户端的知识抢答与成绩显示。软件的功能框图如下图1-1所示。 |
|
|
|
图1-1竞赛软件功能框图 |
| 在硬件实现上,可以根据竞赛规模确定竞赛的网络拓朴结构,可以采用总线一、环形或星形的网络结构。在实际实现中,建议采用的是星形。其主要的网络设备组成一般包括计算机、集线器(HUB)、网线(双绞线)和大屏幕投影仪等。其硬件组成如下图1-2所示。 |
|
|
|
图1-2竞赛用硬件组成框图 |
| 2.竞赛软件编码实现 |
| 2.1关于TNMUDP组件 |
| 在软件编写中,用到的网络通讯的组件是DELPHI提供的TNMUDP组件。TNMUDP组件是用于实现用户数据报协议的通信组件,在Internet或Intranet中可以发送数据报分组。其主要的属性和方法如下图1-3所示。 |
|
|
图1-3 TNMUDP属性方法事件说明 |
| 2.2服务器端客户端主要编码 |
| 在服务器端编码中采用TNMUDP组件的SendStream方法,向客户机发送授权信息,同时切换到接收抢答信息状态,并根据接收信息显示抢答结果;客户端主要是利用OnDataReceived 事件来触发抢答的状态转换,如果接收的信息是抢答授权,则进入抢答状态,参赛选手可以进行抢答,否则进行其它动作。在实际编程中,在服务器端实现了竞赛题目的浏览器显示、竞赛成绩的柱形图显示、抢答结果显示和抢答授权。在客户端实现了抢答功能和成绩显示。另外在评分部分,实现的是成绩统计模块,可以接收评委的打分并进行计算,并将成绩发送至服务器和客户机。图1-4是设计实现的服务器端窗体。 |
|
|
|
图1-4服务器端窗体 |
| 如上图所示,在设计时考虑到软件配置的灵活性,提供了可选的操作项,如自定义远程主机地址,是点对点还是广播。授权涉及到的主要代码如下面所示: |
| procedure TFormMain.BitBtnSentClick(Sender: TObject); |
| var |
| MyStream: TMemoryStream; |
| TmpStr: String; |
| i:Integer; |
| Begin |
| NMUDP1.ReportLevel := Status_Basic; //设定状态行显示级别 |
| //广播方式决定远程主机 |
| case RadioGroupBm.ItemIndex of |
| 0: |
| begin |
| NMUDP1.RemoteHost := trim(EditXx.Text); //取得远程主机 |
| NMUDP1.RemotePort := StrToInt(trim(EditPt.Text)); //取得远程端口 |
| TmpStr :=’授权’; //设定授权信息 |
| MyStream := TMemoryStream.Create; |
| try |
| MyStream.Write(TmpStr<1>, Length(EditSm.Text)); //将发送信息存贮到流 |
| NMUDP1.SendStream(MyStream); //将流中的信息发送到远程主机 |
| finally |
| MyStream.Free; //释放流 |
| end; |
| end; |
| 1: //多点传送 |
| begin |
| for i:=0 to ListBoxXx.Count-1 |
| do |
| begin |
| NMUDP1.RemoteHost :=ListBoxXx.Items.Strings; |
| NMUDP1.RemotePort := StrToInt(trim(EditMpt.Text)); |
| TmpStr := EditSm.Text; |
| MyStream := TMemoryStream.Create; |
| try |
| MyStream.Write(TmpStr<1>, Length(EditSm.Text)); |
| NMUDP1.SendStream(MyStream); |
| finally |
| MyStream.Free; |
| end; |
| end; |
| end; |
| end; |
| end; |
| 图1-5是抢答计时窗体,主要利用一个Timer时钟、一个Label时间标签和一个MediaPlayer组件,在Timer组件的OnTimer事件里实现抢答计时。 |
|
|
|
图1-5抢答计时窗体 |
| OnTimer事件的主要代码如下所示: |
| procedure TFormStart.TimerOverTimer(Sender: TObject); |
| begin |
| if strToint(FormStart.LabelOver.Caption)>0 then |
| begin |
| if FormMain.Memo1.Lines.Strings<1><>'' then //抢答成功进入下一窗体 |
| begin |
| FormStart.TimerOver.Enabled:=False; MediaPlayerOver.FileName:=(ExtractFilePath(Application.ExeName)+'clock.wav'); |
| MediaPlayerOver.Open; |
| MediaPlayerOver.Play; |
| FormTip.Show; |
| end |
| else |
| begin FormStart.LabelOver.Caption:=intTostr(strToint(FormStart.LabelOver.Caption)-1); |
| if strToint(FormStart.LabelOver.Caption)<10 then |
| FormStart.LabelOver.Left:=280; //改变时间标签在窗体中的位置 |
| end; |
| end |
| else |
| begin |
| FormStart.TimerOver.Enabled:=False; |
| //播放提示时钟声音 |
| MediaPlayerOver.FileName:=(ExtractFilePath(Application.ExeName)+'clock.wav'); |
| MediaPlayerOver.Open; |
| MediaPlayerOver.Play; |
| FormTip.Show; |
| end; |
| end; |
| 图1-6 是抢答结果显示窗体,主要是利用Memo组件对接收来的UDP数据抢答信息进行分析,取得抢答成功选手,然后利用MediaPlayer组件播放相应的动画提示。 |
|
|
|
图1-6 抢答提示 |
| 程序实现主要代码如下所示: |
| procedure TFormTip.FormShow(Sender: TObject); |
| var msgFrom:string; |
| teamStr:string; |
| posFlag:integer; |
| teamNum:integer; |
| begin |
| PanelTip.Visible:=True; |
| PanelPro.Visible:=False; |
| msgFrom:=trim(FormMain.Memo1.Lines.Strings<1>); |
| posFlag:=Pos('*', msgFrom); |
| teamStr:=copy(msgFrom,posFlag-1,1); |
| if teamStr<>''then |
| begin |
| teamNum:=strToint(teamStr); |
| showmessage(teamStr+'号台选手抢答成功') ;//显示抢答成功选手的台号 MediaPlayerOk.FileName:=(ExtractFilePath(Application.ExeName)+'t0'+teamStr+'.avi'); |
| //取得要播放的选手台号的动画文件 |
| MediaPlayerOk.Display:=PanelTip; |
| MediaPlayerOk.AutoRewind:=True; |
| end; |
| else |
| begin |
| //指定缺省播放的结果动画 |
| MediaPlayerOk.FileName:=(ExtractFilePath(Application.ExeName)+'heihei.avi'); |
| MediaPlayerOk.Display:=PanelTip; |
| MediaPlayerOk.AutoRewind:=True; |
| end; |
| FormStart.Close; |
| FormStart.LabelOver.Caption:='60'; |
| MediaPlayerOk.Close; //播放抢答结果 |
| MediaPlayerOk.Open; |
| MediaPlayerOk.Play; |
| TimerTip.Enabled:=True; |
| end; |
| 图1-7为客户端窗体,通过此窗体选手可以进行抢答,同时显示选手即时成绩。 |
|
|
|
图1-7 客户端 |
| 在程序编码中,主要是利用TNMUDP组件接收授权及成绩信息,进行抢答并对成绩进行处理。程序代码如下所示: |
| procedure TForm1.NMUDP1DataReceived(Sender: TComponent; |
| NumberBytes: Integer; FromIP: String; Port: Integer); |
| var |
| MyStream: TMemoryStream; |
| TmpStr,Rmsg,teamName: String; |
| posStart,posEnd,scoreLast,teamNum:integer; |
| begin |
| MyStream := TMemoryStream.Create; |
| Try //从服务器端接收指令 |
| NMUDP1.ReadStream(MyStream); |
| SetLength(TmpStr,NumberBytes); |
| MyStream.Read(TmpStr<1>,NumberBytes); |
| Memo1.Clear; |
| Memo1.Lines.Add(FromIP+'*'+TmpStr); |
| finally |
| MyStream.Free; |
| end; |
| posStart:=Pos('*', TmpStr); |
| Rmsg:=copy(TmpStr,posStart+1,5); |
| if Rmsg='授权' then //接收授权指令进入抢答状态 |
| begin |
| Form1.NMUDP1.RemoteHost:=FromIP; |
| Form1.ButtonSent.Enabled:=True; |
| Form1.StatusBar1.SimpleText:='现在可以抢答!'; |
| end ; |
| if Rmsg='score' then //下面求取并显示选手成绩 |
| begin |
| posStart:=Pos('#', TmpStr); |
| posEnd:=Pos('@', TmpStr); |
| scoreLast:=strToint(copy(TmpStr,posStart+1,posEnd-posStart-1)); |
| TeamName:= copy(TmpStr,posEnd+1,20); |
| teamNum:=strToint(copy(TmpStr,posEnd+1,1)); |
| Form1.LabelScore.Caption:=intTOstr(scoreLast); |
| Form1.LabelScore.Visible:=True; |
| end; |
| end; |
|
当然还可以在以上编码的基础上加以优化以适合各种知识竞赛的需要,限于篇幅文中对于评分及成绩统计模块没有更多阐述,以上程序在Windows2000/98+Delphi 6.0下调试通过。
|

|
电脑抢答器网 抢答器设计与制作的专业网站 大学生课程设计的园地 |