主要修改部分为五子棋 AI 的三个核心函数:

evaluate_line:增强了连子评分机制,区分活棋和冲棋的价值差异

evaluate_position:优化了防守优先级算法,对高威胁情况增加权重

find_best_move:添加了紧急落子点检测,确保 AI 能优先处理必胜和必防局面

其他游戏功能(猜数字、石头剪刀布、计算器、五子棋双人模式)和用户认证系统保持不变,但五子棋 AI 对战模式的策略性得到显著提升,表现为:</u>

更注重活棋发展(活三、活二)为后续进攻铺路

对玩家的高威胁(如活四)会优先阻挡

能识别必胜局面并立即落子

整体落子更具布局意识,不再是简单的局部最优选择
#include <iostream>
#include <fstream>
#include <map>
#include <cstdlib>
#include <ctime>
#include <string>
#include <limits>
#include <vector>
#include <utility>
#include <functional>
using namespace std;

// 命名空间封装,减少全局变量污染
namespace GameCenter {
	// 存储用户名、盐值和哈希后的密码(用户名 -> (盐值, 哈希密码))
	map<string, pair<string, string>> users; 
	constexpr int GOMOKU_SIZE = 15; // 五子棋棋盘大小
	char gomoku_board[GOMOKU_SIZE][GOMOKU_SIZE];
	
	// 生成随机盐值(增强哈希安全性)
	string generate_salt() {
		const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()";
		string salt;
		for (int i = 0; i < 16; ++i) { // 16位随机盐值
			salt += chars[rand() % chars.size()];
		}
		return salt;
	}
	
	// 增强的哈希函数(盐值+多次哈希)
	string hash_password(const string& pass, const string& salt) {
		string input = salt + pass; // 盐值拼接密码
		size_t hash_result = 0;
		
		// 多次哈希迭代,增加破解难度
		for (int i = 0; i < 10000; ++i) {
			hash_result ^= hash<string>{}(input + to_string(i) + to_string(hash_result));
		}
		
		return to_string(hash_result);
	}
	
	// 加载用户数据
	void load_users() {
		users.clear();
		ifstream fin("users.txt");
		if (!fin.is_open()) {
			return;
		}
		
		string username, salt, hashed_pass;
		while (fin >> username >> salt >> hashed_pass) {
			users[username] = {salt, hashed_pass};
		}
		fin.close();
	}
	
	// 保存用户数据
	bool save_users() {
		ofstream fout("users.txt");
		if (!fout.is_open()) {
			cerr << "错误:无法打开用户数据文件进行写入!" << endl;
			return false;
		}
		
		for (const auto& p : users) {
			fout << p.first << " " << p.second.first << " " << p.second.second << endl;
		}
		fout.close();
		return true;
	}
	
	// 输入整数验证
	int input_int(const string& prompt, int min_val, int max_val) {
		int num;
		while (true) {
			cout << prompt;
			cin >> num;
			
			if (cin.good() && num >= min_val && num <= max_val) {
				cin.ignore(numeric_limits<streamsize>::max(), '\n');
				return num;
			} else {
				cin.clear();
				cin.ignore(numeric_limits<streamsize>::max(), '\n');
				cout << "输入无效,请输入" << min_val << "到" << max_val << "之间的数字!" << endl;
			}
		}
	}
	
	// 猜数字游戏
	void guess_number() {
		int secret = rand() % 100 + 1;
		int guess, cnt = 0;
		cout << "\n===== 猜数字游戏 =====" << endl;
		cout << "系统已生成1~100的随机数,开始猜测吧!" << endl;
		
		while (true) {
			guess = input_int("请输入你的猜测:", 1, 100);
			cnt++;
			if (guess == secret) {
				cout << "恭喜猜对了!共猜了" << cnt << "次!" << endl;
				break;
			} else if (guess < secret) {
				cout << "猜小了哦~" << endl;
			} else {
				cout << "猜大了哦~" << endl;
			}
		}
	}
	
	// 石头剪刀布游戏
	void rock_paper_scissors() {
		const string choice[3] = {"石头", "剪刀", "布"};
		int user_choice = input_int(
									"\n===== 石头剪刀布 =====" 
									"\n0-石头  1-剪刀  2-布" 
									"\n请选择:", 0, 2);
		
		int computer_choice = rand() % 3;
		cout << "你出:" << choice[user_choice] << endl;
		cout << "电脑出:" << choice[computer_choice] << endl;
		
		if (user_choice == computer_choice) {
			cout << "平局!" << endl;
		} else if ((user_choice == 0 && computer_choice == 1) || 
				   (user_choice == 1 && computer_choice == 2) || 
				   (user_choice == 2 && computer_choice == 0)) {
			cout << "你赢了!" << endl;
		} else {
			cout << "你输了!" << endl;
		}
	}
	
