TypeError:int()参数必须是字符串、类似字节的对象或数字,而不是“石头、布、剪刀”游戏客户端文件中的“非类型”

2024-04-24 20:00:09 发布

您现在位置:Python中文网/ 问答频道 /正文

上面的代码是一个简单的“石头,布,剪刀”游戏

我刚刚完成了this视频中的最后一个教程。我已经测试了代码,当我在同一台笔记本电脑上打开服务器和客户端时,它工作正常,但正如教程中的那个家伙所说,它应该能够在其他计算机上运行,我尝试在我姐姐的笔记本电脑上打开一个客户端,服务器在我的笔记本电脑上运行。 它不起作用,我得到的错误是:“TypeError:int()参数必须是字符串、类似于对象的字节或数字,而不是‘NoneType’”

另外,视频的开头解释了游戏应该如何工作。而且大多数注释都不重要,我写它们只是为了记录代码(以后可能记不起来的事情)

下面是错误的屏幕截图: Error

client.py文件:

import pygame
from network import Network
pygame.font.init()

width = 700
height = 700
win = pygame.display.set_mode((width, height))
pygame.display.set_caption('Client')

class Button:
    def __init__(self, text, x, y, color):
        self.text = text
        self.x = x
        self.y = y 
        self.color = color
        self.width = 150
        self.height = 100
    
    def draw(self, win):
        pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height))
        font = pygame.font.SysFont('comicsans', 40)
        text = font.render(self.text, 1, (255,255,255))
        win.blit(text, (self.x + round(self.width/2) - round(text.get_width()/2), self.y + round(self.height/2) - round(text.get_height()/2) ))

    def click(self, clicked_position):
        x1 = clicked_position[0]
        y1 = clicked_position[1]

        if self.x <= x1 <= self.x + self.width and self.y <= y1 <= self.y +self.height:
            return True
        else:
            return False

def redraw_window(win, game, player):
    win.fill((128,128,128))
    
    if not(game.connected()):
        font = pygame.font.SysFont('comicsans', 80)
        text = font.render('Waiting for Player...', 1, (255,0,0))
        win.blit(text, (width/2 - text.get_width()/2, height/2 - text.get_height()/2))
    else:
        font = pygame.font.SysFont('comicsans', 60)
        text = font.render('Your move', 1, (0,255,255))
        win.blit(text, (80,200))

        text = font.render('Opponents', 1, (0,255,255))
        win.blit(text, (380,200))

        move1 = game.get_player_move(0)
        move2 = game.get_player_move(1)

        if game.both_players_moved():
            text1 = font.render(move1, 1, (0,0,0))
            text2 = font.render(move2, 1, (0,0,0))
        else:
            if game.player1_moved and player == 0:
                text1 = font.render(move1, 1, (0,0,0))
            elif game.player1_moved:
                text1 = font.render('Locked in', 1, (0,0,0))
            else:
                text1 = font.render('Waiting...', 1, (0,0,0))
            
            if game.player2_moved and player == 0:
                text2 = font.render(move2, 1, (0,0,0))
            elif game.player2_moved:
                text2 = font.render('Locked in', 1, (0,0,0))
            else:
                text2 = font.render('Waiting...', 1, (0,0,0))
        
        if player == 1:
            win.blit(text2, (100,350))
            win.blit(text1, (400,350))
        else:
            win.blit(text1, (100,350))
            win.blit(text2, (400,350))

        for button in buttons:
            button.draw(win)
    pygame.display.update()

buttons = [Button('Rock', 50, 500, (0,0,0)), Button('Scissors', 250, 500, (255,0,0)), Button('Paper', 450, 500, (0,255,0))]
def main():
    run = True
    clock = pygame.time.Clock()
    n = Network() # Use the Network() class to connect to the server
    player = int(n.get_player())
    print('You are player', player)

    while run:
        clock.tick(60)
        try:
            game = n.send('get')
            # If this doesn't work it'll be because one of the clients have already exited and the game was deleted
        except:
            run = False
            print('Coudn\'t get the game')
            break

        if game.both_players_moved():
            redraw_window(win, game, player)
            pygame.time.delay(1000)
            try:
                game = n.send('reset')
            except:
                run = False
                print('Coudn\'t get the game')
                break
            
            font = pygame.font.SysFont('comicsans', 90)
            if (game.winner() == 1 and player == 1) or (game.winner() == 0 and player == 0):
                text = font.render('You Won!', 1, (255,0,0))
            elif game.winner() == -1:
                text = font.render('Tie Game!', 1, (255,0,0))
            else:
                text = font.render('You Lost!', 1, (255,0,0))
            
            win.blit(text, (width/2 - text.get_width()/2, height/2 - text.get_height()/2))
            pygame.display.update()
            pygame.time.delay(2000)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()

            if event.type == pygame.MOUSEBUTTONDOWN:
                position = pygame.mouse.get_pos()
                for button in buttons:
                    if button.click(position) and game.connected():
                        if player == 0:
                            if not game.player1_moved:
                                n.send(button.text)
                        else:
                            if not game.player2_moved:
                                n.send(button.text)
        redraw_window(win, game, player)

def menu_screen():
    run = True
    clock = pygame.time.Clock()
    
    while run:
        clock.tick(60)
        win.fill((128,128,128))
        font = pygame.font.SysFont('comicsans', 60)
        text = font.render('Click to Play!', 1, (255,0,0))
        win.blit(text, (width/2 - text.get_width()/2, height/2 - text.get_height()/2))
        pygame.display.update()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                run = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                run = False
    
    main()
            
while True:
    menu_screen()

server.py文件:

import socket
from _thread import *
import pickle
from game import Game

server = '192.168.100.5' # The server.py script has to be runing on this machine
port = 5555

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind((server, port))
except socket.error as e:
    print(e)

