#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <algorithm>
#include <sstream>
#include <windows.h>
#include <vector>
#include <limits>
using namespace std;

const string VERSION = "v3.0.0";
const string ADMIN_USER = "admin";
const string ADMIN_PWD = "admin123";
const string USER_FILE = "users.txt";
const string CALC_HISTORY_FILE = "calc_history.txt";
const string GOBANG_HISTORY_FILE = "gobang_history.txt";
const string NOTE_FILE = "notes.txt";
const string ANNOUNCEMENT_FILE = "announcement.txt";

enum class LanguageType { CHINESE, ENGLISH };
LanguageType currentLang = LanguageType::CHINESE;

enum class ConsoleColor {
	BLACK = 0, RED = 1, GREEN = 2, YELLOW = 3, BLUE = 4, PURPLE = 5, CYAN = 6, WHITE = 7,
	GRAY = 8, LIGHT_RED = 9, LIGHT_GREEN = 10, LIGHT_YELLOW = 11, LIGHT_BLUE = 12,
	LIGHT_PURPLE = 13, LIGHT_CYAN = 14, LIGHT_WHITE = 15
};

struct AppState {
	string loginUsername;
	bool isAdmin = false;
	bool isRunning = true;
} appState;

void setConsoleColor(ConsoleColor textColor, ConsoleColor bgColor = ConsoleColor::BLACK) {
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	if (hConsole == INVALID_HANDLE_VALUE) return;
	SetConsoleTextAttribute(hConsole, ((int)bgColor << 4) | (int)textColor);
}

void resetConsoleColor() { setConsoleColor(ConsoleColor::LIGHT_WHITE, ConsoleColor::BLACK); }

void flushConsoleOutput() {
	cout << flush;
}

void clearConsole() {
	system("cls");
}

string simpleEncrypt(const string& input) {
	unsigned long long hash = 14695981039346656037ULL;
	for (char c : input) { hash ^= (unsigned char)c; hash *= 1099511628211ULL; }
	stringstream ss; ss << hex << hash;
	string result = ss.str();
	if (result.size() < 16) result = string(16 - result.size(), '0') + result;
	return result.substr(0, 16);
}

string getCurrentTime() {
	time_t now = time(nullptr);
	char buffer[80];
	strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localtime(&now));
	return string(buffer);
}

