0

我是编程新手,我的程序有一些问题。希望有人可以帮助我

我正在尝试使用 socket 和 pyqt5 在 Python 上创建一个石头剪刀布游戏。当我在不使用 pyqt5 的情况下运行它时,我的程序可以正常工作,但是在尝试实现它之后我被卡住了。希望有人能解释我的错误。

在窗口中,我应该输入“石头”或“纸”或“剪刀”。然后它应该被发送到服务器,服务器应该随机生成上述选项之一并检查谁获胜。在它将结果发送回客户端(我的窗口)之后。此外,每次我发送数据时,它都应该在窗口中保持分数。

这是我的 server.py

import socket
import pickle
import random

s=socket.socket()
ip_host=socket.gethostname()
port=3030
s.bind((ip_host, port))
s.listen(5)

c,addr = s.accept()

choices=["rock", "paper", "scissors"]
tie=0
win=0
lose=0

while win!=3 or lose!=3:
    player=pickle.loads(c.recv(1024))
    num=random.randint(0,2)
    cpu=choices[num]
    if player==cpu:
        print("Tie")
        tie+=1
        c.send(pickle.dumps('tie'))
    else:
        if (player=='rock' and cpu=='paper') or (player=='paper' and cpu=='scissors') or (player=='scissors' and cpu=='rock'):
            print("You lose")
            lose+=1
            c.send(pickle.dumps("lose"))
        else:
            print("You win")
            win+=1
            c.send(pickle.dumps("win"))

c.close()
s.close()

这是我的client.py

import socket
import pickle
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys

s=socket.socket()
server_host=socket.gethostname()
server_port=3030
s.connect((server_host, server_port))
print("Connected to some server")

class grid_pro(QWidget):
    """grid example"""
    def __init__(self):
        super().__init__()
        self.setGeometry(200,200,200,200)
        self.setWindowTitle("Rock-Paper-Scissors")
        self.label=QLabel("Enter rock, paper or scissors:")
        self.input=QLineEdit()
        self.guess=QPushButton("Guess")
        self.win=QLabel('You: 0')
        self.lose=QLabel("CPU: 0")
        self.result=QLabel("Start")

        self.grid=QGridLayout(self)
        self.grid.addWidget(self.label, 0, 0)
        self.grid.addWidget(self.input, 0, 1)
        self.grid.addWidget(self.guess, 1, 0)
        self.grid.addWidget(self.result, 1, 1)
        self.grid.addWidget(self.win, 2, 0)
        self.grid.addWidget(self.lose, 2, 1)
        self.guess.clicked.connect(self.client)
        self.client()
        self.show()

    def client(self):
        win=0
        lose=0
        tie=0
        while 1:
            self.win.setText('You: %d'%(win))
            self.lose.setText('CPU: %d'%(lose))
            n=str(self.input.text())
            s.send(pickle.dumps(n))
            result=pickle.loads(s.recv(1024))
            if result=='win':
                print("You win")
                win+=1
            elif result=='lose':
                lose+=1
                print("You lose")
            elif result=='tie':
                tie+=1
                print("Tie")
            if win==3 or lose==3:
                break

        self.result.setText("You "+result+'!!')


app=QApplication(sys.argv)
form=grid_pro()
sys.exit(app.exec_())
4

1 回答 1

0

client如果使用 UI,为什么要在插槽中使用无限循环?这在您的应用程序从控制台运行时最需要,因此您需要每次都提示用户输入一些新值。当使用不需要的 UI 时,因为已经有一个无限循环正在为您重绘 UI:

import socket
import pickle
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys

s=socket.socket()
server_host=socket.gethostname()
server_port=3030
s.connect((server_host, server_port))
print("Connected to some server")

class grid_pro(QWidget):
    """grid example"""
    def __init__(self):
        super().__init__()
        self.setGeometry(200, 200, 200, 200)
        self.setWindowTitle("Rock-Paper-Scissors")
        self.label = QLabel("Enter rock, paper or scissors:")
        self.input = QLineEdit()
        self.guess = QPushButton("Guess")
        self.win = QLabel('You: 0')
        self.lose = QLabel("CPU: 0")
        self.result = QLabel("Start")

        self.grid=QGridLayout(self)
        self.grid.addWidget(self.label, 0, 0)
        self.grid.addWidget(self.input, 0, 1)
        self.grid.addWidget(self.guess, 1, 0)
        self.grid.addWidget(self.result, 1, 1)
        self.grid.addWidget(self.win, 2, 0)
        self.grid.addWidget(self.lose, 2, 1)
        self.guess.clicked.connect(self.client)
        self.client()
        self.show()

    @pyqtSlot()
    def client(self):
        win = 0
        lose = 0
        tie = 0
        self.win.setText('You: %d' % (win))
        self.lose.setText('CPU: %d' % (lose))
        n = str(self.input.text())
        s.send(pickle.dumps(n))
        result = pickle.loads(s.recv(1024))

        if result=='win':
            print("You win")
            win += 1
        elif result=='lose':
            lose += 1
            print("You lose")
        elif result=='tie':
            tie += 1
            print("Tie")

        self.result.setText("You %s!!" % result)


app = QApplication(sys.argv)
form = grid_pro()
sys.exit(app.exec_())

请注意,我将@pyqtSlot()装饰器添加到client插槽中,因此您需要从中导入它PyQt5.QtCore(使用此装饰器专门装饰信号插槽是一种很好的做法,即使它可以与普通的 python 可调用对象一起使用)。

此外,您应该修改代码以正确终止客户端-服务器连接。据我通过阅读您的代码了解,每场比赛最多持续5轮(第一个获得3胜的人),然后您关闭连接(因此要玩另一场比赛,您需要重新启动服务器)。我会在匹配结束而不关闭连接时重置分数,并在客户端中实现另一个插槽,该插槽可以由 a 触发QPushButton,它将'QUIT'字符串(或您喜欢的任何其他内容)发送到服务器,读取此类字符串时将终止连接(并且客户端将相应地跟进,因为他知道游戏正在终止,因为他发送了'QUIT'细绳)。现在,当匹配结束时,服务器关闭连接,客户端上会出现套接字错误。

于 2016-03-17T10:50:57.053 回答