'''server'''
import socket
import numpy as np
from threading import Thread, Lock
import random
import json
import pickle
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('10.181.22.132', 6000))
'''
=================================================
0,数据库
=================================================
'''
'''记录有多少人登录'''
clientDict = {} #ipTuple: strName
'''记录一个桌子有几个人,凑够三个人开始玩'''
table = [] #[player, player, player]
'''玩家类'''
class player():
def __init__(self, name, card, landloard=False):
self.name = name #ipTuple
self.card = card
self.landloard = landloard
'''记录上一次出的牌'''
lastCard = -1
'''所有的牌面'''
totalCard = [f'{i}' for i in list(range(1, 11))+['J', 'Q', 'K'] for j in range(4)]
totalCard += ['小王', '大王']
'''牌的大小'''
cardValue = {key: value for key, value in zip([f'{i}' for i in range(1, 11)], range(1, 11))}
cardValue['J'] = 11
cardValue['Q'] = 12
cardValue['K'] = 13
cardValue['小王'] = 14
cardValue['大王'] = 15
'''
=================================================
1,人齐以后开始游戏
=================================================
'''
def playGame():
global table
global lastCard
'''
---------------------------
1-0,游戏开始
---------------------------
'''
for client in clientDict:
sk.sendto(f'\033[34m人数以齐,游戏开始!\033[0m'.encode('utf-8'), client)
'''
---------------------------
1-1,分配地主
---------------------------
'''
landlordIndex = np.random.randint(0, 3, 1)
print(landlordIndex)
print(table[int(landlordIndex)])
for client in clientDict:
sk.sendto(f'\033[34m{clientDict[table[int(landlordIndex)].name]}是地主\033[0m'.encode('utf-8'), client)
table[int(landlordIndex)].landloard = True
'''
---------------------------
1-2,发牌
---------------------------
'''
#将牌分为三份
middleMemoryCard = totalCard
card1 = sorted([middleMemoryCard[i] for i in np.random.choice(range(54), 17, replace=False)], key=lambda x: cardValue[x])
for card in card1:
middleMemoryCard.remove(card)
card2 = sorted([middleMemoryCard[i] for i in np.random.choice(range(37), 17, replace=False)], key=lambda x: cardValue[x])
farmersCard = [card1, card2]
for card in card2:
middleMemoryCard.remove(card)
card3 = sorted(middleMemoryCard, key=lambda x: cardValue[x])
# 发牌并显示牌
for i in range(3):
if table[i].landloard == True:
table[i].card = card3
sk.sendto(f'\033[35m你的牌是{str(card3)}\033[0m'.encode('utf-8'), table[i].name)
else:
table[i].card = farmersCard[-1]
sk.sendto(f'\033[35m你的牌是{str(farmersCard[-1])}\033[0m'.encode('utf-8'), table[i].name)
farmersCard.pop()
'''
---------------------------
1-3,出牌/说话
---------------------------
'''
overOrNot = False #游戏结束标志
JudgmentBit = False
farmersOrder = list(range(3))
farmersOrder.remove(landlordIndex)
playerCardOrder = [int(landlordIndex)] + farmersOrder #总的出牌顺序
passNum = 0 #pass个数
while True:
'''1-3-1,一直循环,只到有人出完牌'''
for i in playerCardOrder:
passOrNot = False # 出牌位,换人时一旦出牌passNum就要归零
'''1-3-2,顺序出牌'''
while True:
for client in clientDict:
sk.sendto(f'\033[34m轮到{clientDict[table[i].name]}出牌,出牌时请以英文“,”隔开,无牌可出请输入pass\033[0m'.encode('utf-8'), client)
cardMsg = sk.recvfrom(1024)
middleMsg = pickle.loads(cardMsg[0])
'''1-3-2-1,非出牌人说话'''
if cardMsg[1] != table[i].name:
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'{clientDict[cardMsg[1]]}说: {middleMsg}'.encode('utf-8'), client)
'''1-3-2-2,出牌人无牌可出\出牌错误\所出的牌没有\压不上\出牌成功'''
if cardMsg[1] == table[i].name:
'''1-3-2-2-1,出牌人无牌可出'''
if middleMsg[0] == 'pass':
passOrNot = True
passNum += 1
for client in clientDict:
sk.sendto(f'\033[36m{clientDict[cardMsg[1]]}竟然跳过了,实在太菜了!!!\033[0m'.encode('utf-8'), client)
break
elif len(middleMsg) > 2:
'''1-3-2-2-1.1,出牌错误,出的超过两张不允许'''
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'{clientDict[cardMsg[1]]}说: {middleMsg}'.encode('utf-8'), client)
else:
sk.sendto(f'\033[36m只允许出单张或者对子\033[0m'.encode('utf-8'), client)
elif (lastCard != -1) and (len(lastCard) != len(middleMsg)):
'''1-3-2-2-1.2,出牌错误,出牌与上一玩家的数目不一致'''
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'{clientDict[cardMsg[1]]}说: {middleMsg}'.encode('utf-8'), client)
else:
sk.sendto(f'\033[36m出牌需与上一玩家的数目保持一致!!!\033[0m'.encode('utf-8'), client)
else:
'''1-3-2-2-2,所出的牌没有:检查所出的牌是否都有,如果没有则出牌错误,认为是在说话'''
for card in middleMsg:
if card not in table[i].card:
JudgmentBit = True
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'{clientDict[cardMsg[1]]}说: {middleMsg}'.encode('utf-8'), client)
else:
sk.sendto(f'\033[36m不要出自己没有的牌!!!\033[0m'.encode('utf-8'), client)
break
if JudgmentBit:
JudgmentBit = False
continue
if len(middleMsg) == 2:
'''1-3-2-2-1.1,出牌错误,出的两张不同不允许'''
if middleMsg[0] != middleMsg[1]:
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'{clientDict[cardMsg[1]]}说: {middleMsg}'.encode('utf-8'), client)
else:
sk.sendto(f'\033[36m对子必须是相同的牌!!!\033[0m'.encode('utf-8'), client)
continue
'''1-3-2-2-3,所出的牌都有,判断是否可以压上'''
if lastCard == -1:
'''1-3-2-2-3.1,出牌成功,第一个出牌,总是能压上'''
lastCard = middleMsg
for card in middleMsg:
'''移除牌'''
table[i].card.remove(card)
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'\033[31m{clientDict[cardMsg[1]]}出牌: {middleMsg}\033[0m'.encode('utf-8'), client)
else:
sk.sendto(f'出牌成功!现在的牌是\033[35m{table[i].card}\033[0m'.encode('utf-8'), client)
break
elif lastCard[0] >= middleMsg[0]:
'''1-3-2-2-3.2,出的牌压不上,重新出牌'''
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'{clientDict[cardMsg[1]]}说: {middleMsg}'.encode('utf-8'), client)
else:
sk.sendto(f'\033[36m出的牌太小了!!!\033[0m'.encode('utf-8'), client)
continue
else:
'''1-3-2-2-3.2,出牌成功,出的牌可以压上'''
lastCard = middleMsg
for card in middleMsg:
'''移除牌'''
table[i].card.remove(card)
for client in clientDict:
if client != cardMsg[1]:
sk.sendto(f'\033[31m{clientDict[cardMsg[1]]}出牌: {middleMsg}\033[0m'.encode('utf-8'), client)
else:
sk.sendto(f'出牌成功!现在的牌是\033[35m{table[i].card}\033[0m'.encode('utf-8'), client)
break
'''一旦有人出牌,passNum置零'''
if not passOrNot:
passNum = 0
'''如果连续两个人跳过,重置lastCard'''
if passNum == 2:
lastCard = -1
'''1-3-3,如果有人出完了,游戏结束'''
if len(card3) == 0:
for client in clientDict:
sk.sendto(f'\033[34m**********************************地主获胜**********************************\033[0m'.encode('utf-8'), client)
overOrNot = True
break
elif len(card1) == 0 or len(card2) == 0:
for client in clientDict:
sk.sendto(f'\033[34m**********************************农民获胜**********************************\033[0m'.encode('utf-8'), client)
overOrNot = True
break
if overOrNot:
break
'''
---------------------------
1-4,初始化
---------------------------
'''
table = []
'''主程序'''
if __name__ == '__main__':
while True:
msg = sk.recvfrom(1024)
'''
=================================================
2,玩家登录、发送消息、申请玩游戏
=================================================
'''
if msg[1] not in clientDict:
'''2-1-1:登录'''
print(msg[1], pickle.loads(msg[0]))
clientDict[msg[1]] = pickle.loads(msg[0])
print(clientDict)
for client in clientDict:
sk.sendto(f'\033[31m欢迎{clientDict[msg[1]]}接入棋牌聊天室,当前版本1.1,只允许出单张和对子,想要玩牌请输入p/P\033[0m'.encode('utf-8'), client)
else:
'''2-1-2:退出'''
msgRec = pickle.loads(msg[0])
if msgRec[0].upper() == 'QUTI':
print(f'\033[32m{msg[1]}退出棋牌聊天室\033[0m')
quitter = clientDict[msg[1]]
clientDict.pop(msg[1])
print(clientDict)
for client in clientDict:
sk.sendto(f'\033[32m{quitter}退出棋牌聊天室\033[0m'.encode('utf-8'), client)
elif msgRec[0].upper() == 'P':
'''2-1-3:申请游戏,初始化玩家'''
if len(table) < 3:
print(f'\033[33m{msg[1]}申请参战\033[0m')
table.append(player(msg[1], []))
print(f'-->{table[-1].name}')
for client in clientDict:
sk.sendto(f'\033[33m{clientDict[msg[1]]}申请参战,还差{3-len(table)}人\033[0m'.encode('utf-8'), client)
else:
for client in clientDict:
sk.sendto(f'\033[33m{clientDict[msg[1]]}申请参战,但很可惜人数满了。。。\033[0m'.encode('utf-8'), client)
else:
'''2-1-4:发送消息'''
for client in clientDict:
if client != msg[1]:
sk.sendto(f'{clientDict[msg[1]]}说: {pickle.loads(msg[0])}'.encode('utf-8'), client)
'''
---------------------------
2-2,开始游戏
---------------------------
'''
if len(table) == 3:
playGame()
'''client'''
import socket
from threading import Thread
import pickle
sk = socket.socket(type=socket.SOCK_DGRAM)
server = ('10.181.22.132', 6000)
def receiveMessage(sk):
'''接收消息'''
while True:
msg = sk.recvfrom(1024)
print(msg[0].decode('utf-8'))
def sendMessage(sk):
'''发消息,轮到出牌的时候出牌'''
while True:
msg = list(input('>>>').split(','))
sk.sendto(pickle.dumps(msg), server)
if msg[0].upper() == 'P':
print('申请参战!')
if msg[0].upper() == 'QUTI':
print('退出棋牌室,再见!')
break
if __name__ == '__main__':
name = input('请输入您的名字:')
sk.sendto(pickle.dumps(name), server)
th1 = Thread(target=receiveMessage, args=(sk, ))
th2 = Thread(target=sendMessage, args=(sk,))
th1.start()
th2.start()