本文以及程序代码原创,谢绝转载!
最近的一个项目,练手用的,大概一个星期的开发时间,不过每天写代码16小时以上,折合标准工作时间差不多半个月吧。
是单词记忆系统,能实现联网对战,离线练习,用户登录与注册,排名,自定义签名,密码修改,词库选择,新闻显示,系统管理等功能。通过自带词库的动态查找切割选词。
指针用的比较多,还算方便,数组和变量开的有点乱,代码写的还是比较随意,我先用的二维数组保存数据,后来用结构体存的。因为都是单词遍历的查找,基本上没有链表,然后数据库连接,网络通信那块时间用的比较久,单词用的文件io,简易的写了个匹配,源码里都有。界面c控制台,函数动态生成的,总代码量1500+行。
源码还算详细。代码基本做到了显示和功能的隔离,模块耦合性嘛,好像开了挺多的全局变量…
涉及隐私问题,全文中学校使用***代替,姓名使用Dmjsz代替。
是单词记忆系统,能实现联网对战,离线练习,用户登录与注册,排名,自定义签名,密码修改,词库选择,新闻显示,系统管理等功能。通过自带词库的动态查找切割选词。
指针用的比较多,还算方便,数组和变量开的有点乱,代码写的还是比较随意,我先用的二维数组保存数据,后来用结构体存的。因为都是单词遍历的查找,基本上没有链表,然后数据库连接,网络通信那块时间用的比较久,单词用的文件io,简易的写了个匹配,源码里都有。界面c控制台,函数动态生成的,总代码量1500+行。
源码还算详细。代码基本做到了显示和功能的隔离,模块耦合性嘛,好像开了挺多的全局变量…
涉及隐私问题,全文中学校使用***代替,姓名使用Dmjsz代替。
效果图
数据库结构
源代码
/**-----源码前置信息----------------------------------| | 本软件中文名为单词世界,英文名为WordWorld,旨在帮助高| |中生和大学生背诵英语单词,包括互联网对战和独立练习,并提 | |供一系列账号及词库解决方案,希望可以真正帮助到想提高英语 | |水平的同学。 | | 软件使用编程软件为MicrosoftVisualStudio2013,开发者| |为***Dmjsz同学,开发时间是2016年10月17日到2016年10月23 | |日,系本人第一次使用c语言开发中小型程序,如有不足,请不吝| |指教。 | | 本软件系开发者本人独立开发完成,但在数据库连接和网络| |通信模块查阅了相关资料,现向曾经提供帮助的朋友表示感谢!| |由于作者水平有限,代码风格显得较为随意,主要以实现功能为| |主,数组的开辟也浪费了不少空间,这些问题将可能在以后逐步| |解决。本代码仅供研究学习之用,谢绝转载。 | |---------------------------------------------------*/ /*包含的头文件*/ #include <stdio.h>//标准输入输出头文件 #include <string.h> //字符串处理头文件 #include <stdlib.h> //standard library标准库头文件 #include <winsock2.h>//网络通信头文件 #include <conio.h>//字符串*号回显使用 #include "Windows.h"//windows头文件 #include "mysql.h"//数据库相关头文件 /*包含的库*/ #pragma comment(lib,"libmysql") //数据库使用 #pragma comment(lib,"ws2_32.lib")//winsock2链接的库 /*数据库的define定义*/ char host[25]="127.0.0.1"; #define USERNAME "root" //定义数据库用户名 #define PASSWORD "11111111" //定义数据库密码 #define DATABASE "data" //定义数据库名 /*全局变量区*/ //定义全局用户名,用来保存当前用户 char username[50] = ""; //定义登录状态,0表示未登录,1表示已登录 int isLoged = 0; //定义时间戳,在时间比对时使用 long int firstTimer = 0; //游戏可以切换不同的服务器,这里的变 //量用来保存处理服务器的序列号 int server = 1; //定义词库文件的位置指向 char wordPath[50] = "dic//default.ewf"; //定义结构体,保存对战时自己和对手的资料 struct ag{ char name[20];//姓名 char score[5];//分数 }; //定义5个结构体变量 struct ag ag[5] = { { "", "" }, { "", "" }, { "", "" }, { "", "" }, { "", "" } }; //当数据库读取信息时,对个人的不同信息没有采用结构体形式,而是使用#号分割, //例如#name#score#saying#,所以原本的循环变量不能保存人数,使用agCounter保存, //又因为,人数在对战开始的列表和结果都有显示,所以定义为全局变量。 int agCounter = 0; int wordAllNum = 3160; /*函数定义区,不同函数将在每个函数的开头具体解释*/ void dush(); void blank(); void word(char * front, char * back); void getWelcomeFrame(); void getRegFrame(); void getLoginFrame(); void getUserMainFrame(); void worldButtleSearchFrame(); int worldButtleFrame(int right, int stage); void worldButtleWaitingFrame(); void worldButtleResultFrame(); void getStartFunction(int state); void dealFile(); char* ipadd(); char* nowTime(); void dealSql(char *old, char *new); long int timePast(); void scorelist(); void changePassword(); void changeSaying(); void changeNews(); void closeSystem(); void header(); void footer(); void nowTimeForFooter(); /* 列表动态行处理函数 我们把一行分为5个部分,即开始符“|”,左显示字符区, 中间空格区,右显示字符区,结束符号“|”,我们给函数 传入左显示字符和右显示字符区,由程序计算剩余空间, 在中间填满空格,使程序可以动态处理。 例如:word("hello","world");则: | hello world| 开始符↑ ↑左显示字符区 ↑中间空格区 右显示字符区↑ ↑结束符 */ void word(char * front, char * back){ int count = strlen(front) + strlen(back);//两边字符求和 if ((count <= 50)){//总字符不超过50 int left = 57 - count;//剩余字符数 char fin[60] = "| ";//定义60字符,开始是“|” char * blank = { " " }; char * backblack = " |\n"; strcat(fin, front);//粘贴左显示字符区到fin for (int i = 1; i <= left - 5; i++){ strcat(fin, blank); }//粘贴空格 strcat(fin, back);//粘贴右显示字符区到fin strcat(fin, backblack); printf("%s", fin);//打印整行 } else{ word("发生意外:传递的字符串超过最大长度", "");//溢出处理 dush(); } } //全行空白的情况 void blank(){ printf("|"); for (int i = 1; i <= 55; i++)printf(" "); printf("|\n"); } //全行横线分隔符 void dush(){ printf("|"); for (int i = 1; i <= 55; i++)printf("-"); printf("|\n"); } //定义头部显示 void header(){ dush(); word("单词世界WordWorld", "Dmjsz制作"); dush(); blank(); } //定义尾部显示 void footer(){ blank(); dush(); nowTimeForFooter(); dush(); } //头部专用时间处理函数 void nowTimeForFooter(){ SYSTEMTIME sys; GetLocalTime(&sys); char temptimer[10] = ""; char timer[30] = ""; //分别获取年月日时分秒,保存到数组中 int item[6] = { sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond }; for (int i = 0; i <= 5; i++){//遍历数组 //将数字转换为字符数组,否则没法使用strcat函数 _itoa(item[i], temptimer, 10); //年与月和月与日之间使用“-”分割 if (i == 1 || i == 2){ strcat(timer, "-"); } //日与时之间使用空格分割 else if (i == 3){ strcat(timer, " "); } //时与分和分与秒之间使用“:”分割 else if (i == 4 || i == 5){ strcat(timer, ":"); } //如果小于10的数字则前面补0 if (item[i] <= 9){ strcat(timer, "0"); } strcat(timer, temptimer); } word("CopyRight 2016 dmjsz", timer); } //数据库专用时间处理函数 //总体与前一个函数相似 char* nowTime(int state){ SYSTEMTIME sys; GetLocalTime(&sys); char temptimer[10] = ""; char timer[30] = ""; int item[6] = { sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond }; for (int i = 0; i <= 5; i++){ _itoa(item[i], temptimer, 10); if (i == 1 || i == 2){ strcat(timer, "-"); } else if (i == 3){ strcat(timer, " "); } else if (i == 4 || i == 5){ strcat(timer, ":"); } if (item[i] <= 9){ strcat(timer, "0"); } strcat(timer, temptimer); } char date[11] = ""; strncpy(date, timer, 10); switch (state){ case 1:return timer; break; case 2:return date; } } /*测定时间流逝的函数*/ long int timePast(){ SYSTEMTIME sys; GetLocalTime(&sys); long int secondR = sys.wDay * 60 * 60 * 24 + sys.wHour * 60 * 60 + sys.wMinute * 60 + sys.wSecond; return secondR; } /*SQL查询函数*/ char* query_sql(char* sql) { char result[30000] = ""; MYSQL my_connection;//一个数据库连接 int res;//sql返回位 MYSQL_RES *res_ptr;//查询结果指针 MYSQL_FIELD *field;//字段结构指针 MYSQL_ROW result_row;//按照行返回查询信息 int row, column;//返回行数与列数 int i, j;//循环控制变量 mysql_init(&my_connection);//初始化连接 if (mysql_real_connect(&my_connection, host, USERNAME, PASSWORD, DATABASE, 0, NULL, CLIENT_FOUND_ROWS)) {//不为空连接成功 mysql_query(&my_connection, "set names utf8");//支持中文 res = mysql_query(&my_connection, sql); if (res) { word("数据库查询连接失败!", ""); mysql_close(&my_connection);//关闭连接 } else { res_ptr = mysql_store_result(&my_connection); if (res_ptr) { column = mysql_num_fields(res_ptr); row = mysql_num_rows(res_ptr) + 1; //以行的形式输出结果 for (i = 1; i < row; i++) { result_row = mysql_fetch_row(res_ptr); for (j = 0; j < column; j++){ strcat(result, "#"); strcat(result, result_row[j]); } } } strcat(result, "#"); mysql_close(&my_connection); char *p = result; return p; } } } /*SQL执行函数,与插入类似,相同注释不再描述*/ void exe_sql(char* sql) { MYSQL my_connection; int res; mysql_init(&my_connection); if (mysql_real_connect(&my_connection, host, USERNAME, PASSWORD, DATABASE, 0, NULL, CLIENT_FOUND_ROWS)) { mysql_query(&my_connection, "set names utf8"); res = mysql_query(&my_connection, sql); if (res) { mysql_close(&my_connection); } else { mysql_close(&my_connection); } } else { word("数据库执行结果失败!", ""); } } /*查询ip函数*/ char* ipadd() { WSADATA wsaData; char name[255]; char *ip; PHOSTENT hostinfo; if (WSAStartup(MAKEWORD(2, 0), &wsaData) == 0) { if (gethostname(name, sizeof(name)) == 0) { if ((hostinfo = gethostbyname(name)) != NULL) { ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list); return ip; } } WSACleanup(); } } /*更改词库函数*/ void changeDic(){ system("cls"); header(); word("请选择需要更换的词库类别", ""); blank(); word("输入序号并回车!", ""); word("1--->大学英语4级", ""); word("2--->大学英语6级", ""); footer(); char c = getchar()-'0'; switch (c){ case 1:strcpy(wordPath, "dic//4.ewf"); wordAllNum = 3160; word("更换完成!",""); Sleep(2000); getUserMainFrame(1); break; case 2:strcpy(wordPath, "dic//6.ewf"); wordAllNum = 1285; word("更换完成!", ""); Sleep(2000); getUserMainFrame(1); break; default: word("选择错误!", ""); Sleep(2000); changeDic(); } } /* 获取开始窗口,其实函数形参等待接受不同的阶段, 本函数本身不执行,而是专门给getStartFunction函数执行的 */ int getStartFrame(int state){ //Windows API,取得句柄 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //定义控制台颜色为纯白 SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); //清空屏幕 system("cls"); header(); switch (state){ case 1: word("------>正在检查网络情况...", ""); break; case 2: word(" 网络连通正常,数据传输速度正常!", ""); blank(); word("------>正在检查核心组件...", ""); break; case 3: word(" 网络连通正常,数据传输速度正常!", ""); blank(); word(" 组件测试通过,核心文件正常!", ""); blank(); word("------>正在与远程服务器进行握手... ", ""); break; case 4: word(" 网络连通正常,数据传输速度正常!", ""); blank(); word(" 组件测试通过,核心文件正常!", ""); blank(); word(" 与服务器握手成功,没有更新信息!", ""); blank(); word("------>正在等待数据传输完毕...", ""); break; case -2: word(" 网络连通异常,请检查网络是否正确连接!", ""); break; break; case -3: word(" 网络连通正常,数据传输速度正常!", ""); blank(); word(" 缺少必要的核心组件!", ""); break; case -4: word(" 网络连通正常,数据传输速度正常!", ""); blank(); word(" 组件测试通过,核心文件正常!", ""); blank(); word(" ------>没有正确的和远程服务器取得联系!", ""); blank(); word(" 请输入一个新的数据服务器地址,回车确认!", ""); footer(); gets(host); getStartFunction(2); break; } footer(); return 0; } /* 开始函数,各项功能检查,也是程序的起点 */ void getStartFunction(int state){ FILE * fp; switch (state){ case 1: printf("正在检查网络连通情况,请稍后..."); //114.114.114.114是中国电信DNS,用它来测试网络连通性 if (system("ping -n 1 114.114.114.114")){//如果返回值是0 getStartFrame(-2);//网络不通 } else{ getStartFrame(2);//打开第二个检查窗口 Sleep(2000); getStartFunction(2); //开始检查第二项 } break; case 2: fp = fopen(wordPath, "r");//测试词库文件是否存在 if (fp == NULL) { getStartFrame(-3); } else { fclose(fp);//关闭词库 Sleep(2000); getStartFrame(3); //打开第三个检查窗口 getStartFunction(3); //开始检查第三项 } break; case 3: if (query_sql("select * from user;") == NULL){ //检查数据库是否连通 getStartFrame(-4); } else { Sleep(2000); getStartFrame(4); getStartFunction(4); } break; case 4:{ Sleep(2000); getWelcomeFrame(1); }//所有检查通过,进入欢迎页面 } } /* 欢迎屏幕的滚动效果 */ void getWelcomeFunction(){ char welword[21] = "Welcome To WordWorld";//定义字符串 char *p1 = welword; char container[21] = ""; char *p2 = container; //屏幕逐个字符显示效果,定义p1指针指向原字符串, //p2指针指向空的新字符串,每隔0.2秒拷贝一个字符, //实现字母滚动效果 while (*p1 != 0){ Sleep(200); system("cls"); *p2 = *p1; p1 += 1; p2 += 1; dush(); word(container, "欢迎来到单词世界!"); } blank(); word("您需要登录账户与全世界的朋友一起并肩作战!", ""); blank(); word("创立账户请按[N],登录已有账户请按[L]", ""); blank(); word("--->服务大区:南方电信专区 切换[C]", ""); blank(); footer(); } /* 欢迎屏幕的框架 */ void getWelcomeFrame(int area){ if (area == 1){//如果不检查area,每次切换大区就要重启本函数, //那么滚动效果也就要再出现一次,显然没有这样的必要, //所以,只在第一次显示欢迎屏幕的时候播放字符滚动效果 char welword[21] = "Welcome To WordWorld"; char *p1 = welword; char container[21] = ""; char *p2 = container; while (*p1 != 0){ Sleep(200); system("cls"); *p2 = *p1; p1 += 1; p2 += 1; dush(); word(container, "欢迎来到单词世界!"); } } else{ system("cls"); dush(); word("Welcome To WordWorld", "欢迎来到单词世界!"); } blank(); word("您需要登录账户与全世界的朋友一起并肩作战!", ""); blank(); word("创立账户请按[N],登录已有账户请按[L],关闭请按[X]", ""); blank(); if (area % 2 == 1){ //南方北方轮换显示 word("--->服务大区:南方电信专区 切换[C]", ""); server = 1; } else{ word("--->服务大区:北方网通专区 切换[C]", ""); server = 2; } blank(); footer(); //获取字符输入 while (!_kbhit())break; char f = _getch(); if (f == 'C' || f == 'c'){ getWelcomeFrame(area + 1); } if (f == 'X' || f == 'x'){ exit(0); } if (f == 'N' || f == 'n'){ getRegFrame(1); } if (f == 'L' || f == 'l'){ getLoginFrame(1); } getWelcomeFrame(1); } /* 注册账号函数 当state=1时是输入用户名的操作,state=2时是确认密码的操作 */ void getRegFrame(int state){ switch (state){ case 1: system("cls"); header(); word("注册账号", ""); blank(); word("------>请输入您的用户名,回车确认", ""); blank(); word(" 稍后将输入密码", ""); blank(); footer(); while (1){ gets(username); if (strlen(username) <= 15){ getRegFrame(2);//转入密码输入流程 } else{ //判断字符防止过大 printf("请输入少于15个字符的用户名!"); } } case 2:system("cls"); header(); word("注册账号", ""); blank(); char tempstr[200] = ""; strcat(tempstr, "你好,"); strcat(tempstr, username); strcat(tempstr, "。欢迎加入我们!"); word(tempstr, ""); blank(); word("------>请输入您的密码,回车确认!", ""); blank(); footer(); while (1){ //密码显示*号 char password[50] = ""; char add[200] = ""; char ch = '\0'; int i = 0; while (ch != '\r') { ch = _getch(); if (ch == '\r') { password[i] = '\0'; break; } if (ch != '\b') { putchar('*'); password[i] = ch; i++; } else { getRegFrame(2); } } printf("\n"); printf("正在查询远程数据表...... \n"); //向数据库插入新用户数据,同时在配置数据库时,注意把 //username字段设置为唯一,当已存在同名用户时,新用户 //将无法创建。 if (strlen(password) <= 15){ char p[200] = "insert into user(username,password,\ saying,ipadd,lastlogin) values('"; strcat(p, username); strcat(p, "','"); strcat(p, password); strcat(p, "','"); strcat(p, "No Saying!"); strcat(p, "','"); strcat(p, ipadd()); strcat(p, "','"); strcat(p, nowTime(1)); strcat(p, "');"); char *exe = p; exe_sql(exe); getLoginFrame(1); } else{ printf("请输入少于15个字符的密码!"); } } } } /* 登录账号函数 当state=1时是输入用户名的操作,state=2时是确认密码的操作 */ void getLoginFrame(int state){ switch (state){ case 1: system("cls"); header(); word("登陆账号", ""); blank(); word("------>请输入您的用户名,回车确认", ""); blank(); word(" 稍后将输入密码", ""); blank(); blank(); dush(); char temp[11] = ""; strcpy(temp, nowTime(2)); word("CopyRight 2016 dmjsz", temp); dush(); while (1){ gets(username); if (strlen(username) <= 15){ getLoginFrame(2); } else{ printf("请输入少于15个字符的用户名!"); //判断字符防止过大 } } case 2:system("cls"); header(); word("登录账号", ""); blank(); char tempstr[200] = ""; strcat(tempstr, "你好,"); strcat(tempstr, username); strcat(tempstr, "。欢迎回来!"); word(tempstr, ""); blank(); word("------>请输入您的密码,回车确认!", ""); blank(); footer(); if (isLoged == 0){//当没有登录时 char password[50] = ""; char sqlw[200] = ""; char ch = '\0'; int i = 0; //密码显示*号 while (ch != '\r') { ch = _getch(); if (ch == '\r') { password[i] = '\0'; break; } if (ch != '\b') { putchar('*'); password[i] = ch; i++; } else { getLoginFrame(2); } } printf("\n"); //执行登录语句 if (strlen(password) <= 15){ char sqlw[200] = ""; char *p; printf("正在查询远程数据表...... \n"); strcat(sqlw, "select password from user where username='"); strcat(sqlw, username); strcat(sqlw, "';"); p = query_sql(sqlw); char temp[20] = ""; dealSql(p, temp); if (strcmp(password, temp) == 0){ printf("登录成功"); isLoged = 1; getUserMainFrame(1); return; } else{ printf("登陆失败,任意键继续!"); getchar(); getLoginFrame(2); } } else{ printf("请输入少于15个字符的密码!"); } getWelcomeFrame(1); } } } /* 主窗口函数 */ void getUserMainFrame(int state){ switch (state){ case 1: system("cls"); char news1[80] = ""; char news2[80] = ""; char score[200] = ""; char coin[10] = ""; char sqlw[200] = ""; char systemstate[50] = ""; //定义大量数组保存不同数据! char dealSqlStr[200] = ""; char dealSqlStr2[200] = ""; char dealSqlStr3[200] = ""; char dealSqlStr4[200] = ""; char dealSqlStr5[200] = ""; char dealSqlStr6[200] = ""; char lastlogin[200] = ""; char stage[200] = ""; printf("正在查询远程数据表...... \n"); //查新新闻1 strcpy(sqlw, "select news1 from system where version=1;"); dealSql(query_sql(sqlw), dealSqlStr); strcpy(news1, dealSqlStr); //查新闻2 strcpy(sqlw, "select news2 from system where version=1;"); dealSql(query_sql(sqlw), dealSqlStr6); strcpy(news2, dealSqlStr6); //获取系统状态 strcpy(sqlw, "select systemstate from system where version=1;"); dealSql(query_sql(sqlw), dealSqlStr5); strcpy(systemstate, dealSqlStr5); //如果系统状态为0,表示整个系统被关闭, //那么除了admin其它用户将不能进入 if ((strcmp(systemstate, "0") == 0) && (strcmp(username, "admin") != 0)){ printf("系统已被管理员关闭!\n请联系管理员!\n任意键退出!\n"); getchar(); exit(0); } //向数据表查询用户信息 //查询用户分数 strcpy(sqlw, "select score from user where username='"); strcat(sqlw, username); strcat(sqlw, "';"); dealSql(query_sql(sqlw), dealSqlStr4); strcpy(score, dealSqlStr4); //查询用户硬币 strcpy(sqlw, "select coin from user where username='"); strcat(sqlw, username); strcat(sqlw, "';"); dealSql(query_sql(sqlw), dealSqlStr2); strcpy(coin, dealSqlStr2); //查询用户最后登录时间 strcpy(sqlw, "select lastlogin from user where username='"); strcat(sqlw, username); strcat(sqlw, "';"); dealSql(query_sql(sqlw), dealSqlStr2); strcpy(lastlogin, dealSqlStr2); //查询用户等级 strcpy(sqlw, "select stage from user where username='"); strcat(sqlw, username); strcat(sqlw, "';"); dealSql(query_sql(sqlw), dealSqlStr3); strcpy(stage, dealSqlStr3); //更新登录时间 strcpy(sqlw, "update user set lastlogin='"); strcat(sqlw, nowTime(1)); strcat(sqlw, "' where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); //更新用户ip地址 strcpy(sqlw, "update user set ipadd='"); strcat(sqlw, ipadd()); strcat(sqlw, "' where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); *exe = sqlw; exe_sql(exe); system("cls"); //定义控制台大小 system("mode con cols=58 lines=32"); header(); word("全区新闻", ""); word(news1, ""); word(news2, ""); dush(); blank(); char temp[200] = " 欢迎!"; strcat(temp, username); strcat(temp, ",最近登录时间:"); strcat(temp, lastlogin); word(temp, ""); char info[200] = " 等级--->"; strcat(info, stage); strcat(info, " 积分--->"); strcat(info, score); word(info, ""); char info2[200] = ""; strcat(info2, " 硬币--->"); strcat(info2, coin); word(info2, ""); dush(); blank(); word(" 请选择功能:", ""); blank(); word(" 世界对战[B]", "赛外练习[P] "); blank(); word(" 大区排名[L]", "词库管理[R] "); blank(); word(" 修改口号[S]", "修改密码[W] "); blank(); word(" 注册用户[M]", "切换用户[C] "); blank(); if (strcmp(username, "admin") == 0){//只有是管理员才显示系统相关的更改选项 word(" 修改新闻[N]", "关闭系统[E] "); blank(); } footer(); //获取用户输入 while (!_kbhit())break; char f = _getch(); if (f == 'X' || f == 'x'){ exit(0); } if (f == 'B' || f == 'b'){ worldButtleSearchFrame(); } if (f == 'P' || f == 'p'){ practiceFrame(1, 0); } if (f == 'L' || f == 'l'){ scorelist(); } if (f == 'R' || f == 'r'){ changeDic(); } if (f == 'W' || f == 'w'){ changePassword(); } if (f == 'S' || f == 's'){ changeSaying(); } if (f == 'M' || f == 'm'){ isLoged = 0; getRegFrame(1); } if (f == 'C' || f == 'c'){ isLoged = 0; getLoginFrame(1); } if (strcmp(username, "admin") == 0){//如果是管理员 if (f == 'N' || f == 'n'){ changeNews(); } if (f == 'E' || f == 'e'){ closeSystem(); } } getUserMainFrame(1); } } /* 管理员更改新闻函数,涉及到数据库插入 */ void changeNews(){ system("cls"); printf("请问你要更改第几条新闻?按数字1或2回答。\n"); while (!_kbhit())break; char f = _getch(); if (f == '1'){ printf("请输入第一条新闻内容:\n"); char content[55] = ""; gets(content); if (strlen(content) < 50){ char sqlw[200] = "update system set news1='"; strcat(sqlw, content); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); printf("新闻更改完毕!任意键确认!\n"); getchar(); getUserMainFrame(1); } else{ printf("请输入少于50个字符的新闻!任意键确认!\n"); getchar(); changeNews(); } } if (f == '2'){ printf("请输入第二条新闻内容:\n"); char content[55] = ""; gets(content); if (strlen(content) < 50){ char sqlw[200] = "update system set news2='"; strcat(sqlw, content); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); printf("新闻更改完毕!任意键确认!\n"); getchar(); getUserMainFrame(1); } else{ printf("请输入少于50个字符的新闻!任意键确认!\n"); getchar(); changeNews(); } } changeNews(); } /* 关闭系统的函数,主要是修改system表中的systemstate字段 */ void closeSystem(){ system("cls"); char sqlw[200] = ""; char systemstate[50] = ""; char dealSqlStr[200] = ""; strcpy(sqlw, "select systemstate from system where version=1;"); dealSql(query_sql(sqlw), dealSqlStr); strcpy(systemstate, dealSqlStr); if (strcmp(systemstate, "1") == 0){ printf("警告!关闭系统后所有用户不能正常登录!\n"); printf("输入Y确定,输入N取消!\n"); while (!_kbhit())break; char f = _getch(); if (f == 'N' || f == 'n'){ getUserMainFrame(1); } if (f == 'Y' || f == 'y'){ char p[100] = "update system set systemstate=0"; char *exe = p; exe_sql(exe); printf("系统已经关闭!任意键返回!\n"); getchar(); getUserMainFrame(1); } } if (strcmp(systemstate, "0") == 0){ printf("是否开启系统?\n"); printf("输入Y确定,输入N取消!\n"); while (!_kbhit())break; char f = _getch(); if (f == 'N' || f == 'n'){ getUserMainFrame(1); } if (f == 'Y' || f == 'y'){ char p[100] = "update system set systemstate=1"; char *exe = p; exe_sql(exe); printf("系统已经开启!任意键返回!\n"); getchar(); getUserMainFrame(1); } } } /* 用户修改自己的口号 */ void changeSaying(){ system("cls"); header(); word("请输入新的口号,回车确定!", ""); footer(); char sqlw[200] = ""; char newPassword[50] = ""; gets(newPassword); if (strlen(newPassword) >= 15){ printf("请输入小于15个字符的口号!任意键继续!"); getchar(); changePassword(); } else{ strcpy(sqlw, "update user set saying='"); strcat(sqlw, newPassword); strcat(sqlw, "' where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); printf("口号更改成功!任意键继续!"); getchar(); getUserMainFrame(1); } } /* 用户更改自己的密码 */ void changePassword(){ system("cls"); dush(); word("单词世界WordWorld", "Dmjsz制作[X]"); dush(); blank(); word("请输入新的密码,回车确定!", ""); blank(); footer(); char sqlw[200] = ""; char newPassword[50] = ""; char ch = '\0'; int i = 0; while (ch != '\r') { ch = _getch(); if (ch == '\r') { newPassword[i] = '\0'; break; } if (ch != '\b') { putchar('*'); newPassword[i] = ch; i++; } else { changePassword(); } } printf("\n"); if (strlen(newPassword) >= 15){ printf("请输入小于15个字符的密码!任意键继续!"); getchar(); changePassword(); } else{ strcpy(sqlw, "update user set password='"); strcat(sqlw, newPassword); strcat(sqlw, "' where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); printf("密码更改成功!任意键继续!"); getchar(); getUserMainFrame(1); } } //显示排名最高的6个用户 void scorelist(){ char sqlw[200] = ""; char dealSqlStr[2000] = ""; char list[2000] = ""; strcpy(sqlw, "SELECT username, score,saying FROM user \ ORDER BY score DESC LIMIT 0 , 6;"); strcpy(dealSqlStr, query_sql(sqlw)); strcpy(list, dealSqlStr); char strCollection2[300][200] = { "" }; char *p = dealSqlStr; int i = 0; int j = 0; int k = 0; while (k < strlen(dealSqlStr)){ if (k == 0){ i++; k++; continue; } if (*p != '#'){ strCollection2[i][j] = *p; p++; j++; } else{ p++; i++; j = 0; } k++; } int count = 0; char temp[200] = ""; system("mode con cols=58 lines=30"); header(); for (i = 0; i < 30; i++){ for (j = 0; j < 20; j++){ if (strCollection2[i][j] == NULL)continue; if (j == 0){ count++; if (count == 1){ strcat(temp, "第"); char temp3[10] = ""; _itoa((i + 1) / 3, temp3, 10); strcat(temp, temp3); strcat(temp, "名,名称:"); strcat(temp, &strCollection2[i][j]); strcat(temp, " 积分:"); } if (count == 2){ strcat(temp, &strCollection2[i][j]); } if (count == 3){ strcpy(temp, "签名:"); strcat(temp, &strCollection2[i][j]); strcat(temp, "。"); } if (count == 2){ word(temp, ""); } if (count == 3){ word(temp, ""); blank(); count = 0; strcpy(temp, ""); } } } } dush(); strcpy(temp, nowTime(2)); word("按q键返回主界面!", ""); footer(); while (!_kbhit())break; char f = _getch(); if (f == 'Q' || f == 'q'){ getUserMainFrame(1); } } /* 世界对战搜索页面 */ void worldButtleSearchFrame(){ system("cls"); system("mode con cols=58 lines=28"); header(); word("搜索对手中...", ""); blank(); dush(); word("已经找到的对手:", ""); blank(); char agname[500] = ""; char sqlw[200] = ""; char old[500] = ""; strcpy(sqlw, "update user set buttlestate=1"); strcat(sqlw, " where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); //获取用户的对战状态 strcpy(sqlw, "select username,score,saying from user where buttlestate=1;"); strcpy(agname, query_sql(sqlw)); strcpy(old, agname); char strCollection[30][20] = { "" }; char *p = agname; int i = 0; int j = 0; int k = 0; while (k < strlen(agname)){ if (k == 0){ i++; k++; continue; } if (*p != '#'){ strCollection[i][j] = *p; p++; j++; } else{ p++; i++; j = 0; } k++; } int count = 0; char temp[200] = ""; for (i = 0; i < 30; i++){ for (j = 0; j < 20; j++){ //如果姓名为null表示没有对手了 if (strCollection[i][j] == NULL)continue; if (j == 0){ count++; if (count == 1){ strcat(temp, "--->对手姓名:"); strcat(temp, &strCollection[i][j]); strcpy(ag[agCounter].name, &strCollection[i][j]); strcat(temp, " 对手积分:"); } if (count == 2){ strcat(temp, &strCollection[i][j]); strcpy(ag[agCounter].score, &strCollection[i][j]); agCounter++; } if (count == 3){ strcpy(temp, " 个性签名:"); strcat(temp, &strCollection[i][j]); strcat(temp, "。"); } if (count == 2){ word(temp, ""); } if (count == 3){ word(temp, ""); blank(); count = 0; strcpy(temp, ""); } } } } footer(); int second = 0; //秒数 int person = 0;//对战人数 //每过5秒刷新一次 for (second = 60;second >= 0; second -= 5){ strcpy(agname, query_sql(sqlw)); if (strcmp(old, agname) != 0){ worldButtleSearchFrame(); } strcpy(old, agname); person++; Sleep(5000); } if (person == 0){//如果没有人对战 printf("等待超时,任意键返回!"); getchar(); getUserMainFrame(1); } else{ worldButtleFrame(0, 1); } } /* 由于数据库查询的数据是带有#号分割的,这个函数专门是去掉#号的 */ void dealSql(char *old, char *new){ char *p1 = ""; char *p2 = ""; p1 = old; p2 = new; while (*p1 != NULL){ if (*p1 != '#'){ *p2 = *p1; p2++; }; p1++; } strcat(new, "\0"); strcat(old, "\0"); } /* 处理词库文件函数 由于我从网上下载的词库带有音标 例如 book /book/ .书 所以这个函数将字符串开头到第一个/符号作为单词 第一个.到结尾作为翻译保存 */ void dealFile(int i, char* english, char *chinese){ FILE *fp; int WhichLine = i; int CurrentIndex = 0; char StrLine[1024]; if ((fp = fopen(wordPath, "r")) == NULL) { printf("词库文件不存在!"); return NULL; } while (!feof(fp)) { if (CurrentIndex == WhichLine) { fgets(StrLine, 1024, fp); break; } fgets(StrLine, 1024, fp); CurrentIndex++; } fclose(fp); char *p1; char *p2; int pos = 0; int first = 0; int second = 0; int fristMark = 0; int secondMark = 0; int third = 0; int thirdMark = 0; p1 = StrLine; while (pos <= strlen(StrLine)){ if (*p1 == '/'&&first == 0){ fristMark = 1; //记录第一标记位 first = pos; } if (*p1 == '.'&&secondMark == 0){ secondMark = 1; //记录第二标记位 second = pos; } if (*p1 == '\n'&&thirdMark == 0){ thirdMark = 1; //记录第三标记位 third = pos; } p1++; pos++; } char temp1[200] = ""; strncpy(temp1, StrLine, first); strcat(temp1, "\0"); char temp2[200] = ""; strncpy(temp2, StrLine + second + 1, third); strcat(temp2, "\0"); strcpy(english, temp1); strcpy(chinese, temp2); } /* 对战函数 对战时,反复递归调用,并传入新的值以控制比赛 */ int worldButtleFrame(int right, int stage){ if (stage == 1){ //如果处在第一阶段,那么首先清空对战状态,以防止其它对手的匹配 char sqlw[200] = ""; firstTimer = timePast(); strcpy(sqlw, "update user set buttlestate=0"); strcat(sqlw, " where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); } system("cls"); system("mode con cols=58 lines=22"); header(); char sign[200] = "还剩下"; char num[5] = ""; _itoa(10 - stage, num, 10); strcat(sign, num); strcat(sign, "题!,时间还有"); strcpy(num, ""); long int temp = timePast(); _itoa(180 - (temp - firstTimer), num, 10); strcat(sign, num); strcat(sign, "秒"); word(username, sign); dush(); blank(); word("请根据中文写出英文对应的单词", ""); blank(); char a[100] = "aaa"; char b[100] = "bbb"; //随机数抽取题号 int rd = rand() % wordAllNum; //抽取中文和英文 dealFile(rd, a, b); char letter[20] = "<---共"; strcpy(num, ""); _itoa(strlen(a), num, 10); strcat(letter, num); strcat(letter, "个字母!"); word(b, letter); blank(); dush(); word("请输入单词,回车确定:", ""); footer(); char userenter[200] = ""; gets(userenter); if (stage >= 10){ //当题目计数大于10的时候开始进入等待界面 worldButtleWaitingFrame(right, username); return 0; } if (strcmp(userenter, a) == 0){ printf("正确!"); Sleep(500); right++; stage++; worldButtleFrame(right, stage); } else{ printf("错误!\n"); printf("正确答案:%s", a); Sleep(2000); stage++; worldButtleFrame(right, stage); } } /* 练习模块函数 就是不需要等待匹配对手,没有时间限制 */ int practiceFrame(int right, int stage){ system("cls"); system("mode con cols=58 lines=22"); header(); char sign[200] = "还剩下"; char num[5] = ""; _itoa(10 - stage, num, 10); strcat(sign, num); strcat(sign, "题!"); word(username, sign); dush(); blank(); word("请根据中文写出英文对应的单词", ""); blank(); char a[100] = "aaa"; char b[100] = "bbb"; int rd = rand() % wordAllNum; dealFile(rd, a, b); char letter[20] = "<---共"; strcpy(num, ""); _itoa(strlen(a), num, 10); strcat(letter, num); strcat(letter, "个字母!"); word(b, letter); blank(); dush(); word("请输入单词,回车确定:", ""); footer(); char userenter[200] = ""; gets(userenter); if (stage >= 10){ getUserMainFrame(1); return 0; } if (strcmp(userenter, a) == 0){ printf("正确!"); Sleep(500); right++; stage++; practiceFrame(right, stage); } else{ printf("错误!\n"); printf("正确答案:%s", a); Sleep(2000); stage++; practiceFrame(right, stage); } } /* 等待对手完成的函数 在这期间会进行分数比对工作,超时将不能参与排名 */ void worldButtleWaitingFrame(int right, char *username){ char sqlw[200] = ""; char agname[200] = ""; char score[10] = ""; int scoreInt = 0; int tempInt = 0; strcpy(sqlw, "select score from user where username='"); strcat(sqlw, username); strcat(sqlw, "';"); strcpy(score, query_sql(sqlw)); char dealSqlInt[10] = ""; //单独对sql的#号处理 strncpy(dealSqlInt, score + 1, strlen(score) - 2); scoreInt = atoi(dealSqlInt); scoreInt = scoreInt + right * 10; strcpy(sqlw, "update user set score="); _itoa(scoreInt, score, 10); strcat(sqlw, score); strcat(sqlw, " where username = '"); strcat(sqlw, username); strcat(sqlw, "';"); char *exe = sqlw; exe_sql(exe); system("cls"); system("mode con cols=58 lines=28"); header(); char sign[50] = "最长等待时间"; char num[5] = ""; strcpy(num, ""); long int temp = timePast(); //最长等待时间也是根据完成时间定义的 _itoa(180 - (temp - firstTimer), num, 10); strcat(sign, num); strcat(sign, "秒"); if ((180 - (temp - firstTimer))>0){ word("等待对手完成中...", sign); } else{ word("您已超时,本次测验不计分!", ""); blank(); word("5秒后自动关闭本页面!", ""); Sleep(5000); getUserMainFrame(1); } footer(); //睡眠到倒计时结束为止,使得大家时间同步 Sleep(((180 - (temp - firstTimer)) + 2) * 1000); worldButtleResultFrame(); } /* 对战结果函数 */ void worldButtleResultFrame(){ system("cls"); system("mode con cols=58 lines=28"); header(); word("结果统计表", ""); blank(); dush(); word("成绩是:", ""); char temp[20] = ""; char sqlw[200] = ""; for (int i = 0; i < agCounter; i++){ if (ag[i].name != NULL){ char name[20] = ""; //拷贝对手姓名 strcpy(name, ag[i].name); int oldscore = atoi(ag[i].score); char score[10] = ""; //查询对手分数 strcpy(sqlw, "select score from user where username='"); strcat(sqlw, name); strcat(sqlw, "';"); strcpy(score, query_sql(sqlw)); char dealSqlInt[10] = "";//单独对sql的#号处理 strncpy(dealSqlInt, score + 1, strlen(score) - 2); int newscore = atoi(dealSqlInt); char temp[200] = ""; if (oldscore != newscore){//如果发现对手的分数发生了变化 char dealNum[5] = ""; int scorechange = newscore - oldscore; int right = scorechange / 10; _itoa(right, dealNum, 10);//int转char数组 strcpy(temp, name); strcat(temp, "--->答对"); strcat(temp, dealNum); strcat(temp, "题,积"); _itoa(scorechange, dealNum, 10); strcat(temp, dealNum); strcat(temp, "分!"); word(temp, ""); } else{//如果对手分数没有变化 strcpy(temp, name); strcat(temp, ",超时或全错,没有成绩!"); word(temp, ""); } } } footer(); getchar(); agCounter = 0;//对战人数归零,等待新一波的对战 getUserMainFrame(1); } /*主函数*/ int main(int argc, char *argv[]) { getStartFunction(1);//调用起始函数 getchar(); return 0; }