1、说明
这个是90年代后期读书时写的C语言练习软件,模仿当时的打字练习软件。
在技能上使用屏幕直接输出,支持彩色,能够在DOS和Windows98的窗口下运行。
2、主要界面
支持多用户档案,以键盘操作。
进入具体用户档案后,支持各类实时统计。
3、主要代码TT.C
//打字练习程序,运行于DOS/WINDOWS95/98/2000/XP/2003等操作系统平台
//作者:YuMing,183832091@qq.com
//写于98年左右,后有简单修订#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
#include<alloc.h>
#include<dos.h>#define TRUE 1//练习窗口大小
#define STARTX 3
#define STARTY 4
#define ENDX 76
#define ENDY 22//背景、正文、出错字符颜色
#define BACKCOLOR 1
#define TEXTCOLOR 14
#define PUTCOLOR (BACKCOLOR*16+11)
#define ERRORCOLOR 0X34// 数据文件路径
#define MAX_PATH 260
char filedir[MAX_PATH],TT_DAT[MAX_PATH],TT_HIS[MAX_PATH];//命令行参数个数和参数串
extern int _argc;
extern char **_argv;#pragma pack(1)
typedef struct _USER_DATA//用户数据
{char name[15]; //用户名char ID; //用户IDchar password[9]; //密码,以加密形式存放char passwordlen; //密码有效长度char flag; //标识位,包括保存文件标识,报警标识等char scoreflag; //成绩标识char textname[13];//用户练习文档名unsigned int scorewhere; //成绩数据开始位置unsigned long where; // 用户练习文档当前位置
}USER_DATA;typedef struct _SCORE //成绩数据
{ int year;char month;char day;char flag; // FF effect int speed; // CPM int accuracy;
}SCORE;
#pragma pack()//函数声明区
int ExitWin(int x1,int y1,int x2,int y2);
void ClearWindows(int x1,int y1,int x2,int y2,int color);
int Menu();
void Initialize();
void Putchar(int c,int color,int x,int y);
void Pwindows(int x1,int y1,int x2,int y2,int color);
void Ptext(int slinex,int sline,int eline,int color );
void ShowTimeStart();
int Getcha();
int Input();
void Sound(int f,int time);
void Score();
void Hide_cor();
void Disp_cor(char high,char width);
void CharColor(int x,int y,int color,char *p);
void Changcolor(int x,int y,int color,int count);// XOR
int Setting();
void EXIT(int i);
void ShowTimeStop();
int Check_login_word(USER_DATA *user);
int read_userdata(USER_DATA *user);
char secure_key[8]={0x19,0x15,0x0d,0x09,0x0e,0x07,0x19,0x0d};
void List_score();
char copyrights[]="\n TT Program \t Ver 1.0 Author: Yu Ming Copyrights(C) 2007 5 ";
void key_change(char *key,char *secure_key,char lenth);
void init_tt_his();
int Gets(char *str,char maxlen,char color,char x,char y);
void change_name(char *name);
void change_password(USER_DATA *user);
int change_textname(USER_DATA *user);
int check_tt_his();//变量定义区
union REGS regs; //寄存器变量,用于DOS和BIOS调用
unsigned int cdatacount=0;
int xcor=STARTX,ycor=STARTY+1,errorchar=0;
unsigned int chartotal=(ENDY-STARTY)*(ENDX-STARTX)/2+100;//显示数据和输入数据
char cdata[(ENDY-STARTY)*(ENDX-STARTX)/2+100];
char Pdata[(ENDY-STARTY)*(ENDX-STARTX)/2+100];
char *databuffer = NULL;
void read_to_buffer(char *p,int len);long filecurr=0;
char filecurr_flag=0; // read: 0 continue, 1 try again
void interrupt (*oldtimer)();
void interrupt newtimer();//时间统计
int timerunning=0,timer1=0,timer2=0,timersec=0,timermin=0;
char curr_time_run=0,timeswp1=0,timeswp2=0;
int timetotal=0;
FILE *tt_his,*tt_dat;
USER_DATA User;
SCORE User_score[10];void main()
{Initialize(); //系统初始化ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);//清除屏幕Pwindows(STARTX-2,STARTY-1,ENDX+2,ENDY,0x3f);//绘制练习窗体Ptext(STARTX,STARTY,ENDY,TEXTCOLOR+BACKCOLOR*16);//输出练习文本ShowTimeStart();//启动时钟显示while (Input()==0) //练习处理;ShowTimeStop();//时钟关闭while(Menu()) //菜单择择与处理;EXIT(0); //退出return ;
}//初始化,包括历史数据、练习文本文件等初始化
void Initialize()
{int i=0; char c;char *p;//设置文本模式regs.x.ax=0x0003;int86(0x10,®s,®s);//申请一块内存用于保存练习用的文本,退出时释放databuffer=(char *)malloc(chartotal*10+100);if(databuffer==NULL) {CharColor(3,5,0x84,"Out of Memory!");Sound(800,10000);exit(0);}//从命令行获取当前的完整路径,然后构造TT.HIS文件的全路径p=*_argv;while(*p) filedir[i++] = *p++;while(filedir[i--]!='\\') ;filedir[i+2]='\0';strcpy(TT_HIS,filedir);strcat(TT_HIS,"TT.HIS");tt_his=fopen(TT_HIS,"rb+");//如果打开历史数据文件失败,则可以选择重构此文件或退出系统if(tt_his==NULL||check_tt_his()){ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);Pwindows(12,7,60,16,0x17);CharColor(20,5,0x9c, " TT.HIS File Error ! ");CharColor(20,9,0x1f, " 1. Rebuild");CharColor(20,11,0x1f," 2. Exit ");CharColor(20,13,0x1f,"Presses in Choices:");Putchar('1',0x1f,40,13);gotoxy(41,14);c=Getcha();while(TRUE){//支持数字和大写字母快捷键选择,快捷键大写字母也可用相同的小写来代替,下同if (c=='1'||c=='2'||c=='R'||c=='r'||c=='E'||c=='e'|| c==0x0d ||c==27) break;else cprintf("%c",7); c=Getcha();}if (c=='1'||c=='R'||c=='r'||c==0x0d) {init_tt_his();} else {ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR); exit(0);}tt_his=fopen(TT_HIS,"rb+");}read_userdata(&User);Check_login_word(&User);fseek(tt_his,(long)User.scorewhere,SEEK_SET);fread(User_score,sizeof(SCORE)*10,1,tt_his);filecurr=User.where;filecurr_flag=0;cdatacount=0;strcpy(TT_DAT,filedir);strcat(TT_DAT,User.textname);tt_dat=fopen(TT_DAT,"r");// TT.HIS 数据有效性检测 if(tt_dat==NULL){cprintf("\7");ClearWindows(0,0,79,24,7);CharColor(3,5,0x84,User.textname);CharColor(16,5,0x84," Open Error !");Disp_cor(6,7);exit(0);}read_to_buffer(databuffer,chartotal*10+50);
}//登陆密码检查,只有设置了密码(密码长度不为0)时才需要检查
int Check_login_word(USER_DATA *user)
{ char tmp[15],old[15],errorcount=0,flag;if(user->passwordlen!=0){Pwindows(15,12,55,20,0x7c);ClearWindows(16,13,54,19,BACKCOLOR*16+7);CharColor(24,13,BACKCOLOR*16+15,"Login Password Check");CharColor(19,15,BACKCOLOR*16+15,"Input Your Password:");strncpy(old,user->password,user->passwordlen+1);key_change(old,secure_key,user->passwordlen);while( errorcount < 3 ){errorcount++;flag=Gets(tmp,9,BACKCOLOR*16+BACKCOLOR,40,15);if(flag!=0) // ESC键退出 { ClearWindows(0,0,79,24,7);Disp_cor(6,7);exit(0);}strupr(tmp); strupr(old);if (strcmp(old,tmp)==0) {return 0;} else if (errorcount<3){CharColor(22,17,BACKCOLOR*16+12,"Password Error, input again!");Sound(800,5000);CharColor(22,17,BACKCOLOR*16+BACKCOLOR," ");}}CharColor(22,17,BACKCOLOR*16+14,"Your Password is Error!");CharColor(24,18,BACKCOLOR*16+14,"and hit any to EXIT");Sound(800,5000);Getcha();ClearWindows(0,0,79,24,7);Disp_cor(6,7);exit(0);}return 0;
}// 上一篇练习完成后,继续下一篇练习
void Continue()
{filecurr_flag=0;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);Disp_cor(15,4);Pwindows(STARTX-2,STARTY-1,ENDX+2,ENDY+1,0x2f);Ptext(STARTX,STARTY,ENDY,TEXTCOLOR+BACKCOLOR*16);ShowTimeStart();while (Input()==0);ShowTimeStop();
}// 上一篇练习完成后,重新练习这篇
void Tryagain()
{ int i;filecurr_flag=1;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);Disp_cor(0x0e,0x03);Pwindows(STARTX-2,STARTY-1,ENDX+2,ENDY+1,0x2f);Ptext(STARTX,STARTY,ENDY,TEXTCOLOR+BACKCOLOR*16);ShowTimeStart();while ( Input()==0 ) ;ShowTimeStop();return ;
}//功能选择菜单,用于练习完一篇之后进行下一步选择
int Menu()
{int c,c1,i,y=16;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);Hide_cor();Score();Pwindows(20,15,50,20,0x2f);CharColor(21,16,0x25, " Continue ");CharColor(21,17,0x25, " Try Again ");CharColor(21,18,0x25, " Setting ");CharColor(21,19,0x25, " Exit ");Changcolor(21,y,0xb1,28);timerunning=0;timer1=0;timer2=0;timersec=0;timermin=0;timetotal=0;while(1){ c=Getcha();c=c>>8; // 获取扫描码,用扫描码比较可以忽略大小写,且支持光标键等特殊键 if ( c==1 ) return 0; // ESC to exit switch(c){ case 46: // char is 'C' or 'c' ,Continue Continue();return(1);case 20: // char is 'T' or 't',Try again Tryagain();return(2);case 31: // char is 'S' or 's', setting while(Setting());return (3);case 45: // char is 'X' or 'x' return 0;case 72: // Up ,Left Changcolor(21,y,0xb1,28);y--;if (y<16) y=19;Changcolor(21,y,0xb1,28);break;case 80: // Down,Right case 57:Changcolor(21,y,0xb1,28);y++;if (y>19) y=16;Changcolor(21,y,0xb1,28);break;case 28: // Enter switch(y){case 16: // Continue Continue();return(1);case 17: // Try again Tryagain();ShowTimeStop();return(2);case 18:Setting();return (3);case 19: // exit return 0;defalut :;}default: ;}}
}
//隐藏光标,调用BIOS中断实现
void Hide_cor()
{ regs.x.ax=0x100;regs.x.cx=0x0100;int86(0x10,®s,®s);
}//显示光标,调用BIOS中断实现
void Disp_cor(char high,char width)
{ regs.h.ah=1;regs.h.ch=high;regs.h.cl=width;int86(0x10,®s,®s);
}//用指定颜色输出一个文本串
void CharColor(int x,int y,int color,char *p)
{//0xb8000000为文本显存地址,直接改变显示字符属性,下面类似static char far *buffer=(char far *)0xb8000000;int z=(y*80+x)*2,i;while(*p){ *(buffer+z++)=*p++;*(buffer+z++)=color;}
}//更改指定位置开始的count个字符显示颜色
void Changcolor(int x,int y,int color,int count)
{ static char far *buffer=(char far *)0xb8000000;int i, z=(y*80+x)*2+1;// Color XOR old Color for(i=0;i<=count;i++){*(buffer+z)^=color;z+=2;}return ;
}//在指定位置用指定颜色显示一个字符
void Putchar(int c,int color,int x,int y)
{static char far *buffer=(char far *)0xb8000000;int z;z=(y*80+x)*2;*(buffer+z)=c;*(buffer+z+1)=color;return ;
}//获取一个键盘输入
int Getcha()
{int key;regs.h.ah=0;int86(0x16,®s,®s);key=regs.x.ax;return key;
}//绘制一个指定大小和颜色的文本窗体
void Pwindows(int x1,int y1,int x2,int y2,int color)
{int i;Putchar(0xc9,color,x1,y1);//╔Putchar(0xbb,color,x2,y1);// ╗Putchar(0xc8,color,x1,y2);//╚Putchar(0xbc,color,x2,y2);// ╝for(i=x1+1;i<x2;i++){Putchar(0xcd,color,i,y1);//═Putchar(0xcd,color,i,y2);}for(i=y1+1;i<y2;i++){ Putchar(0xba,color,x1,i); //║Putchar(0xba,color,x2,i);}
}//显示文本练习窗口和内容
void Ptext(int slinex,int sline,int eline,int color )
{ static read_p;int i=0,j=0,c,d=0;cdatacount=0;errorchar=0;curr_time_run=1;CharColor(16,0,BACKCOLOR*16+12," Welcome to Use Tt Program ");CharColor(5,1,BACKCOLOR*16+12," Autor: Yu Ming Ver 1.0 (C)Copyright 2007,5 Inc ");CharColor(10,24,BACKCOLOR*16+TEXTCOLOR,"CharTotal:");CharColor(30,24,BACKCOLOR*16+TEXTCOLOR,"CharError:");CharColor(50,24,BACKCOLOR*16+TEXTCOLOR,"Speed:");CharColor(1,2,BACKCOLOR*16+10,"User Name: ");CharColor(12,2,BACKCOLOR*16+10,User.name);CharColor(60,2,BACKCOLOR*16+15,"Hour");CharColor(68,2,BACKCOLOR*16+15,"Min");CharColor(75,2,BACKCOLOR*16+15,"Sec");if(filecurr_flag==0){if((chartotal*10-read_p)<chartotal){ read_to_buffer(databuffer,chartotal*10+50);read_p=0;}memcpy((char *)cdata,(char *)(databuffer+read_p),chartotal);read_p+=chartotal;}else{memcpy((char *)cdata,(char *)(databuffer+read_p-chartotal),chartotal);}xcor=slinex;ycor=sline;c=0;for( i=sline; i<=(eline-sline+6)/2; i++){for (j=slinex;j<=ENDX;j++){Putchar(cdata[c++],color,xcor++,ycor);}d++;ycor+=2; xcor=slinex;}gotoxy(STARTX+1,STARTY+2);xcor=STARTX;ycor=STARTY+1;
}//加载练习数据到缓存
void read_to_buffer(char *p,int len)
{int i=0;char c;fseek(tt_dat,filecurr,SEEK_SET);while(i<len){c=getc(tt_dat);if(!feof(tt_dat)){if (c>=32 && c<127) {*p++=c; i++; }}else //读取到文件尾,则重开始处继续读 rewind(tt_dat);}filecurr=ftell(tt_dat);if(User.flag&1) User.where=filecurr; //记住当前位置return ;
}//用户输入处理
int Input()
{int c=0,c1=0;unsigned int speed = 0;char *string,string1[20];Disp_cor(7,8);gotoxy(xcor+1,ycor+1);c=Getcha();c= (c&0xff) ? c&0xff :0;if (c==27) return ExitWin(10,8,50,18);c1=cdata[cdatacount];switch(c){case 8: if (xcor==STARTX) break;xcor--;Putchar(32,BACKCOLOR*16+TEXTCOLOR,xcor,ycor);cdatacount--;if(cdata[cdatacount]!=Pdata[cdatacount])errorchar--;break;default :Pdata[cdatacount]=c;if(c!=c1){errorchar++;if(c>127 || c<32) c=32;Putchar(c,ERRORCOLOR,xcor,ycor);if(User.flag&2){Sound(800,200);}} elsePutchar(c,PUTCOLOR,xcor,ycor);xcor++; cdatacount++;}if(xcor>ENDX){timetotal=timermin*60+timersec;speed=cdatacount*60/timetotal;speed=speed*10/50;string=itoa(cdatacount,string1,10);CharColor(21,24,BACKCOLOR*16+TEXTCOLOR,string);string=itoa(errorchar,string1,10);CharColor(41,24,BACKCOLOR*16+TEXTCOLOR,string);string=itoa(speed,string1,10);CharColor(56,24,BACKCOLOR*16+TEXTCOLOR,string);ycor+=2;xcor=STARTX;if(ycor>ENDY)return 1 ;else return 0;}return 0;}//声音输出,参数:频率,持续时间
void Sound(int f,int time)
{ int hf,lf;hf=time/655;lf=time%655;lf=lf*100;sound(f);regs.h.ah=0x86;regs.x.cx=hf;regs.x.dx=lf;int86(0x15,®s,®s);nosound();
}//成绩报告
void Score()
{unsigned int charspeed1,charspeed2,tmp;char *string,string1[20];float accuracy;Hide_cor();curr_time_run=0;if(cdatacount==0||timetotal==0) charspeed2=0;else charspeed2=cdatacount*60/timetotal;if (charspeed2==0) charspeed1=0;else charspeed1=( charspeed2*10)/50;if (errorchar==0||cdatacount==0) accuracy=100;else if (cdatacount<=errorchar) accuracy=0;else accuracy=(cdatacount-errorchar)*100.0/cdatacount;Pwindows(12,2,60,12,0x2f);CharColor(15,3,BACKCOLOR*16+TEXTCOLOR,"Speed: WPM ");CharColor(15,5,BACKCOLOR*16+TEXTCOLOR,"Speed: CPM ");CharColor(15,7,BACKCOLOR*16+TEXTCOLOR,"Accuracy: \% ");CharColor(15,9,BACKCOLOR*16+TEXTCOLOR,"Time Total: : ");string=itoa(charspeed1,string1,10);CharColor(25,3,BACKCOLOR*16+TEXTCOLOR,string);string=itoa(charspeed2,string1,10);CharColor(25,5,BACKCOLOR*16+TEXTCOLOR,string);tmp=(unsigned int)accuracy;string=itoa(tmp,string1,10);CharColor(26,7,BACKCOLOR*16+TEXTCOLOR,string);string=itoa(timermin,string1,10);CharColor(28,9,BACKCOLOR*16+TEXTCOLOR,string);string=itoa(timersec,string1,10);CharColor(31,9,BACKCOLOR*16+TEXTCOLOR,string);//保存数据到 tt.his if (timetotal>=10){regs.h.ah=0x2a; // 通过DOS功能调用取当前日期int86(0x21,®s,®s);User_score[User.scoreflag].year = regs.x.cx;User_score[User.scoreflag].month = regs.h.dh;User_score[User.scoreflag].day = regs.h.dl;User_score[User.scoreflag].flag = 1;User_score[User.scoreflag].speed = charspeed2;User_score[User.scoreflag].accuracy = (int)(accuracy);if(User.scoreflag>=9) User.scoreflag = 0;else User.scoreflag++;}timetotal=0;cdatacount=0;return ;
}// 退出系统
void EXIT(int i)
{fseek(tt_his,(long)(128+sizeof(USER_DATA)*User.ID),SEEK_SET);fwrite(&User,sizeof(USER_DATA),1,tt_his);fseek(tt_his,(long)User.scorewhere,SEEK_SET);fwrite(User_score,sizeof(SCORE),10,tt_his);fclose(tt_dat);fclose(tt_his);regs.x.ax=3; //恢复为文本模式int86(0x10,®s,®s);if ( databuffer != NULL )free(databuffer);exit(i);
}//开始显示时间
void ShowTimeStart()
{oldtimer=getvect(0x1c);setvect(0x1c,newtimer);timerunning=1;CharColor(68,24,BACKCOLOR*16+15,"TIME: 00:00");
}//停止时间显示
void ShowTimeStop()
{setvect(0x1c,oldtimer);
}// 时钟中断处理过程,直接屏幕输入实时显示当前时间
void interrupt newtimer()
{// echo current time if(curr_time_run){ timer1++;if(timer1>=18){ timer2++;if(timer2==5) {timer2=0;timer1=-1;}else timer1=0;regs.h.ah=0x02;//读取真实时钟,BCD格式int86(0x1a,®s,®s);timeswp2=timeswp1=regs.h.ch;//时timeswp1>>=4;timeswp2&=0x0f;timeswp1+='0';timeswp2+='0';Putchar(timeswp1,0x1b,57,2);Putchar(timeswp2,0x1b,58,2);timeswp2=timeswp1=regs.h.cl;//分timeswp1>>=4;timeswp2&=0x0f;timeswp1+='0';timeswp2+='0';Putchar(timeswp1,0x1b,65,2);Putchar(timeswp2,0x1b,66,2);timeswp2=timeswp1=regs.h.dh;//秒timeswp1>>=4;timeswp2&=0x0f;timeswp1+='0';timeswp2+='0';Putchar(timeswp1,0x1b,72,2);Putchar(timeswp2,0x1b,73,2);if(timerunning){ timerunning=0; //防重入timersec++;if(timersec>59){timermin++;timersec=0;}Putchar(timermin/10+'0',BACKCOLOR*16+11,74,24);Putchar(timermin%10+'0',BACKCOLOR*16+11,75,24);Putchar(timersec/10+'0',BACKCOLOR*16+11,77,24);Putchar(timersec%10+'0',BACKCOLOR*16+11,78,24);timerunning=1;}}}(*oldtimer)();
}//退出窗口
int ExitWin(int x1,int y1,int x2,int y2)
{ int i,j,flag,z,x,y;char *p;timerunning=0;z=(y2-y1+2)*(x2-x1)*2+100;p=malloc(z);x=wherex();y=wherey();gotoxy(x1+6,y1+4);gettext(x1-1,y1-1,x2+1,y2+1,p);Pwindows(x1,y1,x2-1,y2-1,0x74);ClearWindows(x1+1,y1+1,x2-2,y2-2,BACKCOLOR*16+2);CharColor(x1+3,y1+3,BACKCOLOR*16+12," [Quit] [Return] [Continun]");Putchar('Q',0x1e,x1+5,y1+3); //采用不同颜色显示'Q','R','C'三个快捷键Putchar('R',0x1e,x1+15,y1+3);Putchar('C',0x1e,x1+27,y1+3);while(1){z=Getcha();z=z>>8;switch(z){ case 16: // 'Q' or 'q' case 1 : // ESC case 13: // Enter ShowTimeStop();ClearWindows(0,0,79,24,BACKCOLOR*16+2);Score();Getcha();ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);EXIT(0);break;case 19: // 'R' or 'r' free(p);return 1;case 46: // 'C' or 'c' puttext(x1-1,y1-1,x2+1,y2+1,p);timerunning=1;gotoxy(x,y);return 0;default:;}}return 0;
}//清除窗体显示,用空格填充
void ClearWindows(int x1,int y1,int x2,int y2,int color)
{ int i,j;for (i=x1;i<=x2;i++)for (j=y1;j<=y2;j++){Putchar(' ',color,i,j);}return ;
}//更改用户名
void change_name(char *name)
{char tmp[15];int flag;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);CharColor(20,4,BACKCOLOR*16+11," Change Your Name ");Pwindows(16,6,60,12,0x17);CharColor(18,8,BACKCOLOR*16+11," Your Old Name :");CharColor(35,8,BACKCOLOR*16+11,name);CharColor(18,10,BACKCOLOR*16+11," Input Your New Name :");flag=Gets(tmp,14,BACKCOLOR*16+11,42,10);if((flag==0)&&(strlen(tmp)>=1)) strcpy(name,tmp);return ;
}//更改用户密码
void change_password(USER_DATA *user)
{char old1[10],old2[10];char new1[10],new2[10];strncpy(old1,user->password,user->passwordlen+1);key_change(old1,secure_key,user->passwordlen);ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);CharColor(20,4,BACKCOLOR*16+15," Change Your Password ");Pwindows(16,6,60,14,BACKCOLOR*16+15);if(user->passwordlen!=0){CharColor(18,8,BACKCOLOR*16+10," Input Your Old Password :");Gets(old2,8,BACKCOLOR*16+BACKCOLOR,48,8);}CharColor(18,10,BACKCOLOR*16+11," Input Your New Password :");Gets(new1,8,BACKCOLOR*16+BACKCOLOR,48,10);CharColor(18,12,BACKCOLOR*16+11," Input Your Password Again :");Gets(new2,8,BACKCOLOR*16+BACKCOLOR,48,12);//转化为大写进行比较,即密码忽略大小写strupr(new1); strupr(new2);strupr(old1); strupr(old2);if ( ((user->passwordlen!=0)&&(strcmp(new1,new2)==0)&&(strcmp(old1,old2)==0))||((user->passwordlen==0)&&(strcmp(new1,new2)==0))){ user->passwordlen=strlen(new1);key_change(new1,secure_key,user->passwordlen);strncpy(user->password,new1,user->passwordlen+1);CharColor(20,16,0x9f," Now,Your Password has been changed. ");} else CharColor(20,16,0x9c," New Password not retyped correctly. ");CharColor(20,18,BACKCOLOR*16+11," Please hit any key to continue... ");Getcha();ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);return ;
}//获取指定位置的一行输入
int Gets(char *str,char maxlen,char color,char x,char y)
{unsigned char i=0,c;for(i=0;i<maxlen;i++){*(str+i)=0;Putchar(' ',color,x+i,y);}gotoxy(x+1,y+1);i=0;while(1){ c=Getcha();if(c==8&&i>0) {i--; str--;x--;Putchar(' ',color,x,y);}if(c==8&&i<=0) Sound(800,500);if(c==27) return 1;if(c==0x0d) { *str='\0';return 0;}if (i>=maxlen) {Sound(800,500);} else if((c>=32&&c<=127)||(c>=161 && c<255)){ //161~255为汉字区间*str++=c;Putchar(c,color,x,y);x++;i++;}gotoxy(x+1,y+1);}return 0;
}//初始化历史数据,用于历史成绩数据文件出错时自动重建
void init_tt_his()
{ FILE *init_tt_his;char typeendcode[]={0x2e,0x0d,0x0a,0x1a,0x01,0x23,0x1a,0x1a,0x1a,0};USER_DATA userdata;SCORE userscore;int i;init_tt_his=fopen(TT_HIS,"wb");if(init_tt_his==NULL){ puts(" \7 TT.HIS Create Error!"); exit(0);}fprintf(init_tt_his,"%s",copyrights); //write copyrights infomation fprintf(init_tt_his,"%s",typeendcode);fseek(init_tt_his,(long)128,SEEK_SET);userdata.scoreflag=0;userdata.where=(long) 0;strcpy(userdata.name,"YuMing");userdata.ID=0;userdata.passwordlen=0;strcpy(userdata.password,"");key_change(userdata.password,secure_key,userdata.passwordlen);userdata.flag=2;strcpy(userdata.textname,"TT.DAT");userdata.scorewhere=(long)(128+5*sizeof(USER_DATA)+18);fwrite(&userdata,sizeof(USER_DATA),1,init_tt_his);userdata.flag=2;userdata.passwordlen=0;strcpy(userdata.password,"");key_change(userdata.password,secure_key,userdata.passwordlen);userdata.ID=1;strcpy(userdata.name,"USER_ONE");userdata.scorewhere=(long)(128+5*sizeof(USER_DATA)+18+sizeof(SCORE)*10);fwrite(&userdata,sizeof(USER_DATA),1,init_tt_his);userdata.ID=2;strcpy(userdata.name,"USER_TWO");userdata.scorewhere=(long)(128+5*sizeof(USER_DATA)+18+sizeof(SCORE)*20);fwrite(&userdata,sizeof(USER_DATA),1,init_tt_his);userdata.ID=3;strcpy(userdata.name,"USER_THREE");userdata.scorewhere=(long)(128+5*sizeof(USER_DATA)+18+sizeof(SCORE)*30);fwrite(&userdata,sizeof(USER_DATA),1,init_tt_his);userdata.ID=4;strcpy(userdata.name,"USER_FOUR");userdata.scorewhere=(long)(128+5*sizeof(USER_DATA)+18+sizeof(SCORE)*40);fwrite(&userdata,sizeof(USER_DATA),1,init_tt_his);fwrite("USER_END",8,1,init_tt_his);userscore.flag=0;fseek(init_tt_his,(long)(128+5*sizeof(USER_DATA)+18),SEEK_SET);for(i=0;i<50;i++) fwrite(&userscore,sizeof(userscore),1,init_tt_his);fclose(init_tt_his);
}//密钥转换
void key_change(char *key,char *secure_key,char lenth)
{ char i;for(i=0;i<lenth;i++){ *key^=*secure_key;key++;secure_key++;}
}//检查历史成绩文件
int check_tt_his()
{char i,c;char rights_cmp[63];rewind(tt_his);for(i=0;i<60;i++){c=fgetc(tt_his);if (copyrights[i]!=c)return 1; // tt.his error }return 0; // tt.his open ok
}//读取用户数据配置文件
int read_userdata(USER_DATA *user)
{char i,sc,y;USER_DATA userdata[5];gotoxy(80,25);ClearWindows(0,0,79,24,BACKCOLOR*16+1);fseek(tt_his,(long)128,SEEK_SET);fread(userdata,sizeof(USER_DATA),5,tt_his);Pwindows(5,3,75,22,0x2f);ClearWindows(15,8,45,18,BACKCOLOR*16+2);Hide_cor();CharColor(7,2,BACKCOLOR*16+14,"Registration");CharColor(7,5,BACKCOLOR*16+15,"Use up and down arrow keys (or space bar) to move");CharColor(7,6,BACKCOLOR*16+15,"highlight to correct name.. ");CharColor(30,20,BACKCOLOR*16+15,"..press Enter to select highlighted item.");Pwindows(20,8,50,18,0x2f);for(i=0;i<5;i++){CharColor(21,9+i*2,0x2f," ");if(i<4)CharColor(21,10+i*2,0x2f," ");CharColor(22,9+i*2,0x2f,userdata[i].name);}Changcolor(21,9,0xb1,28);y=9;while(TRUE){regs.h.ah=0;int86(0x16,®s,®s);sc=regs.h.ah; // sc=scan code switch(sc){ case 1: // ESC exit regs.x.ax=3;int86(0x10,®s,®s);exit(0);return 0;case 72: // Up ,Left Changcolor(21,y,0xb1,28);y-=2;if (y<9) y=17;Changcolor(21,y,0xb1,28);break;case 80: // Down,Right case 57: // space Changcolor(21,y,0xb1,28);y+=2;if (y>17) y=9;Changcolor(21,y,0xb1,28);break;case 28:// Enter memcpy(user,&userdata[(y-9)/2],sizeof(USER_DATA));Changcolor(21,y,0xa0,28);return 0;default :;}}
}//选项菜单
int Setting()
{char ch1='0',ch2;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);CharColor(8,5,BACKCOLOR*16+3,"Setting and Select Option");Pwindows(6,6,50,16,BACKCOLOR*16+2);CharColor(8,7,BACKCOLOR*16+15, "1.Change Name ");CharColor(8,8,BACKCOLOR*16+15, "2.Change Password ");CharColor(8,9,BACKCOLOR*16+15, "3.Change Text Name ");CharColor(8,10,BACKCOLOR*16+15,"4.Sound On/Off ");CharColor(8,11,BACKCOLOR*16+15,"5.Keep Text Where ");CharColor(8,12,BACKCOLOR*16+15,"6.List Score ");CharColor(8,13,BACKCOLOR*16+15,"0.Return ");CharColor(8,15,BACKCOLOR*16+15," Presses in choices:");gotoxy(31,16);Disp_cor(6,7);while(TRUE){Putchar(ch1,BACKCOLOR*16+15,30,15);ch2=Getcha();if(ch2>='0'&&ch2<='6')ch1=ch2;else if(ch2==27||ch2==13) break;else cprintf("\07");}if ( ch2 != 13 )return 0;switch(ch1){ case '0':return 0;case '1':change_name(User.name);return 1;case '2':change_password(&User);return 2;case '3':change_textname(&User);return 3;case '4': // sound on/off User.flag=User.flag^0x02;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);if(User.flag&0x02)CharColor(3,5,BACKCOLOR*16+3,"Sound On Now !");elseCharColor(3,5,BACKCOLOR*16+3,"Sound Off Now !");CharColor(3,6,BACKCOLOR*16+3,"Press any key to continue...");Hide_cor();Getcha();return 4;case '5':User.flag=User.flag^0x01;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);if(User.flag&0x01)CharColor(3,5,BACKCOLOR*16+3,"Now,keep text where!");elseCharColor(3,5,BACKCOLOR*16+3,"Now,not keep text where!");CharColor(3,6,BACKCOLOR*16+3,"Press any key to continue...");Hide_cor();Getcha();return 5;case '6':List_score();return 6;}return 6;
}//更改练习文本名,即自行定制练习文本
int change_textname(USER_DATA *user)
{char tmp[15];char flag;ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);CharColor(20,4,BACKCOLOR*16+15," Change Text Name ");Pwindows(16,6,60,12,0x1f);CharColor(18,8,BACKCOLOR*16+10," Your Old Text Name :");CharColor(40,8,BACKCOLOR*16+10,user->textname);CharColor(18,10,BACKCOLOR*16+11," Input New Text Name[.DAT]:");flag=Gets(tmp,13,BACKCOLOR*16+15,46,10);if((flag==0)&&(strlen(tmp)>=1)) strcpy(user->textname,tmp);return 0;
}//显示历史成绩
void List_score()
{ int i,y=0;char str,str1[20];ClearWindows(0,0,79,24,BACKCOLOR*16+TEXTCOLOR);CharColor(6,4,BACKCOLOR*16+15,"List History Score");CharColor(28,4,BACKCOLOR*16+15," User Name: ");CharColor(40,4,BACKCOLOR*16+15,User.name);Pwindows(5,5,75,20,BACKCOLOR*16+2);CharColor(7,6,BACKCOLOR*16+15,"Year");CharColor(14,6,BACKCOLOR*16+15,"Month");CharColor(23,6,BACKCOLOR*16+15,"Day");CharColor(30,6,BACKCOLOR*16+15,"Speed(CPM)");CharColor(45,6,BACKCOLOR*16+15,"Accuracy");Hide_cor();for(i=0;i<10;i++){if(User_score[i].flag!=0){y++;CharColor(7,7+y,BACKCOLOR*16+15,itoa(User_score[i].year,str1,10));CharColor(16,7+y,BACKCOLOR*16+15,itoa((int)User_score[i].month,str1,10));CharColor(24,7+y,BACKCOLOR*16+15,itoa((int)User_score[i].day,str1,10));CharColor(33,7+y,BACKCOLOR*16+15,itoa(User_score[i].speed,str1,10));CharColor(48,7+y,BACKCOLOR*16+15,itoa(User_score[i].accuracy,str1,10));Putchar('\%',BACKCOLOR*16+15,52,7+y);}}Getcha();return ;
}
4、数据文件
Mr. Prime Minister and all of your distinguished guests thisevening:On behalf of all of your American guests, I wish to thankyou for the incomparable hospitality for which the Chinesepeople are justly famous throughout the world.I particularlywant to pay tribute, not only to whose who prepared the magnificentdiner,but also to whose who have provided the splendid music. Neverhave I heard American music played better in a foreign land.Mr. Prime Minister, I wish to thank you for your very graciousand eloquent remarks. At this very moment,through the wonder oftelecommunications,more people are seeing and hearing what we saythan on any other such occasion in the whole history of the world.Yet,what we say her will not be long remembered.What we do herecan change the world.As you said in your toast,the Chinese people are a great people,the American people are a great poeple.If our two peoples areenemies,the future of this world we share together is dark indeed.But if we can find common ground to word together,the chance forworld peace is immeasurably increased.In the spirt of frankness which I hope will characterize our tallksthis week,let us recognize at the outset these points: We have at timesin the past been enemies. We have great differences today. What bringsus together is that we have common interests which transcend thosedifferences.As we discuss or differences,neither of us will compromise ourprinciples. But while we cannot close the gulf between us ,we can try tobridge is so that we may be able to talk across it.So,let us in these next five days,start a long march together,not in thelockstep,but on different roads leading to the same goal, the goal ofbuilding a world structure of peace and justice in which all may stand togeterwith equal dignity and in which each nation,large or small,has a right to determineits own form of government, free of outside interference or domination. Theworld watches. The world listens. The world waits to see what we will do.What is the world? In a personal sense,I think of my eldest daughter whosebirthday is today. As I think of her,I think of all the children in the world,in Asia,in Africa,in Europe,in the americas, most of whom were born since thedate of the foundation of the People's Republic of China.What legacy shall we leave out children? Are they distined to die for the hatredswhich have plagued the old world,or are they destined to live because we hadthe vision to build a new world.There is no reason for us to be enemies. Neither of us seeks the territoryof the other;neither of us seeks domination over the other;neither of us seeksto stretch out our hands and rule the world.Chairman Mao has written, "so many deeds cry out to be done,and always urgently;The world rools on. Time presses. Ten thousand years are too long. Seize the day,seize the hour!"This is the hour. This is the day for our two peoples to rise to the heightsof greatness which can build a new and a better world.In the spirit, I ask all of you present to join me in raising your glasses toChairman Mao,to Prime Minister Zhou,and to the friendship of the Chinese andAmerican people which can lead to friendship and peace for all people in the world.