	// 计算器
	void calculator() {
		double a, b;
		char op;
		cout << "\n===== 简易计算器 =====" << endl;
		cout << "请输入表达式(格式:数字 运算符 数字,如 2 + 3):";
		
		while (!(cin >> a >> op >> b)) {
			cin.clear();
			cin.ignore(numeric_limits<streamsize>::max(), '\n');
			cout << "输入格式错误,请重新输入(如 2 + 3):";
		}
		
		switch (op) {
			case '+': cout << "结果:" << a + b << endl; break;
			case '-': cout << "结果:" << a - b << endl; break;
			case '*': cout << "结果:" << a * b << endl; break;
			case '/': 
			if (b == 0) {
				cout << "错误:除数不能为0!" << endl;
			} else {
				cout << "结果:" << a / b << endl;
			}
			break;
			default: cout << "错误:不支持的运算符!" << endl;
		}
	}
	
	// 五子棋工具函数:打印棋盘
	void print_gomoku_board() {
		cout << "   ";
		for (int i = 0; i < GOMOKU_SIZE; ++i) {
			cout << (i < 10 ? " " : "") << i << " ";
		}
		cout << endl;
		for (int i = 0; i < GOMOKU_SIZE; ++i) {
			cout << (i < 10 ? " " : "") << i << " ";
			for (int j = 0; j < GOMOKU_SIZE; ++j) {
				cout << (gomoku_board[i][j] == 0 ? ".  " : string(1, gomoku_board[i][j]) + "  ");
			}
			cout << endl;
		}
	}
	
	// 五子棋工具函数:检查获胜
	bool check_gomoku_win(int x, int y, char c) {
		const int dx[] = {1, 0, 1, 1};
		const int dy[] = {0, 1, 1, -1};
		
		for (int d = 0; d < 4; ++d) {
			int count = 1;
			for (int k = 1; k < 5; ++k) {
				int nx = x + dx[d] * k;
				int ny = y + dy[d] * k;
				if (nx < 0 || nx >= GOMOKU_SIZE || ny < 0 || ny >= GOMOKU_SIZE) break;
				if (gomoku_board[nx][ny] == c) count++;
				else break;
			}
			for (int k = 1; k < 5; ++k) {
				int nx = x - dx[d] * k;
				int ny = y - dy[d] * k;
				if (nx < 0 || nx >= GOMOKU_SIZE || ny < 0 || ny >= GOMOKU_SIZE) break;
				if (gomoku_board[nx][ny] == c) count++;
				else break;
			}
			if (count >= 5) return true;
		}
		return false;
	}
	
	// 五子棋工具函数:初始化棋盘
	void init_gomoku_board() {
		for (int i = 0; i < GOMOKU_SIZE; ++i) {
			for (int j = 0; j < GOMOKU_SIZE; ++j) {
				gomoku_board[i][j] = 0;
			}
		}
	}
	
	// 五子棋-双人对战
	void gomoku_pvp() {
		init_gomoku_board();
		cout << "\n===== 五子棋-双人对战 =====" << endl;
		cout << "玩家1使用 X,玩家2使用 O,先连成5子获胜!" << endl;
		int turn = 0;
		
		while (true) {
			print_gomoku_board();
			char current_player = (turn % 2 == 0) ? 'X' : 'O';
			int x = input_int("玩家" + to_string(turn % 2 + 1) + "(" + current_player + ")请输入行坐标:", 0, GOMOKU_SIZE - 1);
			int y = input_int("玩家" + to_string(turn % 2 + 1) + "(" + current_player + ")请输入列坐标:", 0, GOMOKU_SIZE - 1);
			
			if (gomoku_board[x][y] != 0) {
				cout << "该位置已落子,请重新选择!" << endl;
				continue;
			}
			
			gomoku_board[x][y] = current_player;
			if (check_gomoku_win(x, y, current_player)) {
				print_gomoku_board();
				cout << "恭喜玩家" << (turn % 2 + 1) << "获胜!" << endl;
				break;
			}
			
			turn++;
			if (turn == GOMOKU_SIZE * GOMOKU_SIZE) {
				print_gomoku_board();
				cout << "棋盘已满,平局!" << endl;
				break;
			}
		}
	}
	
