本文以及程序代码原创,谢绝转载!
最近的一个项目,练手用的,大概一个星期的开发时间,不过每天写代码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;
}












Comments NOTHING