void clearInputBuffer() {
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

string getLocalText(const string& key) {
	if (currentLang == LanguageType::CHINESE) {
		if (key == "lang_choice") return "请选择语言:";
		if (key == "lang_cn") return "1. 中文";
		if (key == "lang_en") return "2. 英文";
		if (key == "login") return "登录";
		if (key == "register") return "注册";
		if (key == "username") return "用户名";
		if (key == "password") return "密码";
		if (key == "confirm_pwd") return "确认密码";
		if (key == "user_exist") return "错误:用户名已存在!";
		if (key == "pwd_not_match") return "错误:两次密码不一致!";
		if (key == "register_success") return "注册成功!";
		if (key == "user_not_exist") return "错误:用户名不存在!";
		if (key == "pwd_error") return "错误:密码错误!";
		if (key == "login_success") return "登录成功!";
		if (key == "choice") return "请选择";
		if (key == "invalid_choice") return "错误:无效的选择!";
		if (key == "goodbye") return "感谢使用,再见!";
		if (key == "exit") return "退出";
		if (key == "main_menu") return "===== 主菜单 =====";
		if (key == "calculator") return "大数计算器";
		if (key == "gobang") return "五子棋游戏";
		if (key == "notepad") return "记事本";
		if (key == "mini_games") return "小游戏合集";
		if (key == "tools") return "代码小工具";
		if (key == "calc_input") return "请输入计算式(exit退出):";
		if (key == "calc_result") return "计算结果:";
		if (key == "gobang_black") return "黑棋";
		if (key == "gobang_white") return "白棋";
		if (key == "gobang_win") return "获胜!";
		if (key == "gobang_draw") return "平局!";
		if (key == "coord_error") return "错误:坐标无效!";
		if (key == "chess_exist") return "错误:该位置已有棋子!";
		if (key == "note_edit") return "编辑记事本";
		if (key == "note_view") return "查看记事本";
		if (key == "guess_num") return "猜数字游戏";
		if (key == "minesweeper") return "简易扫雷";
		if (key == "random_num") return "随机数生成";
		if (key == "base_convert") return "进制转换";
		if (key == "string_tool") return "字符串处理";
		if (key == "stopwatch") return "秒表工具";
		if (key == "announcement_title") return "===== 系统公告 =====";
		if (key == "announcement_default") return "欢迎使用C++中心 v3.0.0!\n1. 默认管理员账号:admin,密码:admin123\n2. 所有操作记录将保存在本地文件中\n3. 如有问题请检查文件读写权限";
		if (key == "announcement_load_fail") return "提示:未找到公告文件,显示默认公告";
		if (key == "announcement_continue") return "按回车继续...";
		if (key == "calc_tip") return "支持:加减乘,输入exit退出";
		if (key == "gobang_tip") return "黑棋(X) 先行,白棋(O) 后行";
		if (key == "note_edit_tip") return "请输入内容(按Ctrl+Z回车结束输入):";
		if (key == "note_save_success") return "保存成功!";
		if (key == "note_open_fail") return "错误:无法打开文件!";
		if (key == "note_empty") return "记事本为空!";
		if (key == "guess_num_tip") return "我想了一个1-100的数字,你来猜猜!";
		if (key == "guess_num_small") return "太小了!";
		if (key == "guess_num_big") return "太大了!";
		if (key == "guess_num_success") return "恭喜!你用了%d次猜对了!";
		if (key == "minesweeper_tip") return "5x5扫雷,共5个地雷";
		if (key == "minesweeper_win") return "恭喜!你赢了!";
		if (key == "minesweeper_lose") return "踩雷了!游戏结束!";
		if (key == "minesweeper_revealed") return "该位置已揭开!";
		if (key == "random_num_min") return "输入最小值:";
		if (key == "random_num_max") return "输入最大值:";
		if (key == "random_num_result") return "随机数:%d";
		if (key == "random_num_max_error") return "最大值必须大于最小值!";
		if (key == "base_convert_num") return "输入十进制数:";
		if (key == "base_convert_type") return "转换为(2/8/16)进制:";
		if (key == "base_convert_result") return "转换结果:%s";
		if (key == "base_convert_error") return "请输入2/8/16!";
		if (key == "string_tool_input") return "输入字符串:";
		if (key == "string_tool_upper") return "1. 转大写:%s";
		if (key == "string_tool_lower") return "2. 转小写:%s";
		if (key == "string_tool_reverse") return "3. 反转:%s";
		if (key == "string_tool_length") return "4. 长度:%d";
		if (key == "stopwatch_start") return "按回车开始计时...";
		if (key == "stopwatch_running") return "计时中... 按回车结束!";
		if (key == "stopwatch_result") return "耗时:%.0f 秒";
		if (key == "input_number_error") return "请输入数字!";
		if (key == "input_range_error") return "请输入1-100之间的数字!";
		if (key == "minesweeper_input") return "输入要揭开的位置(行 列):";
		if (key == "continue_tip") return "按回车继续...";
		return "未知文本";
	} else {
		if (key == "lang_choice") return "Please select language:";
		if (key == "lang_cn") return "1. Chinese";
		if (key == "lang_en") return "2. English";
		if (key == "login") return "Login";
		if (key == "register") return "Register";
		if (key == "username") return "Username";
		if (key == "password") return "Password";
		if (key == "confirm_pwd") return "Confirm Password";
		if (key == "user_exist") return "Error: Username already exists!";
		if (key == "pwd_not_match") return "Error: Passwords do not match!";
		if (key == "register_success") return "Registration successful!";
		if (key == "user_not_exist") return "Error: Username does not exist!";
		if (key == "pwd_error") return "Error: Wrong password!";
		if (key == "login_success") return "Login successful!";
		if (key == "choice") return "Please choose";
		if (key == "invalid_choice") return "Error: Invalid choice!";
		if (key == "goodbye") return "Thanks for using, goodbye!";
		if (key == "exit") return "Exit";
		if (key == "main_menu") return "===== Main Menu =====";
		if (key == "calculator") return "Big Number Calculator";
		if (key == "gobang") return "Gobang Game";
		if (key == "notepad") return "Notepad";
		if (key == "mini_games") return "Mini Games";
		if (key == "tools") return "Code Tools";
		if (key == "calc_input") return "Enter calculation (exit to quit): ";
		if (key == "calc_result") return "Result: ";
		if (key == "gobang_black") return "Black";
		if (key == "gobang_white") return "White";
		if (key == "gobang_win") return "Win!";
		if (key == "gobang_draw") return "Draw!";
		if (key == "coord_error") return "Error: Invalid coordinates!";
		if (key == "chess_exist") return "Error: Chess already exists!";
		if (key == "note_edit") return "Edit Notepad";
		if (key == "note_view") return "View Notepad";
		if (key == "guess_num") return "Guess Number";
		if (key == "minesweeper") return "Minesweeper";
		if (key == "random_num") return "Random Num";
		if (key == "base_convert") return "Base Convert";
		if (key == "string_tool") return "String Tool";
		if (key == "stopwatch") return "Stopwatch";
		if (key == "announcement_title") return "===== Announcement =====";
		if (key == "announcement_default") return "Welcome to C++ Center v3.0.0!\nDefault admin: admin / admin123";
		if (key == "announcement_load_fail") return "File not found, use default";
		if (key == "announcement_continue") return "Press Enter to continue...";
		if (key == "calc_tip") return "Support +-*, exit to quit";
		if (key == "gobang_tip") return "Black(X) first, White(O) second";
		if (key == "note_edit_tip") return "Enter content (Ctrl+Z Enter to save): ";
		if (key == "note_save_success") return "Saved!";
		if (key == "note_open_fail") return "Error: Open file failed!";
		if (key == "note_empty") return "Note is empty!";
		if (key == "guess_num_tip") return "Guess 1-100!";
		if (key == "guess_num_small") return "Too small!";
		if (key == "guess_num_big") return "Too big!";
		if (key == "guess_num_success") return "Success! Used %d times!";
		if (key == "minesweeper_tip") return "5x5, 5 mines";
		if (key == "minesweeper_win") return "You win!";
		if (key == "minesweeper_lose") return "Boom! Game over!";
		if (key == "minesweeper_revealed") return "Already opened!";
		if (key == "random_num_min") return "Min: ";
		if (key == "random_num_max") return "Max: ";
		if (key == "random_num_result") return "Num: %d";
		if (key == "random_num_max_error") return "Max > min!";
		if (key == "base_convert_num") return "Decimal: ";
		if (key == "base_convert_type") return "To (2/8/16): ";
		if (key == "base_convert_result") return "Result: %s";
		if (key == "base_convert_error") return "Input 2/8/16!";
		if (key == "string_tool_input") return "String: ";
		if (key == "string_tool_upper") return "1. Upper: %s";
		if (key == "string_tool_lower") return "2. Lower: %s";
		if (key == "string_tool_reverse") return "3. Reverse: %s";
		if (key == "string_tool_length") return "4. Length: %d";
		if (key == "stopwatch_start") return "Enter to start...";
		if (key == "stopwatch_running") return "Timing... Enter to stop!";
		if (key == "stopwatch_result") return "Time: %.0f s";
		if (key == "input_number_error") return "Input number!";
		if (key == "input_range_error") return "1-100 only!";
		if (key == "minesweeper_input") return "Input (row col): ";
		if (key == "continue_tip") return "Press Enter...";
		return "Unknown Text";
	}
}

void showAnnouncement() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("announcement_title") << endl;
	resetConsoleColor();
	cout << endl;
	ifstream annFile(ANNOUNCEMENT_FILE);
	if (annFile.is_open()) {
		string line;
		while (getline(annFile, line)) {
			setConsoleColor(ConsoleColor::LIGHT_CYAN);
			cout << line << endl;
			resetConsoleColor();
		}
		annFile.close();
	} else {
		setConsoleColor(ConsoleColor::LIGHT_BLUE);
		cout << getLocalText("announcement_load_fail") << endl;
		resetConsoleColor();
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << getLocalText("announcement_default") << endl;
		resetConsoleColor();
	}
	cout << endl;
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << getLocalText("announcement_continue");
	resetConsoleColor();
	clearInputBuffer();
	cin.get();
}