	// 五子棋AI评估函数(增强策略性)
	int evaluate_line(int x, int y, int dx, int dy, char c, char opponent) {
		int count = 1; // 当前位置已有一个子
		int empty_ends = 0; // 两端的空位数
		bool block1 = false, block2 = false; // 两端是否被阻挡
		
		// 正向检查
		for (int i = 1; i <= 4; ++i) {
			int nx = x + dx * i;
			int ny = y + dy * i;
			if (nx < 0 || nx >= GOMOKU_SIZE || ny < 0 || ny >= GOMOKU_SIZE) {
				block1 = true;
				break;
			}
			if (gomoku_board[nx][ny] == c) {
				count++;
			} else if (gomoku_board[nx][ny] == 0) {
				empty_ends++;
				break;
			} else {
				block1 = true;
				break; // 被对方棋子阻挡
			}
		}
		
		// 反向检查
		for (int i = 1; i <= 4; ++i) {
			int nx = x - dx * i;
			int ny = y - dy * i;
			if (nx < 0 || nx >= GOMOKU_SIZE || ny < 0 || ny >= GOMOKU_SIZE) {
				block2 = true;
				break;
			}
			if (gomoku_board[nx][ny] == c) {
				count++;
			} else if (gomoku_board[nx][ny] == 0) {
				empty_ends++;
				break;
			} else {
				block2 = true;
				break; // 被对方棋子阻挡
			}
		}
		
		// 策略性评分调整:活棋优先于冲棋,高分值情况拉开差距
		if (count >= 5) return 1000000; // 五子连珠(必胜)
		else if (count == 4) {
			if (empty_ends >= 1) return 100000; // 活四(有一端可连五)
			else return 50000; // 冲四(被阻挡一端)
		} else if (count == 3) {
			if (empty_ends == 2) return 10000; // 活三(两端可发展)
			else if (empty_ends == 1) return 5000; // 冲三(一端可发展)
		} else if (count == 2) {
			if (empty_ends == 2) return 1000; // 活二(灵活发展)
			else if (empty_ends == 1) return 500; // 冲二
		} else if (count == 1) {
			if (empty_ends == 2) return 100; // 单棋活二潜力
		}
		return 0;
	}
	
	// 评估位置得分(增加防守优先级)
	int evaluate_position(int x, int y, char c) {
		if (gomoku_board[x][y] != 0) return -1; // 非空位不得分
		char opponent = (c == 'X') ? 'O' : 'X';
		int score = 0;
		int dirs[4][2] = {{1,0}, {0,1}, {1,1}, {1,-1}}; // 四个方向
		
		// 先评估AI自身得分
		for (auto &d : dirs) {
			score += evaluate_line(x, y, d[0], d[1], c, opponent);
		}
		
		// 评估对手威胁(防守优先级:对方高威胁需优先处理)
		int opponent_score = 0;
		for (auto &d : dirs) {
			opponent_score += evaluate_line(x, y, d[0], d[1], opponent, c);
		}
		
		// 策略调整:对方有高威胁时(如活四)优先防守
		if (opponent_score >= 100000) {
			score += opponent_score * 1.5; // 紧急防守加权
		} else if (opponent_score >= 10000) {
			score += opponent_score * 1.2; // 高威胁防守加权
		} else {
			score += opponent_score * 0.8; // 普通威胁适当考虑
		}
		
		return score;
	}
	
	// 找到AI最佳落子位置(增加策略性选择)
	pair<int, int> find_best_move() {
		int max_score = -1;
		vector<pair<int, int>> candidates;
		bool has_critical = false; // 是否有紧急落子点
		
		// 遍历所有空位评估得分
		for (int i = 0; i < GOMOKU_SIZE; ++i) {
			for (int j = 0; j < GOMOKU_SIZE; ++j) {
				if (gomoku_board[i][j] == 0) {
					int total = evaluate_position(i, j, 'O');
					
					// 检测是否有必胜或必防点
					if (total >= 1000000) { // AI能直接获胜
						return {i, j};
					}
					if (total >= 150000) { // 对方有活四需紧急阻挡
						max_score = total;
						candidates.clear();
						candidates.emplace_back(i, j);
						has_critical = true;
						continue;
					}
					
					if (!has_critical) {
						if (total > max_score) {
							max_score = total;
							candidates.clear();
							candidates.emplace_back(i, j);
						} else if (total == max_score) {
							candidates.emplace_back(i, j);
						}
					}
				}
			}
		}
		
		// 从最佳候选中随机选择(增加不可预测性)
		int idx = rand() % candidates.size();
		return candidates[idx];
	}
	
