实现了可以同时存在多个房间(每两个人一个房间)
一个玩家断开之后会自动等待
server.py
import socket
from _thread import *
import pickle
from game import Game
server = "192.168.124.19" #
port = 8888 #这里和network的 都需要自己修改
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((server, port)) #绑定两者
except socket.error as e:
str(e)
s.listen(2) #相应套接字排队的最大连接个数
print("服务启动,等待连接")
connected = set()
games = {}
idCount = 0 #id玩家数量
def threaded_client(conn, p, gameId):
global idCount
conn.send(str.encode(str(p)))
reply = ""
while True:
try:
data = conn.recv(4096).decode()
if gameId in games:
game = games[gameId]
if not data:
break
else:
if data == "reset":
game.resetWent()
elif data != "get":
game.play(p, data)
conn.sendall(pickle.dumps(game))
else:
break
except:
break
print("Lost connection")
try:
del games[gameId]
print("Closing Game", gameId)
except:
pass
idCount -= 1
conn.close()
while True:
conn, addr = s.accept()
print("连接到:", addr)
idCount += 1
p = 0
gameId = (idCount - 1)//2
if idCount % 2 == 1:
games[gameId] = Game(gameId)
print("创建一个新游戏...")
else:
games[gameId].ready = True
p = 1
start_new_thread(threaded_client, (conn, p, gameId))
game.py
class Game:
def __init__(self, id):
self.p1Went = False
self.p2Went = False
self.ready = False
self.id = id
self.moves = [None, None]
self.wins = [0,0]
self.ties = 0
def get_player_move(self, p):
"""
:param p: [0,1]
:return: Move
"""
return self.moves[p]
def play(self, player, move):
self.moves[player] = move
if player == 0:
self.p1Went = True
else:
self.p2Went = True
def connected(self):
return self.ready
def bothWent(self):
return self.p1Went and self.p2Went
def winner(self):
p1 = self.moves[0].upper()[0]
p2 = self.moves[1].upper()[0]
winner = -1
if p1 == "R" and p2 == "S":
winner = 0
elif p1 == "S" and p2 == "R":
winner = 1
elif p1 == "P" and p2 == "R":
winner = 0
elif p1 == "R" and p2 == "P":
winner = 1
elif p1 == "S" and p2 == "P":
winner = 0
elif p1 == "P" and p2 == "S":
winner = 1
return winner
def resetWent(self):
self.p1Went = False
self.p2Went = False
client.py
import pygame
from network import Network
import pickle
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, pos):
x1 = pos[0]
y1 = pos[1]
if self.x <= x1 <= self.x + self.width and self.y <= y1 <= self.y + self.height:
return True
else:
return False
def redrawWindow(win, game, p):
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), True)
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.bothWent():
text1 = font.render(move1, 1, (0,0,0))
text2 = font.render(move2, 1, (0, 0, 0))
else:
if game.p1Went and p == 0:
text1 = font.render(move1, 1, (0,0,0))
elif game.p1Went:
text1 = font.render("Locked In", 1, (0, 0, 0))
else:
text1 = font.render("Waiting...", 1, (0, 0, 0))
if game.p2Went and p == 1:
text2 = font.render(move2, 1, (0,0,0))
elif game.p2Went:
text2 = font.render("Locked In", 1, (0, 0, 0))
else:
text2 = font.render("Waiting...", 1, (0, 0, 0))
if p == 1:
win.blit(text2, (100, 350))
win.blit(text1, (400, 350))
else:
win.blit(text1, (100, 350))
win.blit(text2, (400, 350))
for btn in btns:
btn.draw(win)
pygame.display.update()
btns = [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()
player = int(n.getP()) #从network获取
print("You are player", player)
while run:
clock.tick(60)
try:
game = n.send("get")
except:
run = False
print("Couldn't get game")
break
if game.bothWent():
redrawWindow(win, game, player)
pygame.time.delay(500)
try:
game = n.send("reset")
except:
run = False
print("Couldn't get 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:
pos = pygame.mouse.get_pos()
for btn in btns:
if btn.click(pos) and game.connected():
if player == 0:
if not game.p1Went: #给server发送自己的选择
n.send(btn.text)
else:
if not game.p2Went:
n.send(btn.text)
redrawWindow(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, (100,200))
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()
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.124.19"
self.port = 8888
self.addr = (self.server, self.port)
self.p = self.connect()
def getP(self):
return self.p
def connect(self):
try:
self.client.connect(self.addr)
return self.client.recv(2048).decode()
except:
pass
def send(self, data):
try:
self.client.send(str.encode(data))
return pickle.loads(self.client.recv(2048*2))
except socket.error as e:
print(e)
|