void initAdminUser() {
	ifstream file(USER_FILE);
	if (!file.is_open()) {
		ofstream newFile(USER_FILE);
		if (newFile.is_open()) {
			newFile << ADMIN_USER << " " << simpleEncrypt(ADMIN_PWD) << endl;
			newFile.close();
		}
	}
	file.close();
}

bool checkUserExists(const string& username) {
	ifstream file(USER_FILE);
	if (!file.is_open()) return false;
	string user, pwd;
	while (file >> user >> pwd) {
		if (user == username) {
			file.close();
			return true;
		}
	}
	file.close();
	return false;
}

void registerNewUser() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "===== " << getLocalText("register") << " =====" << endl;
	resetConsoleColor();
	string username, password, confirmPwd;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("username") << ":";
	resetConsoleColor();
	cin >> username;
	if (checkUserExists(username)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("user_exist") << endl;
		resetConsoleColor();
		Sleep(1000);
		return;
	}
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("password") << ":";
	resetConsoleColor();
	cin >> password;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("confirm_pwd") << ":";
	resetConsoleColor();
	cin >> confirmPwd;
	if (password != confirmPwd) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("pwd_not_match") << endl;
		resetConsoleColor();
		Sleep(1000);
		return;
	}
	ofstream file(USER_FILE, ios::app);
	if (file.is_open()) {
		file << username << " " << simpleEncrypt(password) << endl;
		file.close();
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << getLocalText("register_success") << endl;
		resetConsoleColor();
	} else {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("note_open_fail") << endl;
		resetConsoleColor();
	}
	Sleep(1000);
}