	// 五子棋-AI对战
	void gomoku_ai() {
		init_gomoku_board();
		cout << "\n===== 五子棋-AI对战 =====" << endl;
		cout << "你使用 X,AI使用 O,先连成5子获胜!" << endl;
		int turn = 0; // 0-玩家,1-AI
		
		while (true) {
			print_gomoku_board();
			if (turn % 2 == 0) { // 玩家回合
				int x = input_int("请输入行坐标:", 0, GOMOKU_SIZE - 1);
				int y = input_int("请输入列坐标:", 0, GOMOKU_SIZE - 1);
				
				if (gomoku_board[x][y] != 0) {
					cout << "该位置已落子,请重新选择!" << endl;
					continue;
				}
				
				gomoku_board[x][y] = 'X';
				if (check_gomoku_win(x, y, 'X')) {
					print_gomoku_board();
					cout << "恭喜你获胜!" << endl;
					break;
				}
			} else { // AI回合
				auto [ai_x, ai_y] = find_best_move();
				gomoku_board[ai_x][ai_y] = 'O';
				cout << "AI落子:行" << ai_x << " 列" << ai_y << endl;
				if (check_gomoku_win(ai_x, ai_y, 'O')) {
					print_gomoku_board();
					cout << "AI获胜!再接再厉!" << endl;
					break;
				}
			}
			
			turn++;
			if (turn == GOMOKU_SIZE * GOMOKU_SIZE) {
				print_gomoku_board();
				cout << "棋盘已满,平局!" << endl;
				break;
			}
		}
	}
	
	// 游戏菜单
	void game_menu() {
		while (true) {
			cout << "\n===== 游戏菜单 =====" << endl;
			int sel = input_int(
								"1. 猜数字\n"
								"2. 石头剪刀布\n"
								"3. 计算器\n"
								"4. 五子棋-双人\n"
								"5. 五子棋-AI\n"
								"6. 退出\n"
								"请选择:", 1, 6);
			
			switch (sel) {
				case 1: guess_number(); break;
				case 2: rock_paper_scissors(); break;
				case 3: calculator(); break;
				case 4: gomoku_pvp(); break;
				case 5: gomoku_ai(); break;
				case 6: 
				cout << "感谢游玩,再见!" << endl;
				return;
			}
		}
	}
	
	// 用户注册登录流程
	void user_auth() {
		load_users();
		bool logged_in = false;
		
		while (!logged_in) {
			cout << "\n===== 用户中心 =====" << endl;
			int choice = input_int("1. 注册\n2. 登录\n请选择:", 1, 2);
			
			string username, password;
			if (choice == 1) { // 注册
				cout << "请输入用户名:";
				cin >> username;
				cin.ignore(numeric_limits<streamsize>::max(), '\n');
				
				if (users.find(username) != users.end()) {
					cout << "用户名已存在!" << endl;
					continue;
				}
				
				cout << "请输入密码:";
				cin >> password;
				
				string salt = generate_salt();
				string hashed_pass = hash_password(password, salt);
				users[username] = {salt, hashed_pass};
				
				if (save_users()) {
					cout << "注册成功!即将进入游戏菜单~" << endl;
					logged_in = true;
				} else {
					cout << "注册失败,请重试!" << endl;
					users.erase(username);
				}
			} else { // 登录
				cout << "请输入用户名:";
				cin >> username;
				cin.ignore(numeric_limits<streamsize>::max(), '\n');
				
				cout << "请输入密码:";
				cin >> password;
				
				auto it = users.find(username);
				if (it != users.end()) {
					string salt = it->second.first;
					string input_hash = hash_password(password, salt);
					if (input_hash == it->second.second) {
						cout << "登录成功!即将进入游戏菜单~" << endl;
						logged_in = true;
					} else {
						cout << "用户名或密码错误,请重试!" << endl;
					}
				} else {
					cout << "用户名或密码错误,请重试!" << endl;
				}
			}
		}
		
		game_menu();
	}
}

int main() {
	srand((unsigned)time(0));
	
	cout << "开发者:故渊(才译翔)\n";
	cout << "协助开发:(想成为者@才译翔,UID:2430)\n";
	cout << "协助开发者:曹莫凡,UID:1619\n\n";
	
	GameCenter::user_auth();
	
	return 0;
}

代码到此结束,谢谢

0 条评论

目前还没有评论...

信息

ID
116
时间
1000ms
内存
256MiB
难度
8
标签
递交数
56
已通过
9
上传者