#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;
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	if (hConsole != INVALID_HANDLE_VALUE) FlushConsoleInputBuffer(hConsole);
}

void clearConsole() {
#ifdef _WIN32
	system("cls");
#else
	system("clear");
#endif
}

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);
}

// 修正:使用 strftime 替代 put_time,增强兼容性
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 Chess";
		if (key == "gobang_white") return "White Chess";
		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 here!";
		if (key == "note_edit") return "Edit Notepad";
		if (key == "note_view") return "View Notepad";
		if (key == "guess_num") return "Guess Number Game";
		if (key == "minesweeper") return "Simple Minesweeper";
		if (key == "random_num") return "Random Number Generator";
		if (key == "base_convert") return "Base Conversion";
		if (key == "string_tool") return "String Tools";
		if (key == "stopwatch") return "Stopwatch Tool";
		if (key == "announcement_title") return "===== System Announcement =====";
		if (key == "announcement_default") return "Welcome to C++ Center v3.0.0!\n1. Default admin account: admin, password: admin123\n2. All operation records are saved in local files\n3. Check file read/write permissions if there are issues";
		if (key == "announcement_load_fail") return "Tip: Announcement file not found, showing default announcement";
		if (key == "announcement_continue") return "Press Enter to continue...";
		if (key == "calc_tip") return "Supported: +-* (multiplication only supports single-digit multiplier), enter exit to quit";
		if (key == "gobang_tip") return "Black Chess(X) first move, White Chess(O) second move";
		if (key == "note_edit_tip") return "Enter content (Ctrl+Z to end input): ";
		if (key == "note_save_success") return "Saved successfully!";
		if (key == "note_open_fail") return "Error: Cannot open file!";
		if (key == "note_empty") return "Notepad is empty!";
		if (key == "guess_num_tip") return "I thought of a number between 1-100, guess it!";
		if (key == "guess_num_small") return "Too small!";
		if (key == "guess_num_big") return "Too big!";
		if (key == "guess_num_success") return "Congratulations! You guessed it in %d tries!";
		if (key == "minesweeper_tip") return "5x5 Minesweeper with 5 mines";
		if (key == "minesweeper_win") return "Congratulations! You win!";
		if (key == "minesweeper_lose") return "Stepped on a mine! Game over!";
		if (key == "minesweeper_revealed") return "Position already revealed!";
		if (key == "random_num_min") return "Enter min: ";
		if (key == "random_num_max") return "Enter max: ";
		if (key == "random_num_result") return "Random number: %d";
		if (key == "random_num_max_error") return "Max must be greater than min!";
		if (key == "base_convert_num") return "Enter decimal number: ";
		if (key == "base_convert_type") return "Convert to (2/8/16) base: ";
		if (key == "base_convert_result") return "Result: %s";
		if (key == "base_convert_error") return "Please enter 2/8/16!";
		if (key == "string_tool_input") return "Enter string: ";
		if (key == "string_tool_upper") return "1. To upper: %s";
		if (key == "string_tool_lower") return "2. To 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 "Press Enter to start timing...";
		if (key == "stopwatch_running") return "Timing... Press Enter to stop!";
		if (key == "stopwatch_result") return "Elapsed time: %.0f seconds";
		if (key == "input_number_error") return "Please enter a number!";
		if (key == "input_range_error") return "Please enter a number between 1-100!";
		if (key == "minesweeper_input") return "Enter position to reveal (row col): ";
		if (key == "continue_tip") return "Press Enter to continue...";
		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();
	flushConsoleOutput();
	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();
	flushConsoleOutput();
	while (!(cin >> langChoice) || (langChoice != 1 && langChoice != 2)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
		flushConsoleOutput();
	}
	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(const string& num1, const string& num2) {
	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');
	return (start == string::npos) ? "0" : result.substr(start);
}