bool userLogin() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "===== " << getLocalText("login") << " =====" << endl;
	resetConsoleColor();
	string username, password;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("username") << ":";
	resetConsoleColor();
	cin >> username;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("password") << ":";
	resetConsoleColor();
	cin >> password;
	if (!checkUserExists(username)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("user_not_exist") << endl;
		resetConsoleColor();
		Sleep(1000);
		return false;
	}
	ifstream file(USER_FILE);
	string user, encryptedPwd;
	while (file >> user >> encryptedPwd) {
		if (user == username) {
			file.close();
			if (simpleEncrypt(password) == encryptedPwd) {
				appState.loginUsername = username;
				appState.isAdmin = (username == ADMIN_USER);
				return true;
			} else {
				setConsoleColor(ConsoleColor::LIGHT_RED);
				cout << getLocalText("pwd_error") << endl;
				resetConsoleColor();
				Sleep(1000);
				return false;
			}
		}
	}
	file.close();
	return false;
}

void selectLanguage() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== C++ Center " << VERSION << " =====" << endl;
	resetConsoleColor();
	cout << endl;
	int langChoice = 0;
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("lang_choice") << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << getLocalText("lang_cn") << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_PURPLE);
	cout << getLocalText("lang_en") << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("choice") << "(1/2):";
	resetConsoleColor();
	while (!(cin >> langChoice) || (langChoice != 1 && langChoice != 2)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
	}
	switch (langChoice) {
	case 1: currentLang = LanguageType::CHINESE; break;
	case 2: currentLang = LanguageType::ENGLISH; break;
	default: currentLang = LanguageType::CHINESE; break;
	}
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "\n" << (currentLang == LanguageType::CHINESE ? "语言选择完成!" : "Language selected!") << endl;
	resetConsoleColor();
	Sleep(800);
}

string bigNumberAdd(const string& num1, const string& num2) {
	string result;
	int carry = 0;
	int i = num1.size() - 1, j = num2.size() - 1;
	while (i >= 0 || j >= 0 || carry > 0) {
		int digit1 = (i >= 0) ? (num1[i--] - '0') : 0;
		int digit2 = (j >= 0) ? (num2[j--] - '0') : 0;
		int sum = digit1 + digit2 + carry;
		carry = sum / 10;
		result.push_back((sum % 10) + '0');
	}
	reverse(result.begin(), result.end());
	return result;
}

string bigNumberSub(string num1, string num2) {
	bool negative = false;
	if (num1.size() < num2.size() || (num1.size() == num2.size() && num1 < num2)) {
		swap(num1, num2);
		negative = true;
	}
	string result;
	int borrow = 0;
	int i = num1.size() - 1, j = num2.size() - 1;
	while (i >= 0) {
		int digit1 = num1[i--] - '0' - borrow;
		int digit2 = (j >= 0) ? (num2[j--] - '0') : 0;
		borrow = 0;
		if (digit1 < digit2) {
			digit1 += 10;
			borrow = 1;
		}
		result.push_back((digit1 - digit2) + '0');
	}
	reverse(result.begin(), result.end());
	size_t start = result.find_first_not_of('0');
	result = (start == string::npos) ? "0" : result.substr(start);
	return negative ? "-" + result : result;
}

string bigNumberMul(const string& num1, const string& num2) {
	if (num1 == "0" || num2 == "0") return "0";
	vector<int> res(num1.size() + num2.size(), 0);
	for (int i = num1.size() - 1; i >= 0; i--) {
		for (int j = num2.size() - 1; j >= 0; j--) {
			int mul = (num1[i] - '0') * (num2[j] - '0');
			int sum = mul + res[i + j + 1];
			res[i + j + 1] = sum % 10;
			res[i + j] += sum / 10;
		}
	}
	string result;
	for (int num : res) {
		if (!(result.empty() && num == 0)) result.push_back(num + '0');
	}
	return result.empty() ? "0" : result;
}

void saveCalcHistory(const string& expr, const string& result) {
	ofstream file(CALC_HISTORY_FILE, ios::app);
	if (file.is_open()) {
		file << getCurrentTime() << " | " << appState.loginUsername << " | " << expr << " = " << result << endl;
		file.close();
	}
}

