def mouseReleaseEvent(self, a0: QMouseEvent): if self.is_over: # 如果游戏已经结束,点击失效 return # 如果点击在棋盘区域 if a0.x() >= 50 and a0.x() <= 50 + 30 * 18 + 14 and a0.y( ) >= 50 and a0.y() <= 50 + 30 * 18 + 14: # 讲像素坐标转化成棋盘坐标,判断棋盘此位置是否为空 pos = trans_pos(a0) if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 # 不为空,则生成棋子并显示 self.chess = Chessman(self.color, self) self.chess.move(a0.pos()) self.logo_move() self.chess.show() self.change_color() pygame.mixer.music.play() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片
def auto_run(self): ''' 电脑自动执行落子操作 :return: 自动落子 ''' # 找到能下棋的空位置中,假设电脑和人下在此处,得到分数中最大值 score_c = [[0 for i in range(0, 19)] for i in range(0, 19)] score_p = [[0 for i in range(0, 19)] for i in range(0, 19)] # 计算所有的分数 for j in range(0, 19): for i in range(0, 19): if chessboard[i][j] is None: # 如果此处为空 , 计算此处分数,分别记下落黑子和落白子不同的分数 chessboard[i][j] = Chessman('b', parent=self) score_c[i][j] += self.score(i, j, 'b') chessboard[i][j] = Chessman('w', parent=self) score_p[i][j] += self.score(i, j, 'w') chessboard[i][j].close() chessboard[i][j] = None # 为便于计算,将两个二维数组,转换成两个一位数组 r_score_c = [] for item in score_c: r_score_c.extend(item) r_score_p = [] for item in score_p: r_score_p.extend(item) # 最终分数,取两个数组中的最大值合并成一个数组 result = [max(a, b) for a, b in zip(r_score_c, r_score_p)] # 取最大值点的下标 chess_index = result.index(max(result)) # 通过下标计算出位置并落子 x = chess_index // 19 y = chess_index % 19 self.chess = Chessman(self.color, self) self.chess.move(QPoint(y * 30 + 50, x * 30 + 50)) self.chess.show() self.logo_move() self.change_color() pygame.mixer.music.play() chessboard[x][y] = self.chess history.append((x, y, self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return None
def mouseReleaseEvent(self, a0: QMouseEvent): if self.is_over: # 如果游戏已经结束,点击失效 return if not self.my_turn: print("not my turn") return # 如果点击在棋盘区域 if a0.x() >= 50 and a0.x() <= 50 + 30 * 19 and a0.y() >= 50 and a0.y( ) <= 50 + 30 * 19: # 讲像素坐标转化成棋盘坐标,判断棋盘此位置是否为空 pos = trans_pos(a0) if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 # 不为空,则生成棋子并显示 self.chess = Chessman(self.color, self) self.chess.move(a0.pos()) self.chess.show() pygame.mixer.music.play() # 播放声音 self.logo_move() # 移动小标 self.change_color() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 将坐标发送给另一方 if self.tcp_socket is not None: data = {"msg": "position", "data": pos} self.tcp_socket.sendall((json.dumps(data) + " END").encode()) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return self.my_turn = False self.label_statuvalue.setText("对方回合")
class DoublePlayer(BasePlayer): # 双人对战窗体 def __init__(self, parent=None): super().__init__(parent) # 清空棋盘 global chessboard chessboard = [[None for i in range(0, 19)] for i in range(0, 19)] self.is_over = False # 标识黑旗白旗 self.color = 'w' # 三个按钮点击触发的函数 self.restart_button.click_signal.connect(self.restart) self.huiqi_button.click_signal.connect(self.goback) self.renshu_button.click_signal.connect(self.lose) self.win_label = None self.chess_pos.hide() # 这个位置标识隐藏起来 def win(self, color): ''' 黑旗胜利或者白棋胜利了 ''' if color == 'b': win_pic = QPixmap('source/黑棋胜利.png') else: win_pic = QPixmap('source/白棋胜利.png') self.win_label = QLabel(parent=self) self.win_label.setPixmap(win_pic) self.win_label.resize(win_pic.size()) self.win_label.move(50, 50) # 显示游戏结束的图片 self.win_label.show() self.is_over = True # 游戏结束 def mouseReleaseEvent(self, a0: QMouseEvent): if self.is_over: # 如果游戏已经结束,点击失效 return # 如果点击在棋盘区域 if a0.x() >= 50 and a0.x() <= 50 + 30 * 18 + 14 and a0.y( ) >= 50 and a0.y() <= 50 + 30 * 18 + 14: # 讲像素坐标转化成棋盘坐标,判断棋盘此位置是否为空 pos = trans_pos(a0) if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 # 不为空,则生成棋子并显示 self.chess = Chessman(self.color, self) self.chess.move(a0.pos()) self.logo_move() self.chess.show() self.change_color() pygame.mixer.music.play() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 def change_color(self): if self.color == 'w': self.color = 'b' else: self.color = 'w' def restart(self): ''' 重新开始游戏 ''' # 清空所有棋子 for j in range(0, 19): for i in range(0, 19): if chessboard[i][j] is not None: chessboard[i][j].close() chessboard[i][j] = None history.clear() #清空历史数组 if self.is_over: # 如果游戏已经结束 self.win_label.close() self.win_label = None self.is_over = False self.chess_pos.hide() # 这个位置标识隐藏起来 def goback(self): ''' 悔棋按钮 ''' if self.is_over: return None # 如果游戏已经结束了 if len(history) == 0: return None # 没有落子,不能悔棋 chess = history.pop(-1) chessboard[chess[0]][chess[1]].close() chessboard[chess[0]][chess[1]] = None self.change_color() self.chess_pos.hide() # 这个位置标识隐藏起来 def lose(self): ''' 认输按钮 ''' if self.is_over: return None # 如果游戏已经结束了 self.win(self.color) def logo_move(self): self.chess_pos.show() self.chess_pos.move(self.chess.pos()) self.chess_pos.raise_()
class NetworkPlayer(BasePlayer): dataSignal = pyqtSignal(dict, name='data') # 网络对战窗体 def __init__(self, name, parent=None): super().__init__(parent) self.ip = None self.name = name self.label_statu = QLabel("游戏状态:", self) self.label_statu.resize(100, 20) self.label_statuvalue = QLabel("等待连接", self) self.label_statuvalue.resize(200, 30) self.label_statuvalue.setAlignment(Qt.AlignTop) self.label_statu.move(630, 200) self.label_statuvalue.move(690, 204) # 清空棋盘 global chessboard chessboard = [[None for i in range(0, 19)] for i in range(0, 19)] # 默认情况下游戏是结束状态, 通过开始按钮才可以触发 self.is_over = True # 标识黑旗白旗 self.color = 'w' # 是否是我的回合 self.my_turn = False # 三个按钮点击触发的函数 self.restart_button.click_signal.connect(self.restart) self.huiqi_button.click_signal.connect(self.goback) self.renshu_button.click_signal.connect(self.lose) self.win_label = None self.cuicu_button = TDPushButton(self, "source/催促按钮_normal.png", "source/催促按钮_hover.png", "source/催促按钮_press.png", parent=self) self.cuicu_button.move(640, 450) self.cuicu_button.click_signal.connect(self.cuicu) self.chess_pos.hide() # 这个位置标识隐藏起来 # 网络模块启动 self.is_connected = False # 默认情况下没有连接 self.is_listening = False # 默认情况下没有监听 self.tcp_socket = None # 默认情况下网络连接为None self.dataSignal.connect(self.deal_data) def deal_data(self, data): ''' 对收到的数据进行处理 ''' print(data) if data['msg'] == 'action': if data['data'] == 'restart': result = QMessageBox.information( self, "消息", "对方请求(重新)开始游戏,是否同意?", QMessageBox.Yes | QMessageBox.No) if result == QMessageBox.Yes: data = {"msg": "replay", "data": True, "type": "restart"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) self.restart_func() self.is_over = False if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") else: data = {"msg": "replay", "data": False, "type": "restart"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) self.label_statuvalue.setText("点击开始") if data['data'] == 'lose': QMessageBox.information(self, "消息", "对方认输") if self.my_turn: self.win(color=self.color) # self.change_color() else: self.change_color() self.win(color=self.color) if data['data'] == 'goback': result = QMessageBox.information( self, "消息", "对方请求悔棋,是否同意?", QMessageBox.Yes | QMessageBox.No) if result == QMessageBox.Yes: data = {"msg": "replay", "data": True, "type": "goback"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) self.goback_func() # self.is_over = False if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") else: data = {"msg": "replay", "data": False, "type": "goback"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) # self.label_statuvalue.setText("等待开始") if data['data'] == 'cuicu': print(self.is_connected) if not self.is_connected: return if self.is_over: return print("cuicu") sound.play() # pygame.mixer.music.load("source/luozisheng.wav") if data['data'] == 'ready': pass if data['data'] == 'exit': # 对方退出游戏 self.is_connected = False self.is_listening = False self.tcp_socket.close() self.tcp_socket = None print(data) elif data['msg'] == 'position': print(data['data']) # 在对应位置落子 pos = data['data'] if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 self.chess = Chessman(self.color, self) self.chess.move(QPoint(pos[0] * 30 + 50, pos[1] * 30 + 50)) self.chess.show() pygame.mixer.music.play() # 播放声音 self.logo_move() # 移动小标 self.change_color() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return self.my_turn = True self.label_statuvalue.setText("己方回合") elif data['msg'] == 'replay': if data['type'] == 'restart': # 重开回执 if data['data'] == True: self.restart_func() else: QMessageBox.information(self, "消息", "对方拒绝了你的请求") self.label_statuvalue.setText("点击开始") return if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") if data['type'] == 'goback': # 悔棋回执 if data['data'] == True: self.is_over = False self.goback_func() else: QMessageBox.information(self, '消息', '对方拒绝了你的请求') if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") self.is_over = False elif data['msg'] == 'name': self.setWindowTitle('与 {} 对战中'.format(data['data'])) def restart_func(self): # 清空所有棋子 for j in range(0, 19): for i in range(0, 19): if chessboard[i][j] is not None: chessboard[i][j].close() chessboard[i][j] = None history.clear() # 清空历史数组 if self.is_over: # 如果游戏已经结束 if self.win_label is not None: self.win_label.close() self.win_label = None self.is_over = False self.chess_pos.hide() # 这个位置标识隐藏起来 def recv_data(self, sock, addr): self.is_connected = True # 连接状态 print("start receiving data ...") while True: print("start receiving data ...") try: res_data = recv_sockdata(sock) except (ConnectionAbortedError, ConnectionResetError): print("对方离开游戏") # QMessageBox.information(self,"提示","对方已经断开连接") self.is_connected = False # 连接断开 self.label_statuvalue.setText("对方断线,\n点击开始重试") break try: data = json.loads(res_data, encoding="utf-8") except json.decoder.JSONDecodeError as e: print("error data:\n" + res_data) continue # 在线程处理函数中不能直接进行界面的相关操作,所以用一个信号把数据发送出来 self.dataSignal.emit(data) # self.deal_data(data,parent) self.is_connected = False # 连接断开 self.tcp_socket.close() def closeEvent(self, a0: QCloseEvent): if self.tcp_socket is not None and self.is_connected == True: self.tcp_socket.sendall((json.dumps({ "msg": "action", "data": "exit" })).encode()) self.tcp_socket.close() return super().closeEvent(a0) def win(self, color): ''' 黑旗胜利或者白棋胜利了 ''' if color == 'b': win_pic = QPixmap('source/黑棋胜利.png') self.label_statuvalue.setText("黑旗胜利") else: win_pic = QPixmap('source/白棋胜利.png') self.label_statuvalue.setText("白棋胜利") self.win_label = QLabel(parent=self) self.win_label.setPixmap(win_pic) self.win_label.resize(win_pic.size()) self.win_label.move(50, 50) # 显示游戏结束的图片 self.win_label.show() self.is_over = True # 游戏结束 def mouseReleaseEvent(self, a0: QMouseEvent): if self.is_over: # 如果游戏已经结束,点击失效 return if not self.my_turn: print("not my turn") return # 如果点击在棋盘区域 if a0.x() >= 50 and a0.x() <= 50 + 30 * 19 and a0.y() >= 50 and a0.y( ) <= 50 + 30 * 19: # 讲像素坐标转化成棋盘坐标,判断棋盘此位置是否为空 pos = trans_pos(a0) if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 # 不为空,则生成棋子并显示 self.chess = Chessman(self.color, self) self.chess.move(a0.pos()) self.chess.show() pygame.mixer.music.play() # 播放声音 self.logo_move() # 移动小标 self.change_color() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 将坐标发送给另一方 if self.tcp_socket is not None: data = {"msg": "position", "data": pos} self.tcp_socket.sendall((json.dumps(data) + " END").encode()) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return self.my_turn = False self.label_statuvalue.setText("对方回合") def change_color(self): if self.color == 'w': self.color = 'b' else: self.color = 'w' def restart(self): ''' 重新开始游戏 ''' pass def goback(self): ''' 悔棋按钮 ''' if self.my_turn is False: return # 如果是对方回合,不能悔棋 if self.is_over: return if not self.is_connected: return else: data = {"msg": "action", "data": "goback"} self.tcp_socket.sendall((json.dumps(data) + " END").encode()) self.label_statuvalue.setText("请求悔棋") self.is_over = True def goback_func(self): if self.is_over: return None # 如果游戏已经结束了 if len(history) == 0: return None # 没有落子,不能悔棋 chess = history.pop(-1) chessboard[chess[0]][chess[1]].close() chessboard[chess[0]][chess[1]] = None # self.change_color() if len(history) == 0: return None # 没有落子,不能悔棋 chess = history.pop(-1) chessboard[chess[0]][chess[1]].close() chessboard[chess[0]][chess[1]] = None # self.change_color() self.chess_pos.hide() # 这个位置标识隐藏起来 def lose(self): ''' 认输按钮 ''' if self.is_over: return if not self.is_connected: return else: data = {"msg": "action", "data": "lose"} self.tcp_socket.sendall((json.dumps(data) + " END").encode()) self.label_statuvalue.setText("对方胜利") if self.my_turn: self.change_color() self.win(color=self.color) else: self.win(color=self.color) def cuicu(self): ''' 催促按钮 ''' if self.my_turn: return if self.is_over: return if not self.is_connected: return else: data = {"msg": "action", "data": "cuicu"} self.tcp_socket.sendall((json.dumps(data) + " END").encode()) # self.label_statuvalue.setText("请求(重新)开始") def logo_move(self): self.chess_pos.show() self.chess_pos.move(self.chess.pos()) self.chess_pos.raise_()
def deal_data(self, data): ''' 对收到的数据进行处理 ''' print(data) if data['msg'] == 'action': if data['data'] == 'restart': result = QMessageBox.information( self, "消息", "对方请求(重新)开始游戏,是否同意?", QMessageBox.Yes | QMessageBox.No) if result == QMessageBox.Yes: data = {"msg": "replay", "data": True, "type": "restart"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) self.restart_func() self.is_over = False if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") else: data = {"msg": "replay", "data": False, "type": "restart"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) self.label_statuvalue.setText("点击开始") if data['data'] == 'lose': QMessageBox.information(self, "消息", "对方认输") if self.my_turn: self.win(color=self.color) # self.change_color() else: self.change_color() self.win(color=self.color) if data['data'] == 'goback': result = QMessageBox.information( self, "消息", "对方请求悔棋,是否同意?", QMessageBox.Yes | QMessageBox.No) if result == QMessageBox.Yes: data = {"msg": "replay", "data": True, "type": "goback"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) self.goback_func() # self.is_over = False if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") else: data = {"msg": "replay", "data": False, "type": "goback"} self.tcp_socket.sendall( (json.dumps(data) + " END").encode()) # self.label_statuvalue.setText("等待开始") if data['data'] == 'cuicu': print(self.is_connected) if not self.is_connected: return if self.is_over: return print("cuicu") sound.play() # pygame.mixer.music.load("source/luozisheng.wav") if data['data'] == 'ready': pass if data['data'] == 'exit': # 对方退出游戏 self.is_connected = False self.is_listening = False self.tcp_socket.close() self.tcp_socket = None print(data) elif data['msg'] == 'position': print(data['data']) # 在对应位置落子 pos = data['data'] if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 self.chess = Chessman(self.color, self) self.chess.move(QPoint(pos[0] * 30 + 50, pos[1] * 30 + 50)) self.chess.show() pygame.mixer.music.play() # 播放声音 self.logo_move() # 移动小标 self.change_color() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return self.my_turn = True self.label_statuvalue.setText("己方回合") elif data['msg'] == 'replay': if data['type'] == 'restart': # 重开回执 if data['data'] == True: self.restart_func() else: QMessageBox.information(self, "消息", "对方拒绝了你的请求") self.label_statuvalue.setText("点击开始") return if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") if data['type'] == 'goback': # 悔棋回执 if data['data'] == True: self.is_over = False self.goback_func() else: QMessageBox.information(self, '消息', '对方拒绝了你的请求') if self.my_turn: self.label_statuvalue.setText("己方回合") else: self.label_statuvalue.setText("对方回合") self.is_over = False elif data['msg'] == 'name': self.setWindowTitle('与 {} 对战中'.format(data['data']))
class SinglePlayer(BasePlayer): ''' 单人游戏窗体 ''' def __init__(self, parent=None): super().__init__(parent) # 清空棋盘 global chessboard chessboard = [[None for i in range(0, 19)] for i in range(0, 19)] self.is_over = False # 标识黑旗白旗 self.color = 'w' # 三个按钮点击触发的函数 self.restart_button.click_signal.connect(self.restart) self.huiqi_button.click_signal.connect(self.goback) self.renshu_button.click_signal.connect(self.lose) self.win_label = None self.chess_pos.hide() # 这个位置标识隐藏起来 def win(self, color): ''' 黑旗胜利或者白棋胜利了 ''' if color == 'b': win_pic = QPixmap('source/黑棋胜利.png') else: win_pic = QPixmap('source/白棋胜利.png') self.win_label = QLabel(parent=self) self.win_label.setPixmap(win_pic) self.win_label.resize(win_pic.size()) self.win_label.move(50, 50) # 显示游戏结束的图片 self.win_label.show() self.is_over = True # 游戏结束 def mouseReleaseEvent(self, a0: QMouseEvent): if self.is_over: # 如果游戏已经结束,点击失效 return # 如果点击在棋盘区域 if a0.x() >= 50 and a0.x() <= 50 + 30 * 18 + 14 and a0.y( ) >= 50 and a0.y() <= 50 + 30 * 18 + 14: # 讲像素坐标转化成棋盘坐标,判断棋盘此位置是否为空 pos = trans_pos(a0) if chessboard[pos[1]][pos[0]] is not None: return # 如果对应位置不为空,说明有棋子,则直接返回 # 不为空,则生成棋子并显示 self.chess = Chessman(self.color, self) self.chess.move(a0.pos()) self.logo_move() self.chess.show() self.change_color() pygame.mixer.music.play() # 在棋盘的对应位置放上棋子 chessboard[pos[1]][pos[0]] = self.chess # 并且在列表中记录坐标 history.append((pos[1], pos[0], self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return None # 如果没有胜利,电脑落子 self.auto_run() def change_color(self): if self.color == 'w': self.color = 'b' else: self.color = 'w' def restart(self): ''' 重新开始游戏 ''' # 清空所有棋子 for j in range(0, 19): for i in range(0, 19): if chessboard[i][j] is not None: chessboard[i][j].close() chessboard[i][j] = None history.clear() # 清空历史数组 if self.is_over: # 如果游戏已经结束 self.win_label.close() self.win_label = None self.is_over = False self.chess_pos.hide() # 这个位置标识隐藏起来 def goback(self): ''' 悔棋按钮 ''' if self.is_over: return None # 如果游戏已经结束了 if len(history) == 0: return None # 没有落子,不能悔棋 chess = history.pop(-1) chessboard[chess[0]][chess[1]].close() chessboard[chess[0]][chess[1]] = None # self.change_color() chess = history.pop(-1) chessboard[chess[0]][chess[1]].close() chessboard[chess[0]][chess[1]] = None # self.change_color() self.chess_pos.hide() # 这个位置标识隐藏起来 def lose(self): ''' 认输按钮 ''' if self.is_over: return None # 如果游戏已经结束了 self.change_color() self.win(self.color) def auto_run(self): ''' 电脑自动执行落子操作 :return: 自动落子 ''' # 找到能下棋的空位置中,假设电脑和人下在此处,得到分数中最大值 score_c = [[0 for i in range(0, 19)] for i in range(0, 19)] score_p = [[0 for i in range(0, 19)] for i in range(0, 19)] # 计算所有的分数 for j in range(0, 19): for i in range(0, 19): if chessboard[i][j] is None: # 如果此处为空 , 计算此处分数,分别记下落黑子和落白子不同的分数 chessboard[i][j] = Chessman('b', parent=self) score_c[i][j] += self.score(i, j, 'b') chessboard[i][j] = Chessman('w', parent=self) score_p[i][j] += self.score(i, j, 'w') chessboard[i][j].close() chessboard[i][j] = None # 为便于计算,将两个二维数组,转换成两个一位数组 r_score_c = [] for item in score_c: r_score_c.extend(item) r_score_p = [] for item in score_p: r_score_p.extend(item) # 最终分数,取两个数组中的最大值合并成一个数组 result = [max(a, b) for a, b in zip(r_score_c, r_score_p)] # 取最大值点的下标 chess_index = result.index(max(result)) # 通过下标计算出位置并落子 x = chess_index // 19 y = chess_index % 19 self.chess = Chessman(self.color, self) self.chess.move(QPoint(y * 30 + 50, x * 30 + 50)) self.chess.show() self.logo_move() self.change_color() pygame.mixer.music.play() chessboard[x][y] = self.chess history.append((x, y, self.chess.color)) # 每次落子后,都判断一下胜负 res = is_win(chessboard) if res: self.win(res) # 通过颜色,显示胜利的图片 return None def score(self, x, y, color): ''' 计分函数 :return:,返回(x,y)坐标点落color颜色的子所得的分数。 可以得到的分数 ''' blank_score = [0, 0, 0, 0] # 四个方向空白点分数 chess_score = [0, 0, 0, 0] # 四个方向同色点分数 # 右方向 for i in range(x, x + 5): if i >= 19: break if chessboard[i][y] is not None: if chessboard[i][y].color == color: # 如果是同色点,同色点分数加一 chess_score[0] += 1 # 朝一个方向执行,每次遇到相同颜色的都加1分 else: break else: # 目标点附近的点为空的,记录空白点数量 blank_score[0] += 1 break # 左方向 for i in range(x - 1, x - 5, -1): if i <= 0: break if chessboard[i][y] is not None: if chessboard[i][y].color == color: chess_score[0] += 1 else: break else: blank_score[0] += 1 break # 下方向 for j in range(y, y + 5): if j >= 19: break if chessboard[x][j] is not None: if chessboard[x][j].color == color: chess_score[1] += 1 else: break else: blank_score[1] += 1 break # 上方向 for j in range(y - 1, y - 5, -1): if j <= 0: break if chessboard[x][j] is not None: if chessboard[x][j].color == color: chess_score[1] += 1 else: break else: blank_score[1] += 1 break # 右下 j = y for i in range(x, x + 5): if i >= 19 or j >= 19: break if chessboard[i][j] is not None: if chessboard[i][j].color == color: chess_score[2] += 1 else: break else: blank_score[2] += 1 break j += 1 # 左上 j = y - 1 for i in range(x - 1, x - 5, -1): if i <= 0 or j <= 0: break if chessboard[i][j] is not None: if chessboard[i][j].color == color: chess_score[2] += 1 else: break else: blank_score[2] += 1 break j -= 1 # 左下 j = y for i in range(x, x - 5, -1): if i <= 0 or j >= 19: break if chessboard[i][j] is not None: if chessboard[i][j].color == color: chess_score[3] += 1 else: break else: blank_score[3] += 1 break j += 1 # 右上 j = y - 1 for i in range(x + 1, x + 5): if i >= 19 or j <= 0: break if chessboard[i][j] is not None: if chessboard[i][j].color == color: chess_score[3] += 1 else: break else: blank_score[3] += 1 break j -= 1 # 计算总分 for score in chess_score: if score > 4: # 如果有某个方向超过4,则在此处落子形成五子连珠 return 100 # 直接返回100分的最高分 for i in range(0, len(blank_score)): if blank_score[i] == 0: # b[]等于零说明在这空白点的附近的空白点的附近同样没有同色棋子,故分数减20 blank_score[i] -= 20 # 结果,将两个列表依次相加。 result = [a + b for a, b in zip(chess_score, blank_score)] # 返回最高分值 return max(result) def logo_move(self): self.chess_pos.show() self.chess_pos.move(self.chess.pos()) self.chess_pos.raise_()