#跳棋服务器.py
import socket
import sqlite3
import threading
client_sockets = []
client_sockets_lock = threading.Lock() # 锁,用于线程安全的操作client_sockets
# 初始创建数据库表(只需要执行一次)
def init_db():
conn = sqlite3.connect('equipment.db')
cursor = conn.cursor()
try:
cursor.execute('CREATE TABLE IF NOT EXISTS user (id VARCHAR(20) PRIMARY KEY, password VARCHAR(20))')
conn.commit()
except Exception as e:
print(e)
finally:
conn.close()
cnt=0
def handle_client(client_socket, client_address):
# 在每个线程中创建独立的数据库连接和游标
conn = sqlite3.connect('equipment.db')
cursor = conn.cursor()
global cnt
try:
print(f"处理来自 {client_address} 的连接")
while True:
try:
message = client_socket.recv(1024).decode()
if not message:
break
print(f"收到来自 {client_address} 的消息: {message}")
if message.startswith("register:"):
_, username, password = message.split(':')
cursor.execute('SELECT * FROM user WHERE id=?', (username,))
if cursor.fetchone():
response = "用户已存在"
else:
cursor.execute('INSERT INTO user (id, password) VALUES (?, ?)', (username, password))
conn.commit()
response = "注册成功"
client_socket.sendall(response.encode())
elif message.startswith("user:"):
_, username, password = message.split(':')
cursor.execute('SELECT * FROM user WHERE id=? AND password=?', (username, password))
user = cursor.fetchone()
if user:
response = "登录成功:" + str(len(client_sockets))
else:
response = "登录失败"
client_socket.sendall(response.encode())
elif message == "quit":
break
else:
cnt += 1
print(cnt)
cnt %= len(client_sockets)
response = eval(message)
response.append(cnt+1)
print(response)
response=str(response)
with client_sockets_lock:
for i in client_sockets:
# if i != client_socket: # 不要把消息发回给发送者
try:
i.sendall(response.encode())
print(response)
except OSError:
print("发送消息时出错,可能是套接字已关闭")
except ConnectionResetError:
print(f"与 {client_address} 的连接被远程主机重置")
break
finally:
with client_sockets_lock:
client_sockets.remove(client_socket)
client_socket.close()
conn.close()
print(f"与 {client_address} 的连接已关闭")
def start_server():
init_db() # 初始化数据库
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('10.171.131.51', 8888))
server_socket.listen(5)
print("服务器启动,等待连接...")
while True:
client_socket, client_address = server_socket.accept()
with client_sockets_lock:
client_sockets.append(client_socket)
print(f"连接来自 {client_address}")
client_handler = threading.Thread(target=handle_client, args=(client_socket, client_address))
client_handler.start()
if __name__ == "__main__":
start_server()
#CheckerPiece
import math
import pygame
class CheckerPiece:
def __init__(self, center, color):
self.center = center # 棋子的中心位置
self.color = [color, (0, 0, 0)] # 棋子的颜色
self.radius = 5 # 棋子的半径
self.clicked = False # 标记棋子是否被点击了
self.index = 0
def draw(self, screen):
# 绘制棋子
pygame.draw.circle(screen, (0, 0, 0), self.center, self.radius + 2) # 绘制黑色的边框
pygame.draw.circle(screen, self.color[self.index], self.center, self.radius) # 绘制棋子
def is_clicked(self, pos):
# 判断点击位置是否在棋子范围内
distance = math.sqrt((pos[0] - self.center[0]) ** 2 + (pos[1] - self.center[1]) ** 2)
return distance < self.radius
def handle_click(self):
# 处理点击事件
self.clicked = True
#CheckersBoard.py
import socket
import threading
import time
import pygame
import sys
import math
from CheckerPiece import CheckerPiece
class CheckersBoard:
def __init__(self):
pygame.init()
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_address = ('192.168.1.137', 8888)
self.client_socket.connect(self.server_address)
# 启动接收消息的线程
self.receive_thread = threading.Thread(target=self.receive_messages)
self.receive_thread.start()
self.winner=-1
self.is_clicked = -1
self.BOARDSIZE = 600
self.CEN = self.BOARDSIZE / 2
self.EDGE = 30
self.RADIUS = self.CEN - self.EDGE
self.RATIO = 0.87
self.HEIGHT = self.RADIUS / 2
self.SIDE = self.HEIGHT / self.RATIO
self.EACHHEIGHT = self.RADIUS / 8
self.EACHWIDTH = self.SIDE / 8
self.RA = 5
self.gamestate=False
self.WHITE = (255, 255, 255)
self.BLACK = (0, 0, 0)
self.YELLOW = (255, 255, 0)
self.GREEN = (0, 255, 0)
self.BLUE = (0, 0, 255)
self.RED = (255, 0, 0)
self.COLOR=[self.RED,self.GREEN,self.BLUE]
self.id=""
self.password=""
self.playerid=0
self.playernow=1
self.POS1 = [
(12, 0), (11, 1), (13, 1), (10, 2), (12, 2), (14, 2), (9, 3), (11, 3),
(13, 3), (15, 3)
]
self.POS2 = [
(3, 7), (2, 6), (4, 6), (1, 5), (3, 5), (5, 5), (0, 4), (2, 4),
(4, 4), (6, 4)
]
self.POS3 = [
(21, 7), (20, 6), (22, 6), (19, 5), (21, 5), (23, 5), (18, 4), (20, 4),
(22, 4), (24, 4)
]
self.victoy = [[(20,8),(19,9),(21,9),(18,10),(20,10),(22,10),(17,11),(19,11),(21,11),(23,11),(16,12),(18,12),(20,12),(22,12),(24,12)],
[(8,12),(10,12),(12,12),(14,12),(16,12),(9,13),(11,13),(13,13),(15,13),(10,14),(12,14),(14,14),(11,15),(13,15),(12,16)],
[(4,8),(3,9),(5,9),(2,10),(4,10),(6,10),(1,11),(3,11),(5,11),(7,11),(0,12),(2,12),(4,12),(6,12),(8,12)]]
self.POS4 = self.POS1 + self.POS2 + self.POS3 + [(x, y) for y in range(4, 13) for x in
range(8 - y + 4, 16 + y - 4 + 2, 2)] + [(x, y) for y in
range(13, 18) for x in
range(8 + y - 12,
16 - y + 13, 2)]
# self.screen = pygame.display.set_mode((self.BOARDSIZE, self.BOARDSIZE))
pygame.display.set_caption('Checkers Board')
self.pieces = []
for row, col in self.POS1:
center_xy = self.rcToXy((row, col))
self.pieces.append(CheckerPiece(center_xy, self.GREEN))
for row, col in self.POS2:
center_xy = self.rcToXy((row, col))
self.pieces.append(CheckerPiece(center_xy, self.RED))
for row, col in self.POS3:
center_xy = self.rcToXy((row, col))
self.pieces.append(CheckerPiece(center_xy, self.BLUE))
# 字体初始化
font_name = pygame.font.get_fonts()[0]
self.font = pygame.font.SysFont(font_name, 18)
# 定义状态
self.state = "INITIAL"
def is_clicked_empty(self, pos, center):
center = self.rcToXy((center[0], center[1]))
for i in self.pieces:
if center == i.center:
return False
distance = math.sqrt((pos[0] - center[0]) ** 2 + (pos[1] - center[1]) ** 2)
return distance < 5
def rcToXy(self, rc):
xy = [0, 0]
xy[0] = (rc[0] - 12) * self.EACHWIDTH + self.CEN
xy[1] = rc[1] * self.EACHHEIGHT + self.EDGE
return xy
def drawLine(self, start_rc, end_rc):
start_xy = self.rcToXy(start_rc)
end_xy = self.rcToXy(end_rc)
pygame.draw.aaline(self.screen, self.BLACK, start_xy, end_xy, 1)
def drawBoard(self):
self.screen.fill(self.WHITE)
tan = [
[(self.CEN - self.SIDE / 2, self.EDGE + self.HEIGHT), (self.CEN + self.SIDE / 2, self.EDGE + self.HEIGHT),
(self.CEN + self.SIDE, self.CEN),
(self.CEN + self.SIDE / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT),
(self.CEN - self.SIDE / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT), (self.CEN - self.SIDE, self.CEN)],
[(self.CEN, self.EDGE), (self.CEN - self.SIDE / 2, self.EDGE + self.HEIGHT),
(self.CEN + self.SIDE / 2, self.EDGE + self.HEIGHT)],
[(self.CEN + self.SIDE * 3 / 2, self.EDGE + self.HEIGHT),
(self.CEN + self.SIDE / 2, self.EDGE + self.HEIGHT), (self.CEN + self.SIDE, self.CEN)],
[(self.CEN + self.SIDE * 3 / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT), (self.CEN + self.SIDE, self.CEN),
(self.CEN + self.SIDE / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT)],
[(self.CEN, self.BOARDSIZE - self.EDGE),
(self.CEN + self.SIDE / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT),
(self.CEN - self.SIDE / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT)],
[(self.CEN - self.SIDE * 3 / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT),
(self.CEN - self.SIDE / 2, self.BOARDSIZE - self.EDGE - self.HEIGHT), (self.CEN - self.SIDE, self.CEN)],
[(self.CEN - self.SIDE * 3 / 2, self.EDGE + self.HEIGHT), (self.CEN - self.SIDE, self.CEN),
(self.CEN - self.SIDE / 2, self.EDGE + self.HEIGHT)]
]
for i in range(0, 4):
if i == 0:
COLOR = self.YELLOW
pygame.draw.polygon(self.screen, COLOR, tan[i], 0)
else:
if i == 1:
COLOR = self.GREEN
elif i == 2:
COLOR = self.BLUE
elif i == 3:
COLOR = self.RED
pygame.draw.polygon(self.screen, COLOR, tan[i], 0)
pygame.draw.polygon(self.screen, COLOR, tan[i + 3], 0)
start_rc = [12, 0]
end_rc = [12, 0]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] -= 1
start_rc[1] += 1
end_rc[0] += 1
end_rc[1] += 1
start_rc = [0, 4]
end_rc = [24, 4]
for each in range(0, 5):
self.drawLine(start_rc, end_rc)
start_rc[0] += 1
start_rc[1] += 1
end_rc[0] -= 1
end_rc[1] += 1
start_rc = [4, 8]
end_rc = [20, 8]
for each in range(0, 5):
self.drawLine(start_rc, end_rc)
start_rc[0] -= 1
start_rc[1] += 1
end_rc[0] += 1
end_rc[1] += 1
start_rc = [9, 13]
end_rc = [15, 13]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] += 1
start_rc[1] += 1
end_rc[0] -= 1
end_rc[1] += 1
start_rc = [24, 4]
end_rc = [24, 4]
for each in range(0, 5):
self.drawLine(start_rc, end_rc)
start_rc[0] -= 2
end_rc[0] -= 1
end_rc[1] += 1
start_rc = [12, 0]
end_rc = [24, 12]
for each in range(0, 5):
self.drawLine(start_rc, end_rc)
start_rc[0] -= 1
start_rc[1] += 1
end_rc[0] -= 2
start_rc = [6, 4]
end_rc = [15, 13]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] -= 2
end_rc[0] -= 1
end_rc[1] += 1
start_rc = [3, 9]
end_rc = [6, 12]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] -= 1
start_rc[1] += 1
end_rc[0] -= 2
start_rc = [0, 4]
end_rc = [0, 4]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] += 2
end_rc[0] += 1
end_rc[1] += 1
start_rc = [0, 12]
end_rc = [12, 0]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] += 2
end_rc[0] += 1
end_rc[1] += 1
start_rc = [21, 7]
end_rc = [18, 4]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] += 1
start_rc[1] -= 1
end_rc[0] += 2
start_rc = [8, 12]
end_rc = [16, 4]
for each in range(0, 5):
self.drawLine(start_rc, end_rc)
start_rc[0] += 1
start_rc[1] += 1
end_rc[0] += 2
start_rc = [21, 9]
end_rc = [18, 12]
for each in range(0, 4):
self.drawLine(start_rc, end_rc)
start_rc[0] += 1
start_rc[1] += 1
end_rc[0] += 2
# 画棋子
for piece in self.pieces:
piece.draw(self.screen)
# 显示状态提示
self.display_status()
pygame.display.flip()
def display_status(self):
if self.is_clicked == -1:
status_text = "player"+str(self.playernow)+":Click on a piece to move"
elif self.is_clicked == 114514:
status_text = "winner:"+str(self.winner)
else:
status_text = "player"+str(self.playernow)+":Click on a destination to move the piece"
status_surface = self.font.render(status_text, True, self.BLACK)
self.screen.blit(status_surface, (10, 10))
status_text = "your player id:"+str(self.playerid)
status_surface = self.font.render(status_text, True, self.BLACK)
self.screen.blit(status_surface, (500, 10))
def receive_messages(self):
while True:
try:
response = self.client_socket.recv(1024).decode()
if response:
print(f"收到服务器的回复: {response}")
if response.startswith("登录成功"):
self.gamestate = True
self.playerid = int(response.split(':')[1])
print("你的playerid:",self.playerid)
elif response == "登录失败":
print("密码错误")
elif response == "注册成功":
print("注册成功")
else:
try:
numbers = eval(response)
if isinstance(numbers, list) and len(numbers) == 4:
print(f"提取到的4个数字: {numbers}")
self.pieces[numbers[0]].center = self.rcToXy((numbers[1], numbers[2]))
self.playernow = numbers[3]
else:
print("未能成功解析到三个数字列表")
except Exception as e:
print(f"解析出错: {e}")
else:
break
except ConnectionResetError:
print("与服务器的连接断开")
break
def send_message(self, message):
self.client_socket.sendall(message.encode())
def close(self):
self.client_socket.close()
def checkVictory(self):
cnt=[0,0,0]
for piece in self.pieces:
for i in range(3):
for center in self.victoy[i]:
#print(self.COLOR[self.playerid - 1],piece.color[0],self.rcToXy((center[0], center[1])),piece.center)
if self.COLOR[self.playerid - 1] == piece.color[0] and self.rcToXy((center[0], center[1])) == piece.center:
cnt[i] += 1
break
for i in range(3):
if cnt[i] == 10:
return i
return -1
def main(self):
while self.gamestate == False:
action = input("请选择操作 (1: 登录, 2: 注册): ")
if action == "1":
self.id = input("输入用户名:")
self.password = input("输入密码:")
self.send_message("user:" + str(self.id) + ":" + str(self.password))
elif action == "2":
self.id = input("输入注册用户名:")
self.password = input("输入注册密码:")
self.send_message("register:" + str(self.id) + ":" + str(self.password))
else:
print("无效的选项,请重新选择")
time.sleep(1)
self.screen = pygame.display.set_mode((self.BOARDSIZE, self.BOARDSIZE))
while self.gamestate == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 在事件处理函数中处理点击事件
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # 左键点击
if self.is_clicked != -1:
for center in self.POS4:
if self.is_clicked_empty(event.pos, center):
self.pieces[self.is_clicked].center = self.rcToXy((center[0], center[1]))
self.send_message("[%d, %d, %d]" % (self.is_clicked, center[0], center[1]))
self.pieces[self.is_clicked].index = 0
self.is_clicked = -1
self.winner = self.checkVictory()
if(self.winner != -1):
print("winner:",self.winner)
self.is_clicked = 114514
break
else:
i = 0
for piece in self.pieces:
#print(self.COLOR[self.playerid-1]==piece.color[0],self.playerid == self.playernow)
if piece.is_clicked(event.pos) and self.COLOR[self.playerid-1]==piece.color[0] and self.playerid == self.playernow:
piece.handle_click()
if self.is_clicked != -1:
self.pieces[self.is_clicked].index = 0
self.is_clicked = i
self.pieces[self.is_clicked].index = 1
i += 1
self.drawBoard()
pygame.display.flip()
#main.py
import socket
import time
import pygame
import sys
import math
from CheckerPiece import CheckerPiece
from CheckersBoard import CheckersBoard
if __name__ == "__main__":
checker_board = CheckersBoard()
checker_board.main()