void runCalculator() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "===== " << getLocalText("calculator") << " =====" << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("calc_tip") << endl;
	resetConsoleColor();
	string input;
	clearInputBuffer();
	while (true) {
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << "\n" << getLocalText("calc_input");
		resetConsoleColor();
		getline(cin, input);
		if (input == "exit") break;
		if (input.empty()) continue;

		size_t opPos = string::npos;
		for (size_t k = 1; k < input.size(); k++) {
			if (input[k] == '+' || input[k] == '-' || input[k] == '*') {
				opPos = k;
				break;
			}
		}
		if (opPos == string::npos) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("invalid_choice") << endl;
			resetConsoleColor();
			continue;
		}

		string num1 = input.substr(0, opPos);
		char op = input[opPos];
		string num2 = input.substr(opPos + 1);

		bool num1Valid = all_of(num1.begin(), num1.end(), isdigit);
		bool num2Valid = all_of(num2.begin(), num2.end(), isdigit);
		if (!num1Valid || !num2Valid) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("input_number_error") << endl;
			resetConsoleColor();
			continue;
		}

		string result;
		try {
			switch (op) {
			case '+': result = bigNumberAdd(num1, num2); break;
			case '-': result = bigNumberSub(num1, num2); break;
			case '*': result = bigNumberMul(num1, num2); break;
			default: throw runtime_error("");
			}
			setConsoleColor(ConsoleColor::LIGHT_PURPLE);
			cout << getLocalText("calc_result") << result << endl;
			resetConsoleColor();
			saveCalcHistory(input, result);
		}
		catch (...) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("invalid_choice") << endl;
			resetConsoleColor();
		}
	}
}

const int BOARD_SIZE = 15;
typedef char GobangBoard[BOARD_SIZE][BOARD_SIZE];

void initGobangBoard(GobangBoard board) {
	for (int i = 0; i < BOARD_SIZE; ++i)
		for (int j = 0; j < BOARD_SIZE; ++j)
			board[i][j] = '+';
}

void printGobangBoard(GobangBoard board) {
	cout << "  ";
	for (int i = 0; i < BOARD_SIZE; ++i) {
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << fixed << setw(2) << i;
		resetConsoleColor();
	}
	cout << endl;
	for (int i = 0; i < BOARD_SIZE; ++i) {
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << fixed << setw(2) << i;
		resetConsoleColor();
		for (int j = 0; j < BOARD_SIZE; ++j) {
			if (board[i][j] == 'X') {
				setConsoleColor(ConsoleColor::BLACK, ConsoleColor::WHITE);
			} else if (board[i][j] == 'O') {
				setConsoleColor(ConsoleColor::WHITE, ConsoleColor::BLACK);
			} else {
				setConsoleColor(ConsoleColor::LIGHT_GREEN);
			}
			cout << fixed << setw(2) << board[i][j];
			resetConsoleColor();
		}
		cout << endl;
	}
}

bool checkGobangWin(GobangBoard board, int x, int y, char chess) {
	const int dirs[4][2] = {{0, 1}, {1, 0}, {1, 1}, {1, -1}};
	for (auto& dir : dirs) {
		int count = 1;
		for (int i = 1; i < 5; ++i) {
			int nx = x + dir[0] * i;
			int ny = y + dir[1] * i;
			if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE || board[nx][ny] != chess) break;
			count++;
		}
		for (int i = 1; i < 5; ++i) {
			int nx = x - dir[0] * i;
			int ny = y - dir[1] * i;
			if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE || board[nx][ny] != chess) break;
			count++;
		}
		if (count >= 5) return true;
	}
	return false;
}

void saveGobangHistory(const string& winner) {
	ofstream file(GOBANG_HISTORY_FILE, ios::app);
	if (file.is_open()) {
		file << getCurrentTime() << " | " << appState.loginUsername << " | Winner:" << winner << endl;
		file.close();
	}
}

void runGobang() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "===== " << getLocalText("gobang") << " =====" << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("gobang_tip") << endl;
	resetConsoleColor();
	Sleep(500);
	GobangBoard board;
	initGobangBoard(board);
	bool isBlackTurn = true;
	int stepCount = 0;
	clearInputBuffer();
	while (true) {
		clearConsole();
		printGobangBoard(board);
		char chess = isBlackTurn ? 'X' : 'O';
		string chessName = isBlackTurn ? getLocalText("gobang_black") : getLocalText("gobang_white");
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << "\n" << chessName << "(" << chess << ")" << getLocalText("choice") << "(行 列):";
		resetConsoleColor();
		int x, y;
		while (!(cin >> x >> y) || x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("coord_error") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
		}
		clearInputBuffer();
		if (board[x][y] != '+') {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("chess_exist") << endl;
			resetConsoleColor();
			Sleep(800);
			continue;
		}
		board[x][y] = chess;
		stepCount++;
		if (checkGobangWin(board, x, y, chess)) {
			clearConsole();
			printGobangBoard(board);
			setConsoleColor(ConsoleColor::LIGHT_YELLOW);
			cout << chessName << getLocalText("gobang_win") << endl;
			resetConsoleColor();
			saveGobangHistory(chessName);
			break;
		}
		if (stepCount >= BOARD_SIZE * BOARD_SIZE) {
			clearConsole();
			printGobangBoard(board);
			setConsoleColor(ConsoleColor::LIGHT_YELLOW);
			cout << getLocalText("gobang_draw") << endl;
			resetConsoleColor();
			saveGobangHistory(getLocalText("gobang_draw"));
			break;
		}
		isBlackTurn = !isBlackTurn;
	}
	Sleep(1500);
}

