tensorzhang

可打牌,可聊天;出牌只能出对子和单张:)

1,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[0;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[0;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[0;35m你的牌是{str(card3)}\033[0m\'.encode(\'utf-8\'), table[i].name)
        else:
            table[i].card = farmersCard[-1]
            sk.sendto(f\'\033[0;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[0;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[0;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[0;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[0;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[0;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[0;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[0;31m{clientDict[cardMsg[1]]}出牌: {middleMsg}\033[0m\'.encode(\'utf-8\'), client)
                                else:
                                    sk.sendto(f\'出牌成功!现在的牌是\033[0;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[0;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[0;31m{clientDict[cardMsg[1]]}出牌: {middleMsg}\033[0m\'.encode(\'utf-8\'), client)
                                else:
                                    sk.sendto(f\'出牌成功!现在的牌是\033[0;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[0;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[0;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[0;31m欢迎{clientDict[msg[1]]}接入棋牌聊天室,当前版本1.1,只允许出单张和对子,想要玩牌请输入p/P,退出请输入QUTI\033[0m\'.encode(\'utf-8\'), client)

        else:
            \'\'\'2-1-2:退出\'\'\'
            msgRec = pickle.loads(msg[0])
            if msgRec[0].upper() == \'QUTI\':
                print(f\'\033[0;32m{msg[1]}退出棋牌聊天室\033[0m\')
                quitter = clientDict[msg[1]]
                clientDict.pop(msg[1])
                print(clientDict)
                for client in clientDict:
                    sk.sendto(f\'\033[0;32m{quitter}退出棋牌聊天室\033[0m\'.encode(\'utf-8\'), client)

            elif msgRec[0].upper() == \'P\':
                \'\'\'2-1-3:申请游戏,初始化玩家\'\'\'
                if len(table) < 3:
                    print(f\'\033[0;33m{msg[1]}申请参战\033[0m\')
                    table.append(player(msg[1], []))
                    print(f\'-->{table[-1].name}\')
                    for client in clientDict:
                        sk.sendto(f\'\033[0;33m{clientDict[msg[1]]}申请参战,还差{3-len(table)}人\033[0m\'.encode(\'utf-8\'), client)
                else:
                    for client in clientDict:
                        sk.sendto(f\'\033[0;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()

2,client-客户端

\'\'\'client\'\'\'
import socket
from threading import Thread
import pickle
from colorama import init
init(autoreset=True)

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()

分类:

技术点:

相关文章: