本文以及程序代碼原創,謝絕轉載!
最近的一個項目,練手用的,大概一個星期的開發時間,不過每天寫代碼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; }