Example #1
0
    def __init__(self, name, sock, parent=None):
        super().__init__(parent)
        self.name = name  # 对方的昵称
        self.setWindowTitle('与 {} 对战中'.format(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.keep_connect = True
        # 三个按钮点击触发的函数
        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 = True  # 默认情况下有连接
        self.is_listening = True  # 默认情况下启动了监听
        self.tcp_socket = sock
        self.label_statuvalue.setText("连接成功,\n点击开始")
        threading.Thread(target=self.recv_data,
                         args=(self.tcp_socket, '')).start()

        self.dataSignal.connect(self.deal_data)
        self.disconnectSignal.connect(self.dis_connect)
Example #2
0
    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)
Example #3
0
    def initUI(self):
        self.setFixedSize(760, 650)  # 设置固定大小
        self.move(200, 10)
        self.setWindowTitle('五子棋-三级狗')
        self.setWindowIcon(QIcon('source/icon.ico'))
        # 设置背景图片
        palette1 = QPalette()
        palette1.setBrush(self.backgroundRole(),
                          QBrush(QPixmap('source/游戏界面.png')))  # 设置背景图片
        self.setPalette(palette1)

        self.back_button = TDPushButton(self,
                                        'source/返回按钮_normal.png',
                                        'source/返回按钮_hover.png',
                                        'source/返回按钮_press.png',
                                        parent=self)
        self.back_button.click_signal.connect(self.back)
        self.back_button.move(680, 10)
        self.restart_button = TDPushButton(self,
                                           'source/开始按钮_normal.png',
                                           'source/开始按钮_hover.png',
                                           'source/开始按钮_press.png',
                                           parent=self)
        self.restart_button.move(640, 240)
        self.huiqi_button = TDPushButton(self,
                                         'source/悔棋按钮_normal.png',
                                         'source/悔棋按钮_hover.png',
                                         'source/悔棋按钮_press.png',
                                         parent=self)
        self.huiqi_button.move(640, 310)
        self.renshu_button = TDPushButton(self,
                                          'source/认输按钮_normal.png',
                                          'source/认输按钮_hover.png',
                                          'source/认输按钮_press.png',
                                          parent=self)
        self.renshu_button.move(640, 380)

        # 落棋标志
        self.chess_pos = QLabel(self)
        pic = QPixmap("source/标识.png")
        self.chess_pos.setPixmap(pic)
        self.chess_pos.setFixedSize(pic.size())
        self.chess_pos.show()
Example #4
0
 def initUI(self):
     self.setFixedSize(760, 650)# 设置固定大小
     self.move(200, 10)
     self.setWindowTitle('五子棋-三级狗')
     self.setWindowIcon(QIcon('source/icon.ico'))
     # 设置背景图片
     palette1 = QPalette()
     palette1.setBrush(self.backgroundRole(), QBrush(QPixmap('source/五子棋界面.png')))   # 设置背景图片
     self.setPalette(palette1)
     # 加载选择按钮
     self.single_button = TDPushButton(self,'source/人机对战_normal.png','source/人机对战_hover.png','source/人机对战_press.png',parent=self)
     self.single_button.move(250,300)
     self.single_button.show()
     self.single_button.click_signal.connect(self.single_player) # 连接信号和槽,点击按钮触发函数
     self.double_button = TDPushButton(self,'source/双人对战_normal.png','source/双人对战_hover.png','source/双人对战_press.png',parent=self)
     self.double_button.move(250,400)
     self.double_button.show()
     self.double_button.click_signal.connect(self.double_player)
     self.network_button = TDPushButton(self,'source/联机对战_normal.png','source/联机对战_hover.png','source/联机对战_press.png',parent=self)
     self.network_button.move(250,500)
     self.network_button.show()
     self.network_button.click_signal.connect(self.network_player)
     self.game_window = None
Example #5
0
class MainWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.initUI()  # 初始化界面

    def initUI(self):
        self.setFixedSize(760, 650)  # 设置固定大小
        self.move(200, 10)
        self.setWindowTitle('五子棋-三级狗')
        self.setWindowIcon(QIcon('source/icon.ico'))
        # 设置背景图片
        palette1 = QPalette()
        palette1.setBrush(self.backgroundRole(),
                          QBrush(QPixmap('source/五子棋界面.png')))  # 设置背景图片
        self.setPalette(palette1)
        # 加载选择按钮
        self.single_button = TDPushButton(self,
                                          'source/人机对战_normal.png',
                                          'source/人机对战_hover.png',
                                          'source/人机对战_press.png',
                                          parent=self)
        self.single_button.move(250, 300)
        self.single_button.show()
        self.single_button.click_signal.connect(
            self.single_player)  # 连接信号和槽,点击按钮触发函数
        self.double_button = TDPushButton(self,
                                          'source/双人对战_normal.png',
                                          'source/双人对战_hover.png',
                                          'source/双人对战_press.png',
                                          parent=self)
        self.double_button.move(250, 400)
        self.double_button.show()
        self.double_button.click_signal.connect(self.double_player)
        self.network_button = TDPushButton(self,
                                           'source/联机对战_normal.png',
                                           'source/联机对战_hover.png',
                                           'source/联机对战_press.png',
                                           parent=self)
        self.network_button.move(250, 500)
        self.network_button.show()
        self.network_button.click_signal.connect(self.network_player)
        self.game_window = None

    def single_player(self):
        self.close()
        self.game_window = SinglePlayer()
        self.game_window.exitSignal.connect(self.game_over)  # 游戏结束
        self.game_window.backSignal.connect(self.show)  # 游戏
        self.game_window.show()

    def double_player(self):
        self.close()
        self.game_window = DoublePlayer()
        self.game_window.exitSignal.connect(self.game_over)  # 游戏结束
        self.game_window.backSignal.connect(self.show)  # 游戏
        self.game_window.show()

    def network_player(self):
        self.close()
        self.game_window = NetworkConfig(main_window=self)
        self.game_window.show()

    def game_over(self):
        sys.exit(app.exec_())
Example #6
0
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_()
Example #7
0
class BasePlayer(QWidget):
    '''
    游戏对战窗体的基类,单人游戏,双人游戏和网络对战都是继承自这个类,这个类中实现并加载了了所有公共的控件
    '''
    backSignal = pyqtSignal()  # 点击后退按钮触发的信号
    exitSignal = pyqtSignal()  # 如果程序退出,触发的信号

    def __init__(self, parent=None):
        super().__init__(parent)
        self.initUI()
        self.is_exit = True

    def initUI(self):
        self.setFixedSize(760, 650)  # 设置固定大小
        self.move(200, 10)
        self.setWindowTitle('五子棋-三级狗')
        self.setWindowIcon(QIcon('source/icon.ico'))
        # 设置背景图片
        palette1 = QPalette()
        palette1.setBrush(self.backgroundRole(),
                          QBrush(QPixmap('source/游戏界面.png')))  # 设置背景图片
        self.setPalette(palette1)

        self.back_button = TDPushButton(self,
                                        'source/返回按钮_normal.png',
                                        'source/返回按钮_hover.png',
                                        'source/返回按钮_press.png',
                                        parent=self)
        self.back_button.click_signal.connect(self.back)
        self.back_button.move(680, 10)
        self.restart_button = TDPushButton(self,
                                           'source/开始按钮_normal.png',
                                           'source/开始按钮_hover.png',
                                           'source/开始按钮_press.png',
                                           parent=self)
        self.restart_button.move(640, 240)
        self.huiqi_button = TDPushButton(self,
                                         'source/悔棋按钮_normal.png',
                                         'source/悔棋按钮_hover.png',
                                         'source/悔棋按钮_press.png',
                                         parent=self)
        self.huiqi_button.move(640, 310)
        self.renshu_button = TDPushButton(self,
                                          'source/认输按钮_normal.png',
                                          'source/认输按钮_hover.png',
                                          'source/认输按钮_press.png',
                                          parent=self)
        self.renshu_button.move(640, 380)

        # 落棋标志
        self.chess_pos = QLabel(self)
        pic = QPixmap("source/标识.png")
        self.chess_pos.setPixmap(pic)
        self.chess_pos.setFixedSize(pic.size())
        self.chess_pos.show()

    def closeEvent(self, a0: QCloseEvent):
        if self.is_exit:  # 默认情况下,关闭窗体,退出游戏。如果点击返回按钮,则is_exit被设置为False,不触发此信号。
            self.exitSignal.emit()
        else:
            self.backSignal.emit()

    def back(self):
        self.is_exit = False
        self.close()

    def logo_move(self):
        pass