string bigNumberMul(const string& num1, int num2) {
	string result;
	int carry = 0;
	for (int i = num1.size() - 1; i >= 0; --i) {
		int product = (num1[i] - '0') * num2 + carry;
		carry = product / 10;
		result.push_back((product % 10) + '0');
	}
	if (carry > 0) result.push_back(carry + '0');
	reverse(result.begin(), result.end());
	size_t start = result.find_first_not_of('0');
	return (start == string::npos) ? "0" : result.substr(start);
}

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;
	while (true) {
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << "\n" << getLocalText("calc_input");
		resetConsoleColor();
		flushConsoleOutput();
		cin >> input;
		if (input == "exit") break;
		if (input.empty()) continue;
		size_t opPos = input.find_first_of("+-*");
		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);
		if (num1.find_first_not_of("0123456789") != string::npos ||
			num2.find_first_not_of("0123456789") != string::npos) {
			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 '*': 
				if (num2.size() > 1) throw runtime_error("");
				result = bigNumberMul(num1, stoi(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 << setw(2) << i;
		resetConsoleColor();
	}
	cout << endl;
	for (int i = 0; i < BOARD_SIZE; ++i) {
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << setw(2) << i;
		resetConsoleColor();
		for (int j = 0; j < BOARD_SIZE; ++j) {
			if (board[i][j] == 'X') setConsoleColor(ConsoleColor::BLACK, ConsoleColor::LIGHT_WHITE);
			else if (board[i][j] == 'O') setConsoleColor(ConsoleColor::LIGHT_WHITE, ConsoleColor::BLACK);
			else setConsoleColor(ConsoleColor::LIGHT_GREEN);
			cout << 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;
	printGobangBoard(board);
	while (true) {
		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();
		flushConsoleOutput();
		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();
			flushConsoleOutput();
		}
		if (board[x][y] != '+') {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("chess_exist") << endl;
			resetConsoleColor();
			Sleep(800);
			continue;
		}
		board[x][y] = chess;
		stepCount++;
		clearConsole();
		printGobangBoard(board);
		if (checkGobangWin(board, x, y, chess)) {
			setConsoleColor(ConsoleColor::LIGHT_YELLOW);
			cout << chessName << getLocalText("gobang_win") << endl;
			resetConsoleColor();
			saveGobangHistory(chessName);
			break;
		}
		if (stepCount >= BOARD_SIZE * BOARD_SIZE) {
			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();
	flushConsoleOutput();
	while (!(cin >> choice) || (choice != 1 && choice != 2)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
		flushConsoleOutput();
	}
	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;
		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();
	while (true) {
		setConsoleColor(ConsoleColor::LIGHT_GREEN);
		cout << "\n" << getLocalText("choice") << ":";
		resetConsoleColor();
		flushConsoleOutput();
		while (!(cin >> guess) || guess < 1 || guess > 100) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("input_range_error") << endl;
			resetConsoleColor();
			clearInputBuffer();
			flushConsoleOutput();
		}
		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);
			printf(getLocalText("guess_num_success").c_str(), tries);
			cout << 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++;
		}
	}
	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 count = 0;
						for (int dx = -1; dx <= 1; ++dx)
							for (int dy = -1; dy <= 1; ++dy) {
								int nx = i + dx;
								int ny = j + dy;
								if (nx >= 0 && nx < MS_SIZE && ny >= 0 && ny < MS_SIZE && mines[nx][ny]) count++;
							}
						switch(count) {
							case 1: setConsoleColor(ConsoleColor::LIGHT_BLUE); break;
							case 2: setConsoleColor(ConsoleColor::LIGHT_GREEN); break;
							case 3: setConsoleColor(ConsoleColor::LIGHT_RED); break;
							case 4: setConsoleColor(ConsoleColor::LIGHT_PURPLE); break;
							default: setConsoleColor(ConsoleColor::LIGHT_YELLOW); break;
						}
						cout << setw(2) << count;
					}
				} else {
					setConsoleColor(ConsoleColor::LIGHT_GREEN);
					cout << setw(2) << "#";
				}
				resetConsoleColor();
			}
			cout << endl;
		}
		if (safeCount == MS_SIZE * MS_SIZE - 5) {
			setConsoleColor(ConsoleColor::LIGHT_GREEN);
			cout << "\n" << getLocalText("minesweeper_win") << endl;
			resetConsoleColor();
			break;
		}
		int x, y;
		setConsoleColor(ConsoleColor::LIGHT_YELLOW);
		cout << "\n" << getLocalText("minesweeper_input") << endl;
		resetConsoleColor();
		flushConsoleOutput();
		while (!(cin >> x >> y) || x < 0 || x >= MS_SIZE || y < 0 || y >= MS_SIZE) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("coord_error") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
			flushConsoleOutput();
		}
		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;
			clearConsole();
			for (int i = 0; i < MS_SIZE; ++i)
				for (int j = 0; j < MS_SIZE; ++j)
					if (mines[i][j]) revealed[i][j] = true;
			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 (mines[i][j]) {
						setConsoleColor(ConsoleColor::LIGHT_RED);
						cout << setw(2) << "*";
					} else {
						setConsoleColor(ConsoleColor::LIGHT_GREEN);
						cout << setw(2) << "#";
					}
					resetConsoleColor();
				}
				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();
	flushConsoleOutput();
	while (!(cin >> choice) || (choice != 1 && choice != 2)) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
		flushConsoleOutput();
	}
	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);
	printf(getLocalText("random_num_result").c_str(), num);
	cout << 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);
	printf(getLocalText("base_convert_result").c_str(), result.c_str());
	cout << endl;
	resetConsoleColor();
	Sleep(1000);
}