s.listen(2) # This listen for two clint connections
print('Waiting for a connection, Server Started')

games = {}
id_count = 0

def threaded_client(connection, player, game_id): 
    # Each client has one version of this function running in the background at the same time
    global id_count
    connection.send(str.encode(str(player)))

    reply = ''
    while True: # It runs once for every frame
        try:
            data = connection.recv(4096).decode() # it Receives string from the client

            if game_id in games: 
                # This checks if the game still exists, because if the client disconnects from the game we'll delete it
                game = games[game_id]

                if not data:
                    break
                else:
                    if data == 'reset':
                        game.reset_moves()
                    elif data != 'get':
                        game.play(player, data)
                    
                    connection.sendall(pickle.dumps(game))
            else:
                break
        except:
            break
    print('Lost connection')
    try:
        del games[game_id]
        print('Closing game:', game_id)
    except:
        pass
    id_count -= 1 # One client was closed
    connection.close()

while True: # This runs once for every connection made
    connection, address = s.accept() # connection -> new socket object; address -> address of the sockect from the other device
    print('Connected to: ', address)

    id_count += 1
    player = 0
    game_id = (id_count - 1) // 2 # This will make a single game id for every two people that connect to the server
    if id_count % 2 == 1: 
        # if the result is 0, it means that there are even clients playing the game, but if it is 1,
        # it means that there are odd clients playing the game
        games[game_id] = Game(game_id) # It creates a new game when there are odd clients
        print('Creating a new game...')
    else:
        games[game_id].ready = True
        player = 1

    # start_new_thread(function, arguments)
    start_new_thread(threaded_client, (connection, player, game_id))

network.py文件:

import socket
import pickle

class Network:
    def __init__(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server = '192.168.100.5'
        self.port = 5555
        self.address = (self.server, self.port)
        self.player = self.connect()
    
    def get_player(self):
        return self.player
    
    def connect(self):
        try:
            self.client.connect(self.address) # It connects to the server
            return self.client.recv(2048).decode() # It receives a string which is 0 or 1
        except:
            pass
    
    def send(self, data):
        try:
            self.client.send(str.encode(data)) # It sends a string to the server
            return pickle.loads(self.client.recv(2048*2)) # It receives a object from the server
        except socket.error as e:
            print(e)

game.py文件:

class Game:
    def __init__(self, id):
        self.player1_moved = False
        self.player2_moved = False
        self.ready = False # When True there are two people connected to the same game
        self.id = id # This determines which client plays with which
        self.moves = [None, None] # Rock, paper or scissors
        self.wins = [0,0]
        self.ties = 0

    def get_player_move(self, p):
        # p is 0 or 1 and this function will return the move made by the other player
        return self.moves[p]
    
    def play(self, player, move):
        # Update moves and check which player has already played
        self.moves[player] = move
        if player == 0:
            self.player1_moved = True
        else:
            self.player2_moved = True
    
    def connected(self): # Check if the two player are conected to the game
        return self.ready

    def both_players_moved(self):
        return self.player1_moved and self.player2_moved
    
    def winner(self):
        player1 = self.moves[0].upper()[0] # Get the firt letter of the player move
        player2 = self.moves[1].upper()[0]

        winner = -1
        # Player one wins -> winner = 0
        # Player two wins -> winner = 1
        # Tie = -1

        if player1 == 'R' and player2 == 'S':
            winner = 0
        elif player1 == 'S' and player2 == 'R':
            winner = 1
        elif player1 == 'P' and player2 == 'R':
            winner = 0
        elif player1 == 'R' and player2 == 'P':
            winner = 1
        elif player1 == 'S' and player2 == 'P':
            winner = 0
        elif player1 == 'P' and player2 == 'S':
            winner = 1
        
        return winner
    
    def reset_moves(self):
        self.player1_moved = False
        self.player2_moved = False

Tags: andthetextselfidgamegetif
2条回答

这也许不是解决这个问题的直接办法,但我希望它能在某种程度上有所帮助

首先,我在Windows10(Python3.9.4,PyGame2.0.1)和Ubuntu18.04(Python3.6,PyGame2.0.1)上运行了你们的代码,服务器是在Linux上运行的,运行得很好。因此,我同意存在网络问题,最有可能是防火墙。这里需要注意的是,尽管在我的例子中它与不同版本的python一起工作,但请确保所有包以及python在两台计算机上都是相同的。尝试更改服务器计算机(不要忘记更改server.pynetwork.py中的IP),尝试仅在一台计算机上运行服务器,在另一台计算机上运行两个客户端。正如其他答案所建议的,检查端口,也许这是您应该做的第一件事

关于您收到的错误。您正试图将值强制转换为int,因为您收到了None,您将收到此错误。您正在调用n.get_player(),它在__init__方法中返回self.playerself.player = self.connect()。现在connect方法处于try-except块中。因此,在返回connect之前,请在返回self.client.recv(2048).decode()之前进行一些打印以查看其值。也可以代替pass中的除外。放置类似这样的内容,以捕获异常,该异常将告诉您有关您的问题的更多信息(假设它在这里,我认为它在这里,并且它与服务器连接,不返回播放器编号):

except Exception as e:
    print(e)

在你通过的每个地方都这样做,直到你找到它的底部

我还想指出,我知道您正在从教程中学习,但我不建议使用_thread,而是threading。看看accepted answer和文档here这也很不错tutorial关于threading,我知道它可能太长了,但我从中学到了很多。在快速查看您的代码之后,我认为没有必要将2放入socket.listen(2),更多的here

正如我在开始时所说的,这可能无法解决您面临的问题,但我希望您能从中受益

允许通过防火墙连接服务器计算机上的端口5555

相关问题 更多 >