指法练习软件TT

1、说明

         这个是90年代后期读书时写的C语言练习软件,模仿当时的打字练习软件。

         在技能上使用屏幕直接输出,支持彩色,能够在DOS和Windows98的窗口下运行。

2、主要界面

       支持多用户档案,以键盘操作。

指法练习软件TT_第1张图片

     进入具体用户档案后,支持各类实时统计。

指法练习软件TT_第2张图片

3、主要代码TT.C

//打字练习程序,运行于DOS/WINDOWS95/98/2000/XP/2003等操作系统平台
//作者:YuMing,[email protected]
//写于98年左右,后有简单修订


#include
#include
#include
#include
#include
#include

#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;          //用户ID
	char 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=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);
				}
			} else
				Putchar(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;i0) 
		{
			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;i17) 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 !");
		else
			CharColor(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!");
		else
			CharColor(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 this
 evening:
 On behalf of all of your American guests, I wish to thank
 you for the incomparable hospitality for which the Chinese
 people are justly famous throughout the world.I particularly
 want to pay tribute, not only to whose who prepared the magnificent
 diner,but also to whose who have provided the splendid music. Never
 have I heard American music played better in a foreign land.
 Mr. Prime Minister, I wish to thank you for your very gracious
 and eloquent remarks. At this very moment,through the wonder of
 telecommunications,more people are seeing and hearing what we say
 than 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 here
 can 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 are
 enemies,the future of this world we share together is dark indeed.
 But if we can find common ground to word together,the chance for
 world peace is immeasurably increased.
 In the spirt of frankness which I hope will characterize our tallks
 this week,let us recognize at the outset these points: We have at times
 in the past been enemies. We have great differences today. What brings
 us together is that we have common interests which transcend those
 differences.As we discuss or differences,neither of us will compromise our
 principles. But while we cannot close the gulf between us ,we can try to
 bridge 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 the
 lockstep,but on different roads leading to the same goal, the goal of
 building a world structure of peace and justice in which all  may stand togeter
 with equal dignity and in which each nation,large or small,has a right to determine
 its own form of government, free of outside interference or domination. The
 world 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 whose
 birthday 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 the
 date of the foundation of the People's Republic of China.
 What legacy shall we leave out children? Are they distined to die for the hatreds
 which have plagued the old world,or are they destined to live because we had
 the vision to build a new world.
 There is no reason for us to be enemies. Neither of us seeks the territory
 of the other;neither of us seeks domination over the other;neither of us seeks
 to 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 heights
 of 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 to
 Chairman Mao,to Prime Minister Zhou,and to the friendship of the Chinese and
 American people which can lead to friendship and peace for all people in the world.

你可能感兴趣的:(DOS,C,DOS,指法练习软件)