diff --git a/.gitignore b/.gitignore index 7c51ec9..bdd9ae2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,10 @@ __pycache__/ .idea/ *.exe *.pyd +*.bak +core.* +*.o +*.so +*.gdb_history +*.pro +*.pro.user diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e502ae4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Attach", + "type": "cppdbg", + "request": "attach", + "program": "/usr/bin/python", + "processId": "${command:pickProcess}", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + { + "name": "Python: GomokuCode", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/GomokuCode/main.py", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/GomokuAi/ai.cpp b/GomokuAi/ai.cpp index ff622fa..b15b875 100755 --- a/GomokuAi/ai.cpp +++ b/GomokuAi/ai.cpp @@ -43,7 +43,7 @@ int Node::JudgeRes() return 0; } -void Node::Judge4(uint32_t& ai_4_num, uint32_t& player_4_num){ +void Node::Judge4(uint64_t& ai_4_num, uint64_t& player_4_num){ player_4_num = 0; ai_4_num = 0; int player_cnt, ai_cnt; @@ -92,7 +92,7 @@ void Node::Judge4(uint32_t& ai_4_num, uint32_t& player_4_num){ } } -void Node::Judge3D(uint32_t& ai_3d_num, uint32_t& player_3d_num){ +void Node::Judge3D(uint64_t& ai_3d_num, uint64_t& player_3d_num){ player_3d_num = 0; ai_3d_num = 0; // 1 xooox的形式 @@ -179,8 +179,8 @@ int Node::CalcScore(){ return -100; // 2.判断玩家和电脑的四子的数目(需要保证:不是已经被堵死的四子) - uint32_t ai_4_num; - uint32_t player_4_num; + uint64_t ai_4_num; + uint64_t player_4_num; Judge4(ai_4_num, player_4_num); // 3.如果能够连成活四,或连成双四,则记为90分 @@ -226,8 +226,8 @@ int Node::CalcScore(){ } // 5.判断玩家和电脑的活三的数目 - uint32_t ai_3d_num; - uint32_t player_3d_num; + uint64_t ai_3d_num; + uint64_t player_3d_num; Judge3D(ai_3d_num, player_3d_num); // 6.如果能够连成四三,则记为80分 @@ -395,7 +395,7 @@ set Node::GetOpeList() return ope_list; } -void AI1Step::Search(const uint32_t cur_node_dx, const uint32_t max_depth){ +void AI1Step::Search(const uint64_t cur_node_dx, const uint64_t max_depth){ // 1.首先确认什么地方可以落子。落子的条件是:这个格子必须为空,周围8格内必须有至少一个棋子 set ope_list = MethodTree[cur_node_dx].GetOpeList(); // 2. 然后对每一个可以落子的格子进行搜索 @@ -453,7 +453,9 @@ void AI1Step::Search(const uint32_t cur_node_dx, const uint32_t max_depth){ NextNodeList[cur_node_dx] = static_cast(node_new_dx); } } - }else{ + } + + else{ if (MethodTree[cur_node_dx].Depth % 2 == 0){ //这一步是假想中电脑走的,因此需要让分数尽量大,且应该修改alpha值 if (MethodTree[node_new_dx].Score > MethodTree[cur_node_dx].Score){ MethodTree[cur_node_dx].Score = MethodTree[node_new_dx].Score; @@ -473,7 +475,7 @@ void AI1Step::Search(const uint32_t cur_node_dx, const uint32_t max_depth){ }else{ //子节点还没有具体分数的情况下,应该以这个子节点为下一层的根节点,进行递归,之后再进行计算 if (max_depth >= 2) - Search(static_cast(node_new_dx), max_depth - 1); + Search(static_cast(node_new_dx), max_depth - 1); //根据递归后计算的结果,计算这个节点的分数 if (PlayerFirst){ if (MethodTree[cur_node_dx].Depth % 2 == 0){ //这一步是假想中玩家走的,因此需要让分数尽量小,且应该修改beta值 @@ -516,7 +518,7 @@ void AI1Step::Search(const uint32_t cur_node_dx, const uint32_t max_depth){ Point AI1Step::GetFinalRes(){ if (NextNodeList[0] == -1){ printf("NextNodeList[0] = -1.\n"); -// abort(); + return Point(-1, -1); } return MethodTree[NextNodeList[0]].Ope; } diff --git a/GomokuAi/ai.h b/GomokuAi/ai.h index 83348ba..c388bae 100755 --- a/GomokuAi/ai.h +++ b/GomokuAi/ai.h @@ -43,8 +43,8 @@ class Node int ForceScore; int PlayerFirst; int JudgeRes(); //判断游戏胜负 - void Judge4(uint32_t& ai_4_num, uint32_t& player_4_num); //判断玩家和电脑的四子的数目 - void Judge3D(uint32_t& ai_3d_num, uint32_t& player_3d_num); //判断玩家和电脑的活三的数目 + void Judge4(uint64_t& ai_4_num, uint64_t& player_4_num); //判断玩家和电脑的四子的数目 + void Judge3D(uint64_t& ai_3d_num, uint64_t& player_3d_num); //判断玩家和电脑的活三的数目 }; @@ -57,10 +57,10 @@ class AI1Step NextNodeList = {-1}; //每个节点的下一步节点列表。-1表示这个节点为最终节点 } - void Search(const uint32_t cur_node_dx, const uint32_t max_depth); + void Search(const uint64_t cur_node_dx, const uint64_t max_depth); Point GetFinalRes(); - uint32_t res; + uint64_t res; vector MethodTree; private: const int PlayerFirst; diff --git a/GomokuAi/constants.cpp b/GomokuAi/constants.cpp index 81ab8f2..7b67396 100755 --- a/GomokuAi/constants.cpp +++ b/GomokuAi/constants.cpp @@ -1,4 +1,4 @@ #include "constants.h" int ScoreByNumArount[9] = {0, 1, 20, 30, 26, 24, 22, 20, 18}; -const uint32_t MaxNodeNum = 1000000; +const uint64_t MaxNodeNum = 1000000; diff --git a/GomokuAi/constants.h b/GomokuAi/constants.h index c402c48..bf4bd81 100755 --- a/GomokuAi/constants.h +++ b/GomokuAi/constants.h @@ -4,4 +4,4 @@ #define AI_DEBUG false extern int ScoreByNumArount[9]; -extern const uint32_t MaxNodeNum; //最大允许的节点数量(避免内存占用过多) +extern const uint64_t MaxNodeNum; //最大允许的节点数量(避免内存占用过多) diff --git a/GomokuAi/gomokuai.cpp b/GomokuAi/gomokuai.cpp index 6de5380..a92b76c 100755 --- a/GomokuAi/gomokuai.cpp +++ b/GomokuAi/gomokuai.cpp @@ -3,14 +3,14 @@ #include #include "ai.h" -Point ai_1step(int p_init_map[225], int init_depth, bool player_first, uint32_t max_depth, int& tree_size) +Point ai_1step(int p_init_map[225], int init_depth, bool player_first, uint64_t max_depth, int& tree_size) { // 1 转换参数 int init_map[15][15]; for (int t = 0; t <= 224; t++){ init_map[t / 15][t % 15] = p_init_map[t]; } - //max_depth = static_cast(atoi(p_max_depth)); + //max_depth = static_cast(atoi(p_max_depth)); char g[550]; sprintf(g, "%d %d %d.\n", init_depth, player_first, max_depth); @@ -36,7 +36,7 @@ PyObject* wrap_ai_1step(PyObject* self, PyObject* args) int init_map[225]; int init_depth; bool player_first; - uint32_t max_depth; + uint64_t max_depth; if (!PyArg_ParseTuple(args, "iiiO", &init_depth_origin, &player_first_origin, &max_depth_origin, &init_map_origin)) { @@ -55,7 +55,7 @@ PyObject* wrap_ai_1step(PyObject* self, PyObject* args) } init_depth = init_depth_origin; player_first = static_cast(player_first_origin); - max_depth = static_cast(max_depth_origin); + max_depth = static_cast(max_depth_origin); int tree_size; Point res = ai_1step(init_map, init_depth, player_first, max_depth, tree_size); return Py_BuildValue("iii", tree_size, res.X, res.Y); diff --git a/GomokuAi/setup.py b/GomokuAi/setup.py new file mode 100644 index 0000000..0dee8dc --- /dev/null +++ b/GomokuAi/setup.py @@ -0,0 +1,9 @@ +# used to build Python Modules on Linux distributions. +from distutils.core import setup,Extension + +MOD = 'example' +setup(name=MOD, + version='1.0', + headers=['./ai.h', './constants.h'], + ext_modules=[Extension(MOD,sources=['./ai.cpp','./constants.cpp', './gomokuai.cpp'], + extra_compile_args=['-O0','-g'])]) \ No newline at end of file diff --git a/GomokuCode/corner_widget.py b/GomokuCode/corner_widget.py index d78aadf..ad2fc8c 100755 --- a/GomokuCode/corner_widget.py +++ b/GomokuCode/corner_widget.py @@ -14,11 +14,11 @@ def paintEvent(self, e): qp.begin(self) pen = QPen(Qt.red, 3, Qt.SolidLine) qp.setPen(pen) - qp.drawLine(0, 8, 0, 0) - qp.drawLine(0, 0, 8, 0) - qp.drawLine(22, 0, 28, 0) - qp.drawLine(28, 0, 28, 8) - qp.drawLine(28, 22, 28, 28) - qp.drawLine(28, 28, 20, 28) - qp.drawLine(8, 28, 0, 28) - qp.drawLine(0, 28, 0, 22) + qp.drawLine(8, 8, 0, 8) + qp.drawLine(8, 8, 8, 0) + qp.drawLine(22, 8, 28, 8) + qp.drawLine(20, 0, 20, 8) + qp.drawLine(20, 22, 20, 28) + qp.drawLine(28, 20, 20, 20) + qp.drawLine(8, 20, 0, 20) + qp.drawLine(8, 28, 8, 22) diff --git a/GomokuCode/game.py b/GomokuCode/game.py index bd4cf14..1944ffd 100755 --- a/GomokuCode/game.py +++ b/GomokuCode/game.py @@ -1,7 +1,7 @@ import os import time -AI_USE_CPP = False +AI_USE_CPP = True if not AI_USE_CPP: # 是否用C++版的AI脚本 from ai import AI1Step @@ -32,7 +32,9 @@ def move_1step(self, input_by_window=False, pos_x=None, pos_y=None): if self.g_map[pos_x][pos_y] == 0: self.g_map[pos_x][pos_y] = 1 self.cur_step += 1 - return + return True + else: return False + except ValueError: # 玩家输入不正确的情况(例如输入了‘A’) continue @@ -124,10 +126,13 @@ def ai_play_1step_by_cpp(self): for x in range(15): mapstring.extend(self.g_map[x]) try: - node_len, ai_ope_x, ai_poe_y = example.ai_1step(self.cur_step, int(True), self.max_search_steps, mapstring) - ai_ope = [ai_ope_x, ai_poe_y] + node_len, ai_ope_x, ai_ope_y = example.ai_1step(self.cur_step, int(True), self.max_search_steps, mapstring) + if (ai_ope_x == -1 & ai_ope_y == -1): + raise ValueError('Leaf Node met') + ai_ope = [ai_ope_x, ai_ope_y] except ValueError: raise ValueError('AI程序计算出来的数值不正确') + print('Coordinate:%d %d' % (ai_ope_x, ai_ope_y)) ed = time.time() print('生成了%d个节点,用时%.4f' % (node_len, ed - st)) self.g_map[ai_ope[0]][ai_ope[1]] = 2 diff --git a/GomokuCode/window.py b/GomokuCode/window.py index 3e9e08f..63f39e9 100755 --- a/GomokuCode/window.py +++ b/GomokuCode/window.py @@ -150,7 +150,9 @@ def mousePressEvent(self, e): game_y = int((mouse_y + 15) // 40) - 1 else: # 鼠标点击的位置不正确 return - self.g.move_1step(True, game_x, game_y) + isMoveSuccess = self.g.move_1step(True, game_x, game_y) + if not isMoveSuccess: + return # 2. 根据操作结果进行一轮游戏循环 res, self.flash_pieces = self.g.game_result(show=True) # 判断游戏结果 diff --git a/GomokuCode_NoAI/game.py b/GomokuCode_NoAI/game.py index 64414fa..d07c882 100755 --- a/GomokuCode_NoAI/game.py +++ b/GomokuCode_NoAI/game.py @@ -20,7 +20,8 @@ def move_1step(self, input_by_window=False, pos_x=None, pos_y=None): if self.g_map[pos_x][pos_y] == 0: self.g_map[pos_x][pos_y] = 1 self.cur_step += 1 - return + return True + else: return False except ValueError: # 玩家输入不正确的情况(例如输入了‘A’) continue diff --git a/GomokuCode_NoAI/imgs/muzm.jpg b/GomokuCode_NoAI/imgs/muzm.jpg old mode 100755 new mode 100644 index d81dbef..e85e9e2 Binary files a/GomokuCode_NoAI/imgs/muzm.jpg and b/GomokuCode_NoAI/imgs/muzm.jpg differ diff --git a/GomokuCode_NoAI/imgs/muzm.jpg.back b/GomokuCode_NoAI/imgs/muzm.jpg.back new file mode 100755 index 0000000..d81dbef Binary files /dev/null and b/GomokuCode_NoAI/imgs/muzm.jpg.back differ diff --git a/GomokuCode_NoAI/window.py b/GomokuCode_NoAI/window.py index 54e9e6d..0123ba8 100755 --- a/GomokuCode_NoAI/window.py +++ b/GomokuCode_NoAI/window.py @@ -145,12 +145,14 @@ def mousePressEvent(self, e): # 1. 首先判断按下了哪个格子 mouse_x = e.windowPos().x() mouse_y = e.windowPos().y() - if (mouse_x % 40 <= 15 or mouse_x % 40 >= 25) and (mouse_y % 40 <= 15 or mouse_y % 40 >= 25): + if (mouse_x % 40 <= 15 or mouse_x % 40 >= 25) and (mouse_y % 40 <= 15 or mouse_y % 40 >= 25):1step game_x = int((mouse_x + 15) // 40) - 1 game_y = int((mouse_y + 15) // 40) - 1 else: # 鼠标点击的位置不正确 return - self.g.move_1step(True, game_x, game_y) + isMoveSuccess = self.g.move_1step(True, game_x, game_y) + if not isMoveSuccess: + return # 2. 根据操作结果进行一轮游戏循环 res, self.flash_pieces = self.g.game_result(show=True) # 判断游戏结果