mirror of
https://github.com/LHY0125/Gobang-Game.git
synced 2026-05-10 02:19:46 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f897536a45 |
+2
-4
@@ -34,7 +34,7 @@
|
|||||||
//---------- 游戏设置默认值 ----------//
|
//---------- 游戏设置默认值 ----------//
|
||||||
#define DEFAULT_USE_FORBIDDEN_MOVES false // 默认不启用禁手规则
|
#define DEFAULT_USE_FORBIDDEN_MOVES false // 默认不启用禁手规则
|
||||||
#define DEFAULT_USE_TIMER 0 // 默认不启用计时器
|
#define DEFAULT_USE_TIMER 0 // 默认不启用计时器
|
||||||
#define DEFAULT_TIME_LIMIT 30 // 默认时间限制为30秒(内部存储)
|
#define DEFAULT_TIME_LIMIT 1800 // 默认时间限制为30分钟(内部以秒存储: 30*60)
|
||||||
|
|
||||||
//---------- AI参数 ----------//
|
//---------- AI参数 ----------//
|
||||||
#define DEFAULT_AI_DEPTH 5 // 默认AI搜索深度
|
#define DEFAULT_AI_DEPTH 5 // 默认AI搜索深度
|
||||||
@@ -48,8 +48,6 @@
|
|||||||
#define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小
|
#define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小
|
||||||
|
|
||||||
// 网络配置
|
// 网络配置
|
||||||
#define DEFAULT_PORT 8888 // 默认端口(与DEFAULT_NETWORK_PORT保持一致)
|
|
||||||
#define BUFFER_SIZE 1024 // 缓冲区大小(与NETWORK_BUFFER_SIZE保持一致)
|
|
||||||
#define MAX_IP_LENGTH 16 // 最大IP地址长度
|
#define MAX_IP_LENGTH 16 // 最大IP地址长度
|
||||||
|
|
||||||
// 网络消息类型
|
// 网络消息类型
|
||||||
@@ -65,7 +63,7 @@
|
|||||||
|
|
||||||
//---------- 评分参数 ----------//
|
//---------- 评分参数 ----------//
|
||||||
// 棋型评分 - 用于calculate_step_score函数
|
// 棋型评分 - 用于calculate_step_score函数
|
||||||
#define SCORE_FIVE 0 // 五连
|
#define SCORE_FIVE 5000 // 五连
|
||||||
#define SCORE_LIVE_FOUR 2000 // 活四
|
#define SCORE_LIVE_FOUR 2000 // 活四
|
||||||
#define SCORE_RUSH_FOUR 1000 // 冲四
|
#define SCORE_RUSH_FOUR 1000 // 冲四
|
||||||
#define SCORE_DEAD_FOUR 300 // 死四
|
#define SCORE_DEAD_FOUR 300 // 死四
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ extern int ai_difficulty; // AI难度 (1-5)
|
|||||||
extern NetworkGameState network_state; // 网络游戏状态
|
extern NetworkGameState network_state; // 网络游戏状态
|
||||||
|
|
||||||
// ==================== GUI相关变量 ====================
|
// ==================== GUI相关变量 ====================
|
||||||
// Raylib 不需要暴露窗口和渲染器指针
|
|
||||||
extern int gui_running; // GUI运行状态标志
|
|
||||||
extern int current_player_gui; // GUI当前玩家
|
extern int current_player_gui; // GUI当前玩家
|
||||||
extern int game_over; // 游戏结束标志
|
extern int game_over; // 游戏结束标志
|
||||||
extern char status_message[256]; // 状态消息
|
extern char status_message[256]; // 状态消息
|
||||||
|
|||||||
+3
-39
@@ -1,9 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file gui.h
|
* @file gui.h
|
||||||
* @brief 图形化用户界面头文件
|
* @brief 图形化用户界面头文件
|
||||||
* @note 使用Raylib库实现五子棋的图形化界面
|
* @note 使用IUP库实现五子棋的图形化界面
|
||||||
* @author 刘航宇
|
* @author 刘航宇
|
||||||
* @date 2025-01-15
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GUI_H
|
#ifndef GUI_H
|
||||||
@@ -17,45 +16,16 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化GUI
|
* @brief 初始化GUI
|
||||||
* @details 初始化Raylib图形库和游戏界面组件
|
* @details 初始化IUP图形库和游戏界面组件
|
||||||
* @return 成功返回0,失败返回-1
|
* @return 成功返回0,失败返回-1
|
||||||
*/
|
*/
|
||||||
int init_gui();
|
int init_gui();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 清理GUI资源
|
* @brief 清理GUI资源
|
||||||
* @details 关闭窗口
|
|
||||||
*/
|
*/
|
||||||
void cleanup_gui();
|
void cleanup_gui();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 渲染游戏画面
|
|
||||||
* @details 完整的游戏画面渲染流程
|
|
||||||
*/
|
|
||||||
void render_game();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 处理事件
|
|
||||||
* @details 处理所有Raylib事件并执行相应操作
|
|
||||||
* @return 继续运行返回1,退出返回0
|
|
||||||
*/
|
|
||||||
int handle_events();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 绘制棋盘
|
|
||||||
*/
|
|
||||||
void draw_board();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 绘制棋子
|
|
||||||
*/
|
|
||||||
void draw_stones();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 绘制UI元素
|
|
||||||
*/
|
|
||||||
void draw_ui_elements();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 屏幕坐标转棋盘坐标
|
* @brief 屏幕坐标转棋盘坐标
|
||||||
*/
|
*/
|
||||||
@@ -81,16 +51,10 @@ void start_pve_game_gui();
|
|||||||
*/
|
*/
|
||||||
void start_replay_gui();
|
void start_replay_gui();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 启动图形化界面模式
|
|
||||||
* @note 替代原来的 main 函数中的 GUI 分支逻辑
|
|
||||||
*/
|
|
||||||
int init_gui(); // Already declared
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 运行图形化界面模式
|
* @brief 运行图形化界面模式
|
||||||
* @details 主循环处理事件、渲染画面和更新状态
|
* @details 主循环处理事件、渲染画面和更新状态
|
||||||
*/
|
*/
|
||||||
void run_gui_mode();
|
void run_gui_mode();
|
||||||
|
|
||||||
#endif // GUI_H
|
#endif // GUI_H
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ extern Ihandle *dlg;
|
|||||||
extern Ihandle *board_canvas;
|
extern Ihandle *board_canvas;
|
||||||
extern Ihandle *lbl_player;
|
extern Ihandle *lbl_player;
|
||||||
extern Ihandle *lbl_status;
|
extern Ihandle *lbl_status;
|
||||||
extern int gui_loop_running;
|
|
||||||
extern int gui_game_mode; // 0: PvP, 1: PvE, 2: Replay
|
extern int gui_game_mode; // 0: PvP, 1: PvE, 2: Replay
|
||||||
extern int replay_total_steps; // 复盘总步数
|
extern int replay_total_steps; // 复盘总步数
|
||||||
|
|
||||||
|
|||||||
@@ -532,8 +532,9 @@ ThreatLevel detect_threat(int x, int y, int player)
|
|||||||
// 恢复棋盘
|
// 恢复棋盘
|
||||||
board[x][y] = EMPTY;
|
board[x][y] = EMPTY;
|
||||||
|
|
||||||
// 如果有多个威胁,提升威胁等级
|
// 如果有多个活三威胁,升级为双威胁(如双三、四三等组合)
|
||||||
if (threat_count >= 2 && max_threat >= THREAT_THREE)
|
// 注意:不能把已经是活四的威胁降级为双威胁
|
||||||
|
if (threat_count >= 2 && max_threat == THREAT_THREE)
|
||||||
{
|
{
|
||||||
max_threat = THREAT_DOUBLE;
|
max_threat = THREAT_DOUBLE;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -48,7 +48,11 @@ void load_game_config()
|
|||||||
}
|
}
|
||||||
else if (strncmp(line, "TIME_LIMIT=", 11) == 0)
|
else if (strncmp(line, "TIME_LIMIT=", 11) == 0)
|
||||||
{
|
{
|
||||||
time_limit = atoi(line + 11);
|
int minutes = atoi(line + 11);
|
||||||
|
if (minutes > 0)
|
||||||
|
{
|
||||||
|
time_limit = minutes * 60; // 配置文件存分钟,内部转为秒
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strncmp(line, "NETWORK_PORT=", 13) == 0)
|
else if (strncmp(line, "NETWORK_PORT=", 13) == 0)
|
||||||
{
|
{
|
||||||
@@ -101,7 +105,7 @@ void save_game_config()
|
|||||||
fprintf(file, "\n# 计时器 (0=关闭, 1=开启)\n");
|
fprintf(file, "\n# 计时器 (0=关闭, 1=开启)\n");
|
||||||
fprintf(file, "USE_TIMER=%d\n", use_timer);
|
fprintf(file, "USE_TIMER=%d\n", use_timer);
|
||||||
fprintf(file, "\n# 时间限制 (分钟)\n");
|
fprintf(file, "\n# 时间限制 (分钟)\n");
|
||||||
fprintf(file, "TIME_LIMIT=%d\n", time_limit);
|
fprintf(file, "TIME_LIMIT=%d\n", time_limit / 60); // 内部存秒,配置文件存分钟
|
||||||
fprintf(file, "\n# 网络端口 (范围: %d-%d)\n", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
|
fprintf(file, "\n# 网络端口 (范围: %d-%d)\n", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
|
||||||
fprintf(file, "NETWORK_PORT=%d\n", network_port);
|
fprintf(file, "NETWORK_PORT=%d\n", network_port);
|
||||||
fprintf(file, "\n# 网络超时时间 (毫秒)\n");
|
fprintf(file, "\n# 网络超时时间 (毫秒)\n");
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ int ai_difficulty = 3; // AI难度 (1-5)
|
|||||||
NetworkGameState network_state = {0}; // 网络游戏状态
|
NetworkGameState network_state = {0}; // 网络游戏状态
|
||||||
|
|
||||||
// ==================== GUI相关变量定义 ====================
|
// ==================== GUI相关变量定义 ====================
|
||||||
int gui_running = 1; // GUI运行状态标志
|
|
||||||
int current_player_gui = PLAYER; // GUI当前玩家
|
int current_player_gui = PLAYER; // GUI当前玩家
|
||||||
int game_over = 0; // 游戏结束标志
|
int game_over = 0; // 游戏结束标志
|
||||||
char status_message[256] = "五子棋游戏 - 黑子先行"; // 状态消息
|
char status_message[256] = "五子棋游戏 - 黑子先行"; // 状态消息
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ Ihandle *dlg = NULL;
|
|||||||
Ihandle *board_canvas = NULL;
|
Ihandle *board_canvas = NULL;
|
||||||
Ihandle *lbl_player = NULL;
|
Ihandle *lbl_player = NULL;
|
||||||
Ihandle *lbl_status = NULL;
|
Ihandle *lbl_status = NULL;
|
||||||
int gui_loop_running = 0;
|
|
||||||
int gui_game_mode = 0; // 0: PvP, 1: PvE, 2: Replay, 3: Network
|
int gui_game_mode = 0; // 0: PvP, 1: PvE, 2: Replay, 3: Network
|
||||||
int replay_total_steps = 0; // 复盘总步数
|
int replay_total_steps = 0; // 复盘总步数
|
||||||
|
|
||||||
@@ -32,8 +31,6 @@ int init_gui()
|
|||||||
create_main_menu();
|
create_main_menu();
|
||||||
show_main_menu();
|
show_main_menu();
|
||||||
|
|
||||||
gui_loop_running = 1;
|
|
||||||
|
|
||||||
printf("图形化界面初始化成功!(IUP)\n");
|
printf("图形化界面初始化成功!(IUP)\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -37,7 +37,7 @@ static int btn_network_host_cb(Ihandle *ih)
|
|||||||
Ihandle *dlg = IupGetDialog(ih);
|
Ihandle *dlg = IupGetDialog(ih);
|
||||||
Ihandle *txt_port = IupGetDialogChild(dlg, "NET_PORT");
|
Ihandle *txt_port = IupGetDialogChild(dlg, "NET_PORT");
|
||||||
int port = IupGetInt(txt_port, "VALUE");
|
int port = IupGetInt(txt_port, "VALUE");
|
||||||
if (port <= 0 || port > 65535) port = DEFAULT_PORT;
|
if (port <= 0 || port > 65535) port = DEFAULT_NETWORK_PORT;
|
||||||
|
|
||||||
if (create_server(port))
|
if (create_server(port))
|
||||||
{
|
{
|
||||||
@@ -61,7 +61,7 @@ static int btn_network_join_cb(Ihandle *ih)
|
|||||||
|
|
||||||
char *ip = IupGetAttribute(txt_ip, "VALUE");
|
char *ip = IupGetAttribute(txt_ip, "VALUE");
|
||||||
int port = IupGetInt(txt_port, "VALUE");
|
int port = IupGetInt(txt_port, "VALUE");
|
||||||
if (port <= 0 || port > 65535) port = DEFAULT_PORT;
|
if (port <= 0 || port > 65535) port = DEFAULT_NETWORK_PORT;
|
||||||
|
|
||||||
if (connect_to_server(ip, port))
|
if (connect_to_server(ip, port))
|
||||||
{
|
{
|
||||||
@@ -97,7 +97,7 @@ static int btn_network_cb(Ihandle *ih)
|
|||||||
Ihandle *txt_port = IupText(NULL);
|
Ihandle *txt_port = IupText(NULL);
|
||||||
IupSetAttribute(txt_port, "NAME", "NET_PORT");
|
IupSetAttribute(txt_port, "NAME", "NET_PORT");
|
||||||
char port_str[16];
|
char port_str[16];
|
||||||
sprintf(port_str, "%d", DEFAULT_PORT);
|
sprintf(port_str, "%d", DEFAULT_NETWORK_PORT);
|
||||||
IupSetAttribute(txt_port, "VALUE", port_str);
|
IupSetAttribute(txt_port, "VALUE", port_str);
|
||||||
IupSetAttribute(txt_port, "SIZE", "50x");
|
IupSetAttribute(txt_port, "SIZE", "50x");
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
// 设置控制台编码为UTF-8
|
// 设置控制台编码为UTF-8
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
system("chcp 65001 > nul"); // 设置控制台编码为UTF-8
|
|
||||||
SetConsoleOutputCP(65001); // 设置控制台输出编码
|
SetConsoleOutputCP(65001); // 设置控制台输出编码
|
||||||
SetConsoleCP(65001); // 设置控制台输入编码
|
SetConsoleCP(65001); // 设置控制台输入编码
|
||||||
_mkdir("records");
|
_mkdir("records");
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ bool init_network()
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(&network_state, 0, sizeof(NetworkGameState));
|
memset(&network_state, 0, sizeof(NetworkGameState));
|
||||||
network_state.port = DEFAULT_PORT;
|
network_state.port = DEFAULT_NETWORK_PORT;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-24
@@ -23,29 +23,6 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 复盘游戏全过程并展示评分
|
|
||||||
* @note 实现流程:
|
|
||||||
* 1. 初始化临时复盘棋盘
|
|
||||||
* 2. 按步数顺序逐步重现每个落子
|
|
||||||
* 3. 每步显示:
|
|
||||||
* - 当前步数/总步数
|
|
||||||
* - 落子方(玩家/AI)
|
|
||||||
* - 落子位置(1-based坐标)
|
|
||||||
* - 当前棋盘状态
|
|
||||||
* 4. 通过用户按Enter键控制步骤前进
|
|
||||||
* 5. 复盘结束后自动进入评分环节:
|
|
||||||
* - 评估双方表现
|
|
||||||
* - 显示得分
|
|
||||||
* - 评选MVP
|
|
||||||
* @note 技术细节:
|
|
||||||
* - 使用独立临时棋盘避免影响主游戏状态
|
|
||||||
* - 坐标显示转换为1-based方便用户理解
|
|
||||||
* - 包含输入缓冲区清理防止意外输入
|
|
||||||
* - 评分环节调用calculate_final_score()函数
|
|
||||||
*/
|
|
||||||
void calculate_game_scores();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 计算游戏评分
|
* @brief 计算游戏评分
|
||||||
*/
|
*/
|
||||||
@@ -99,7 +76,7 @@ void calculate_game_scores()
|
|||||||
void display_game_scores(int game_mode)
|
void display_game_scores(int game_mode)
|
||||||
{
|
{
|
||||||
printf("\n===== 对局评分 =====\n");
|
printf("\n===== 对局评分 =====\n");
|
||||||
double sum_score = (long double)player1_final_score + (long double)player2_final_score;
|
double sum_score = (double)player1_final_score + (double)player2_final_score;
|
||||||
|
|
||||||
if (sum_score > 0)
|
if (sum_score > 0)
|
||||||
{
|
{
|
||||||
@@ -379,11 +356,21 @@ int load_game_from_file(const char *filename)
|
|||||||
|
|
||||||
while (fgets(buffer, sizeof(buffer), file) != NULL)
|
while (fgets(buffer, sizeof(buffer), file) != NULL)
|
||||||
{
|
{
|
||||||
|
if (step_count >= MAX_STEPS)
|
||||||
|
{
|
||||||
|
break; // 防止数组越界
|
||||||
|
}
|
||||||
if (sscanf(buffer, "%d,%d,%d,%d", &step_num, &steps[step_count].player, &steps[step_count].x, &steps[step_count].y) == 4)
|
if (sscanf(buffer, "%d,%d,%d,%d", &step_num, &steps[step_count].player, &steps[step_count].x, &steps[step_count].y) == 4)
|
||||||
{
|
{
|
||||||
// 将1-based坐标转换为0-based坐标
|
// 将1-based坐标转换为0-based坐标
|
||||||
steps[step_count].x--;
|
steps[step_count].x--;
|
||||||
steps[step_count].y--;
|
steps[step_count].y--;
|
||||||
|
// 验证坐标合法性
|
||||||
|
if (steps[step_count].x < 0 || steps[step_count].x >= size ||
|
||||||
|
steps[step_count].y < 0 || steps[step_count].y >= size)
|
||||||
|
{
|
||||||
|
continue; // 跳过非法坐标
|
||||||
|
}
|
||||||
step_count++;
|
step_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user