void runNotepad() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== " << getLocalText("notepad") << " =====" << endl;
	resetConsoleColor();
	int choice = 0;
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "1. " << getLocalText("note_edit") << endl;
	cout << "2. " << getLocalText("note_view") << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("choice") << "(1/2):";
	resetConsoleColor();
	while (!(cin >> choice) || (choice != 1 && choice != 2)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
	}
	clearInputBuffer();
	if (choice == 1) {
		ofstream file(NOTE_FILE);
		if (!file.is_open()) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("note_open_fail") << endl;
			resetConsoleColor();
			Sleep(1000);
			return;
		}
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << "\n" << getLocalText("note_edit_tip") << endl;
		resetConsoleColor();
		string line;
		while (getline(cin, line)) {
			file << line << endl;
		}
		cin.clear();
		file.close();
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << getLocalText("note_save_success") << endl;
		resetConsoleColor();
	} else {
		ifstream file(NOTE_FILE);
		if (!file.is_open()) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("note_empty") << endl;
			resetConsoleColor();
			Sleep(1000);
			return;
		}
		setConsoleColor(ConsoleColor::LIGHT_PURPLE);
		cout << "\n===== " << getLocalText("notepad") << " =====" << endl;
		resetConsoleColor();
		string line;
		while (getline(file, line)) {
			setConsoleColor(ConsoleColor::LIGHT_WHITE);
			cout << line << endl;
			resetConsoleColor();
		}
		file.close();
	}
	Sleep(1500);
}

void runGuessNumber() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << "===== " << getLocalText("guess_num") << " =====" << endl;
	resetConsoleColor();
	srand(time(nullptr));
	int target = rand() % 100 + 1;
	int guess, tries = 0;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("guess_num_tip") << endl;
	resetConsoleColor();
	clearInputBuffer();
	while (true) {
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << "\n" << getLocalText("choice") << ":";
		resetConsoleColor();
		while (!(cin >> guess) || guess < 1 || guess > 100) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("input_range_error") << endl;
			resetConsoleColor();
			clearInputBuffer();
		}
		tries++;
		if (guess < target) {
			setConsoleColor(ConsoleColor::LIGHT_BLUE);
			cout << getLocalText("guess_num_small") << endl;
			resetConsoleColor();
		} else if (guess > target) {
			setConsoleColor(ConsoleColor::LIGHT_PURPLE);
			cout << getLocalText("guess_num_big") << endl;
			resetConsoleColor();
		} else {
			setConsoleColor(ConsoleColor::LIGHT_GREEN);
			char buf[100];
			sprintf(buf, getLocalText("guess_num_success").c_str(), tries);
			cout << buf << endl;
			resetConsoleColor();
			break;
		}
	}
	Sleep(1500);
}

