? ? ? ? ?这个是90年代后期读书时写的C语言练习软件,模仿当时的打字练习软件。
? ? ? ? ?在技能上使用屏幕直接输出,支持彩色,能够在DOS和Windows98的窗口下运行。
? ? ? ?支持多用户档案,以键盘操作。
? ? ?进入具体用户档案后,支持各类实时统计。
//打字练习程序,运行于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; //用户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<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);
}
} 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;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 !");
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 ;
}
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.