上面的代码是一个简单的“石头,布,剪刀”游戏
我刚刚完成了this视频中的最后一个教程。我已经测试了代码,当我在同一台笔记本电脑上打开服务器和客户端时,它工作正常,但正如教程中的那个家伙所说,它应该能够在其他计算机上运行,我尝试在我姐姐的笔记本电脑上打开一个客户端,服务器在我的笔记本电脑上运行。 它不起作用,我得到的错误是:“TypeError:int()参数必须是字符串、类似于对象的字节或数字,而不是‘NoneType’”
另外,视频的开头解释了游戏应该如何工作。而且大多数注释都不重要,我写它们只是为了记录代码(以后可能记不起来的事情)
下面是错误的屏幕截图: Error
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()
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))
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)
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
这也许不是解决这个问题的直接办法,但我希望它能在某种程度上有所帮助
首先,我在Windows10(Python3.9.4,PyGame2.0.1)和Ubuntu18.04(Python3.6,PyGame2.0.1)上运行了你们的代码,服务器是在Linux上运行的,运行得很好。因此,我同意存在网络问题,最有可能是防火墙。这里需要注意的是,尽管在我的例子中它与不同版本的python一起工作,但请确保所有包以及python在两台计算机上都是相同的。尝试更改服务器计算机(不要忘记更改
server.py
和network.py
中的IP),尝试仅在一台计算机上运行服务器,在另一台计算机上运行两个客户端。正如其他答案所建议的,检查端口,也许这是您应该做的第一件事关于您收到的错误。您正试图将值强制转换为
int
,因为您收到了None
,您将收到此错误。您正在调用n.get_player()
,它在__init__
方法中返回self.player
和self.player = self.connect()
。现在connect
方法处于try-except块中。因此,在返回connect
之前,请在返回self.client.recv(2048).decode()
之前进行一些打印以查看其值。也可以代替pass
中的除外。放置类似这样的内容,以捕获异常,该异常将告诉您有关您的问题的更多信息(假设它在这里,我认为它在这里,并且它与服务器连接,不返回播放器编号):在你通过的每个地方都这样做,直到你找到它的底部
我还想指出,我知道您正在从教程中学习,但我不建议使用
_thread
,而是threading
。看看accepted answer和文档here这也很不错tutorial关于threading
,我知道它可能太长了,但我从中学到了很多。在快速查看您的代码之后,我认为没有必要将2
放入socket.listen(2)
,更多的here正如我在开始时所说的,这可能无法解决您面临的问题,但我希望您能从中受益
允许通过防火墙连接服务器计算机上的端口5555
相关问题 更多 >
编程相关推荐