void runMinesweeper() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << "===== " << getLocalText("minesweeper") << " =====" << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("minesweeper_tip") << endl;
	resetConsoleColor();
	Sleep(800);
	const int MS_SIZE = 5;
	bool mines[MS_SIZE][MS_SIZE] = { false };
	bool revealed[MS_SIZE][MS_SIZE] = { false };
	int mineCount = 0;
	int safeCount = 0;
	srand(time(nullptr));
	while (mineCount < 5) {
		int x = rand() % MS_SIZE;
		int y = rand() % MS_SIZE;
		if (!mines[x][y]) {
			mines[x][y] = true;
			mineCount++;
		}
	}
	clearInputBuffer();
	while (true) {
		clearConsole();
		cout << "  ";
		for (int i = 0; i < MS_SIZE; ++i) {
			setConsoleColor(ConsoleColor::LIGHT_CYAN);
			cout << setw(2) << i;
			resetConsoleColor();
		}
		cout << endl;
		for (int i = 0; i < MS_SIZE; ++i) {
			setConsoleColor(ConsoleColor::LIGHT_CYAN);
			cout << setw(2) << i;
			resetConsoleColor();
			for (int j = 0; j < MS_SIZE; ++j) {
				if (revealed[i][j]) {
					if (mines[i][j]) {
						setConsoleColor(ConsoleColor::LIGHT_RED);
						cout << setw(2) << "*";
					} else {
						int cnt = 0;
						for (int dx = -1; dx <= 1; dx++)
							for (int dy = -1; dy <= 1; dy++) {
								int nx = i + dx, ny = j + dy;
								if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && mines[nx][ny]) cnt++;
							}
						if (cnt == 1) setConsoleColor(ConsoleColor::LIGHT_BLUE);
						else if (cnt == 2) setConsoleColor(ConsoleColor::LIGHT_GREEN);
						else if (cnt >= 3) setConsoleColor(ConsoleColor::LIGHT_RED);
						else setConsoleColor(ConsoleColor::WHITE);
						cout << setw(2) << cnt;
					}
				} else {
					setConsoleColor(ConsoleColor::LIGHT_GREEN);
					cout << setw(2) << "#";
				}
				resetConsoleColor();
			}
			cout << endl;
		}
		if (safeCount == 20) {
			setConsoleColor(ConsoleColor::LIGHT_GREEN);
			cout << "\n" << getLocalText("minesweeper_win") << endl;
			resetConsoleColor();
			break;
		}
		int x, y;
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << "\n" << getLocalText("minesweeper_input") << ":";
		resetConsoleColor();
		while (!(cin >> x >> y) || x < 0 || x >= 5 || y < 0 || y >= 5) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("coord_error") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
		}
		clearInputBuffer();
		if (revealed[x][y]) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("minesweeper_revealed") << endl;
			resetConsoleColor();
			Sleep(800);
			continue;
		}
		if (mines[x][y]) {
			revealed[x][y] = true;
			for (int i = 0; i < 5; i++)for (int j = 0; j < 5; j++) if (mines[i][j]) revealed[i][j] = true;
			clearConsole();
			for (int i = 0; i < 5; i++) {
				for (int j = 0; j < 5; j++) {
					if (mines[i][j]) { cout << " *"; }
					else { cout << " #"; }
				}
				cout << endl;
			}
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << "\n" << getLocalText("minesweeper_lose") << endl;
			resetConsoleColor();
			break;
		}
		revealed[x][y] = true;
		safeCount++;
	}
	Sleep(1500);
}

void runMiniGames() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_PURPLE);
	cout << "===== " << getLocalText("mini_games") << " =====" << endl;
	resetConsoleColor();
	int choice = 0;
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "1. " << getLocalText("guess_num") << endl;
	cout << "2. " << getLocalText("minesweeper") << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("choice") << "(1/2):";
	resetConsoleColor();
	while (!(cin >> choice) || (choice != 1 && choice != 2)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
	}
	switch (choice) {
	case 1: runGuessNumber(); break;
	case 2: runMinesweeper(); break;
	default: break;
	}
}

void runRandomNumber() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== " << getLocalText("random_num") << " =====" << endl;
	resetConsoleColor();
	int min, max;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("random_num_min");
	resetConsoleColor();
	while (!(cin >> min)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("input_number_error") << endl;
		resetConsoleColor();
		clearInputBuffer();
	}
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("random_num_max");
	resetConsoleColor();
	while (!(cin >> max) || max < min) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("random_num_max_error") << endl;
		resetConsoleColor();
		clearInputBuffer();
	}
	srand(time(nullptr));
	int num = rand() % (max - min + 1) + min;
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	char buf[50];
	sprintf(buf, getLocalText("random_num_result").c_str(), num);
	cout << buf << endl;
	resetConsoleColor();
	Sleep(1000);
}

void runBaseConversion() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== " << getLocalText("base_convert") << " =====" << endl;
	resetConsoleColor();
	int num, base;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("base_convert_num");
	resetConsoleColor();
	while (!(cin >> num) || num < 0) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("input_number_error") << endl;
		resetConsoleColor();
		clearInputBuffer();
	}
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("base_convert_type");
	resetConsoleColor();
	while (!(cin >> base) || (base != 2 && base != 8 && base != 16)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("base_convert_error") << endl;
		resetConsoleColor();
		clearInputBuffer();
	}
	const string digits = "0123456789ABCDEF";
	string result;
	int temp = num;
	if (temp == 0) result = "0";
	else {
		while (temp > 0) {
			result = digits[temp % base] + result;
			temp /= base;
		}
	}
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	char buf[100];
	sprintf(buf, getLocalText("base_convert_result").c_str(), result.c_str());
	cout << buf << endl;
	resetConsoleColor();
	Sleep(1000);
}