void runStringTools() {
	clearConsole();
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	cout << "===== " << getLocalText("string_tool") << " =====" << endl;
	resetConsoleColor();
	clearInputBuffer();
	string str, strOrig;
	setConsoleColor(ConsoleColor::LIGHT_CYAN);
	cout << getLocalText("string_tool_input");
	resetConsoleColor();
	getline(cin, str);
	strOrig = str;
	string strUpper = str;
	transform(strUpper.begin(), strUpper.end(), strUpper.begin(), ::toupper);
	setConsoleColor(ConsoleColor::LIGHT_GREEN);
	printf(getLocalText("string_tool_upper").c_str(), strUpper.c_str());
	cout << endl;
	resetConsoleColor();
	string strLower = str;
	transform(strLower.begin(), strLower.end(), strLower.begin(), ::tolower);
	setConsoleColor(ConsoleColor::LIGHT_BLUE);
	printf(getLocalText("string_tool_lower").c_str(), strLower.c_str());
	cout << endl;
	resetConsoleColor();
	reverse(str.begin(), str.end());
	setConsoleColor(ConsoleColor::LIGHT_PURPLE);
	printf(getLocalText("string_tool_reverse").c_str(), str.c_str());
	cout << endl;
	resetConsoleColor();
	setConsoleColor(ConsoleColor::LIGHT_YELLOW);
	printf(getLocalText("string_tool_length").c_str(), (int)strOrig.size());
	cout << 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();
	flushConsoleOutput();
	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);
	printf(getLocalText("stopwatch_result").c_str(), difftime(end, start));
	cout << 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();
	flushConsoleOutput();
	while (!(cin >> choice) || choice < 1 || choice > 4) {
		setConsoleColor(ConsoleColor::LIGHT_RED);
		cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
		resetConsoleColor();
		clearInputBuffer();
		flushConsoleOutput();
	}
	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();
		flushConsoleOutput();
		int choice = 0;
		while (!(cin >> choice) || choice < 1 || choice > 6) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
			flushConsoleOutput();
		}
		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);
			exit(0);
			break;
			default: break;
		}
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << "\n" << getLocalText("continue_tip");
		resetConsoleColor();
		flushConsoleOutput();
		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();
		flushConsoleOutput();
		while (!(cin >> choice) || (choice != 1 && choice != 2)) {
			setConsoleColor(ConsoleColor::LIGHT_RED);
			cout << getLocalText("invalid_choice") << "," << getLocalText("choice") << ":";
			resetConsoleColor();
			clearInputBuffer();
			flushConsoleOutput();
		}
		if (choice == 1) {
			if (userLogin()) {
				setConsoleColor(ConsoleColor::LIGHT_GREEN);
				cout << getLocalText("login_success") << endl;
				resetConsoleColor();
				Sleep(800);
				showMainMenu();
				break;
			}
		} else registerNewUser();
		setConsoleColor(ConsoleColor::LIGHT_CYAN);
		cout << "\n" << getLocalText("continue_tip");
		resetConsoleColor();
		flushConsoleOutput();
		clearInputBuffer();
		cin.get();
	}
}

// ===================== 程序入口 =====================
int main() {
	SetConsoleOutputCP(936);  
	SetConsoleCP(936);
	srand(time(nullptr));      
	initAdminUser();
	selectLanguage();
	showAnnouncement();
	showLoginRegisterMenu();
	return 0;
}
本次更新修复了部分版本编译时报错的问题

2 条评论

  • @ 2026-3-26 20:59:04

    我在小熊猫C++里运行没有问题呀!

    但是在Dev—C++里运行不了,但也是第24行就出错了
    • @ 2026-3-23 16:01:30

      532和535行的'runtime_error("")'报错

      • 1