void runStringTools() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== " << getLocalText("string_tool") << " =====" << endl;
	resetConsoleColor();
	clearInputBuffer();
	string str;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("string_tool_input");
	resetConsoleColor();
	getline(cin, str);
	string orig = str;
	string up = str; transform(up.begin(), up.end(), up.begin(), toupper);
	string low = str; transform(low.begin(), low.end(), low.begin(), tolower);
	reverse(str.begin(), str.end());

	char b1[100], b2[100], b3[100], b4[100];
	sprintf(b1, getLocalText("string_tool_upper").c_str(), up.c_str());
	sprintf(b2, getLocalText("string_tool_lower").c_str(), low.c_str());
	sprintf(b3, getLocalText("string_tool_reverse").c_str(), str.c_str());
	sprintf(b4, getLocalText("string_tool_length").c_str(), (int)orig.size());

	setConsoleColor(ConsoleColor::LIGHT_GREEN); cout << b1 << endl; resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_BLUE); cout << b2 << endl; resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_PURPLE); cout << b3 << endl; resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW); cout << b4 << endl; resetConsoleColor();
	Sleep(1500);
}

void runStopwatch() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== " << getLocalText("stopwatch") << " =====" << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("stopwatch_start");
	resetConsoleColor();
	clearInputBuffer();
	cin.get();
	time_t start = time(nullptr);
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("stopwatch_running") << endl;
	resetConsoleColor();
	cin.get();
	time_t end = time(nullptr);
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	char buf[50];
	sprintf(buf, getLocalText("stopwatch_result").c_str(), difftime(end, start));
	cout << buf << endl;
	resetConsoleColor();
	Sleep(1000);
}

void runCodeTools() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << "===== " << getLocalText("tools") << " =====" << endl;
	resetConsoleColor();
	int choice = 0;
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	cout << "1. " << getLocalText("random_num") << endl;
	cout << "2. " << getLocalText("base_convert") << endl;
	cout << "3. " << getLocalText("string_tool") << endl;
	cout << "4. " << getLocalText("stopwatch") << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	cout << getLocalText("choice") << "(1-4):";
	resetConsoleColor();
	while (!(cin >> choice) || choice < 1 || choice > 4) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
	}
	switch (choice) {
	case 1: runRandomNumber(); break;
	case 2: runBaseConversion(); break;
	case 3: runStringTools(); break;
	case 4: runStopwatch(); break;
	default: break;
	}
}

void showMainMenu() {
	while (appState.isRunning) {
		clearConsole();
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << getLocalText("main_menu") << " - " << appState.loginUsername << endl;
		resetConsoleColor();
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << "1. " << getLocalText("calculator") << endl;
		cout << "2. " << getLocalText("gobang") << endl;
		cout << "3. " << getLocalText("notepad") << endl;
		cout << "4. " << getLocalText("mini_games") << endl;
		cout << "5. " << getLocalText("tools") << endl;
		cout << "6. " << getLocalText("exit") << endl;
		resetConsoleColor();
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << getLocalText("choice") << "(1-6):";
		resetConsoleColor();
		int choice = 0;
		while (!(cin >> choice) || choice < 1 || choice > 6) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
		}
		switch (choice) {
		case 1: runCalculator(); break;
		case 2: runGobang(); break;
		case 3: runNotepad(); break;
		case 4: runMiniGames(); break;
		case 5: runCodeTools(); break;
		case 6:
			appState.isRunning = false;
			setConsoleColor(ConsoleColor::LIGHT_GREEN);
			cout << getLocalText("goodbye") << endl;
			resetConsoleColor();
			Sleep(800);
			return;
		default: break;
		}
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << "\n" << getLocalText("continue_tip");
		resetConsoleColor();
		clearInputBuffer();
		cin.get();
	}
}

void showLoginRegisterMenu() {
	while (true) {
		clearConsole();
		setConsoleColor(ConsoleColor::LIGHT_BLUE);
		cout << "===== C++ Center " << VERSION << " =====" << endl;
		resetConsoleColor();
		int choice = 0;
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << "1. " << getLocalText("login") << endl;
		cout << "2. " << getLocalText("register") << endl;
		resetConsoleColor();
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << getLocalText("choice") << "(1/2):";
		resetConsoleColor();
		while (!(cin >> choice) || (choice != 1 && choice != 2)) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
		}
		if (choice == 1) {
			if (userLogin()) {
				setConsoleColor(ConsoleColor::LIGHT_GREEN);
				cout << getLocalText("login_success") << endl;
				resetConsoleColor();
				Sleep(800);
				showMainMenu();
				return;
			}
		} else registerNewUser();
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << "\n" << getLocalText("continue_tip");
		resetConsoleColor();
		clearInputBuffer();
		cin.get();
	}
}

int main() {
	SetConsoleOutputCP(CP_UTF8);
	srand((unsigned)time(NULL));
	initAdminUser();
	selectLanguage();
	showAnnouncement();
	showLoginRegisterMenu();
	return 0;
}

0 条评论

目前还没有评论...