python网络编程 交互式游戏设计——吹牛(RemoteBet)(无封帧)

杭电网络编程实验

介绍:

1.交互式游戏设计——吹牛(RemoteBet) (基于TCP)(要求使用封帧技术

        通过在远端主机上搭建一个远程吹牛服务器,其它n台主机可以通过客户端程序与远程的吹牛服务器联系,进行交互式游戏设计。命令行格式如下:

                     RemoteBet <ServerIP>

      如: RemoteBet 127.0.0.1

         游戏背景:小黑和他的朋友们经常去学校东门外面的helens里喝酒。他们很喜欢玩“吹牛”的游戏。但是由于疫情被迫封在了学校里,请你帮助他们设计一款程序,能够让他们在宿舍里仍然能够通过电脑进行游戏。

规则如下:

(1)游戏开始时,服务器向每个玩家发送一个序列。该序列是一个长度为5的数组,数组中每个元素的值为1-6不等。每个玩家仅能看到自己手中的骰子点数。

(2)第一个玩家A轮流进行猜测。猜测所有人拥有的点数之和。例如可以猜测,5个3,6个2等。

(3)当玩家A猜测完成后,下一个玩家B进行猜测。玩家B需要在玩家A的基础之上进行猜测,例如:若玩家A猜测为X个Y,玩家B则需要猜测X+N个Y+M,且满足N*10+M>0NM属于整数

(4)直到有玩家不相信所有人有这么多的数量,可以喊“开!”,此时进行游戏判定:若实际拥有量 与上家吹嘘拥有量 之间满足 < ,则事实为假,上家输;若 >= ,则事实为真,本家输。二者的计算关系为

(5)每当一轮游戏结束时,将这一轮输的玩家将被视为下一轮游戏的开始。

游戏样例:

Alice、Bob、Cristina、Dave四个人进行游戏。

————————————准备阶段————————————

Alice:1 5 6 5 2

Bob:  2 2 4 6 3

Cristina:3 3 3 4 6

Dave:1 1 3 5 1

————————————游戏开始————————————

Alice:3个3

Bob:3个4

Cristina:4个1

Dave:6个1

Alice:6个5

Bob:开!

————————————游戏结算————————————

此时,Alice喊出了6个5,而5在Alice手里有2个,Bob没有,Cristina没有,Dave手里有1个,四个人一共有3个5, 为35, 为65, ,Alice输。

———————————下一轮游戏准备阶段———————————

Alice:1 1 1 1 4

Bob:  2 2 2 1 5

Cristina:3 3 4 4 6

Dave:1 4 3 5 2

————————————游戏开始————————————

Alice:2个4

Bob:3个3

Cristina:4个4

Dave:开!

————————————游戏结算————————————

此时,Cristina喊出了4个4,而4在Alice手里有1个,Bob没有,Cristina手里有2个,Dave手里有1个,四个人一共有4个4, 为44, 为44, ,Dave输。

命令行说明:

       猜测时:2 3

       开: open!

服务器端代码:

# 导入套接字模块
import random
import re
import socket
# 导入线程模块
import threading
import sys
count = 0
user_count = 0
start = False
numlist = []
userlist = []
over = False
turn = -1
sumnumber = 0
count_turn = 0
last = [0, 0]
first = False
sbexit=False

def playing_client(userlist: list):
    global count
    for i in range(count):
        str1 = "您的牌为:" + str(numlist[5 * i]) + " " + str(numlist[5 * i + 1]) + " " + str(
            numlist[5 * i + 2]) + " " + str(numlist[5 * i + 3]) + " " + str(numlist[5 * i + 4])
        senddata = str1.encode(encoding='utf-8')
        userlist[i].sendall(senddata)


def start_game():
    global count, userlist
    global numlist
    print("count" + str(count))
    for i in range(count):
        str1 = "————————————游戏开始————————————".encode(encoding='utf-8')
        userlist[i].sendall(str1)
        for j in range(5):
            a = random.randint(1, 6)
            numlist.append(a)
    playing_client(userlist)
    return


def nextgame():
    global user_count, userlist, first,last
    global numlist
    first = False
    last[0]=0
    last[1]=0
    for i in range(user_count):
        for j in range(5):
            a = random.randint(1, 6)
            numlist[5 * (user_count - 1) + j] = a
    playing_client(userlist)
    return


# 定义个函数,使其专门重复处理客户的请求数据(也就是重复接受一个用户的消息并且重复回答,直到用户选择下线)
def start_client_request(tcp_client_1, tcp_client_address):
    global count, start, userlist, last, turn, first,sbexit
    owner = False
    if start:
        tcp_client_1.close()
        return
    count = count + 1
    this_count = count
    print("this_count"+str(this_count))
    str1="您是第{}号玩家".format(this_count).encode(encoding='utf-8')
    tcp_client_1.sendall(str1)
    # 5 循环接收和发送数据
    while True:
        if sbexit:
            print("exit")
            sys.exit()
        try:
            recv_data = tcp_client_1.recv(1024)
        except ConnectionResetError:
            sbexit = True
            str1 = "sb exit".encode(encoding='utf-8')
            for user1 in userlist:
                if user1!=tcp_client_1:
                    user1.send(str1)
                    user1.close()
            sys.exit()
        recv_meg = recv_data.decode(encoding='utf-8')
        print(recv_meg)
        if start == False:
            if recv_meg == "start":
                start = True
                start_game()
                turn = this_count
                str1 = "your turn".encode(encoding='utf-8')
                tcp_client_1.sendall(str1)
                continue
            else:
                str2 = "输入不符合规则".encode(encoding='utf-8')
                tcp_client_1.sendall(str2)
                continue
        if turn == this_count:
            if recv_meg == 'open!' and first:
                m1 = numlist.count(last[1]) * 10 + last[1]
                m2 = last[0] * 10 + last[1]
                if m1 < m2:
                    message = "{0}号玩家输,{1}号玩家赢".format((this_count + count -2) % count + 1,
                                                               this_count ).encode(encoding="utf-8")
                    message2 = "————————————游戏开始————————————".encode(encoding="utf-8")
                    for user in userlist:
                        user.sendall(message)
                        user.sendall(message2)
                    nextgame()
                    continue
                else:
                    message = "{0}号玩家赢,{1}号玩家输".format((this_count + count -2) % count + 1,
                                                               this_count ).encode(encoding="utf-8")
                    message2 = "————————————游戏开始————————————".encode(encoding="utf-8")
                    for user in userlist:
                        user.sendall(message)
                        user.sendall(message2)
                    nextgame()
                    continue
            m = re.match('^[1-9] [1-6]+', recv_meg)
            if m is not None and m.group(0) == recv_meg:
                number = recv_meg.split(" ")
                if ((int(number[0]) - last[0]) * 10 + (int(number[1]) - last[1]) <= 0):
                    str2 = "输入不符合规则".encode(encoding='utf-8')
                    tcp_client_1.send(str2)
                    continue
                # 发送除当前用户外的每个用户
                message = "{}号用户:".format(this_count)
                message = message + recv_meg
                message = message.encode(encoding='utf-8')
                for user in userlist:
                    if user != tcp_client_1:
                        user.send(message)
                last[0] = int(number[0])
                last[1] = int(number[1])
                first = True
                str1 = "your turn".encode(encoding='utf-8')
                userlist[turn % count].send(str1)
                turn = turn % count + 1
            else:
                str2 = "输入不符合规则".encode(encoding='utf-8')
                tcp_client_1.sendall(str2)
                continue
        else:
            str1 = "未到您的回合".encode(encoding='utf-8')
            tcp_client_1.sendall(str1)
    return


if __name__ == '__main__':
    # 1 创建服务端套接字对象
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置端口复用,使程序退出后端口马上释放
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2 绑定端口
    tcp_server.bind(("", 61234))
    tcp_server.settimeout(20)
    # 3 设置监听
    tcp_server.listen(128)
    # 4 循环等待客户端连接请求(也就是最多可以同时有128个用户连接到服务器进行通信)
    while True:
        if sbexit:
            print("main exit")
            sys.exit()
        tcp_client_1, tcp_client_address = tcp_server.accept()
        if start:
            tcp_client_1.close()
            break
        print('connect')
        userlist.append(tcp_client_1)
        thd = threading.Thread(target=start_client_request, args=(tcp_client_1, tcp_client_address))
        # 设置守护主线程  即如果主线程结束了 那子线程中也都销毁了  防止主线程无法退出
        #thd.setDaemon(True)
        # 启动子线程对象
        thd.start()

客户端代码:

import socket
import threading
import re
exit=True
def sendmessage():
    global tcp_client_1,exit
    while exit:
        send = input()
        send_data = send.encode(encoding='utf-8')
        if not exit:
            break
        tcp_client_1.send(send_data)
def getmessage():
    global tcp_client_1
    while True:
        recv_data = tcp_client_1.recv(1024)
        recv_meg = recv_data.decode(encoding='utf-8')
        print(recv_meg)
        if 'sb exit'==recv_meg:
            exit=False
            break

if __name__ == '__main__':
    # 1 创建客户端套接字对象tcp_client_1
    # 参数介绍:AF_INET 代表IPV4类型, SOCK_STREAM代表tcp传输协议类型 ,注:AF_INET6代表IPV6

    tcp_client_1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    while True:
        cmd=input("请输入:RemoteBet <ServerIP>")
        m=re.match(r'^RemoteBet ((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$', cmd)
        if m is not None and m.group(0) == cmd:
            break
    cmd=cmd.split(' ')
    print(cmd[1])
    # 2 通过客户端套接字的connect方法与服务器套接字建立连接
    # 参数介绍:前面的ip地址代表服务器的ip地址,后面的61234代表服务端的端口号 。
    print("connecting")
    tcp_client_1.connect((cmd[1], 61234))
    print("连接成功")
    # 将编号好的数据存到变量send_data中,注:encode(encoding='utf-8)是将数据转换成utf-8的格式发送给服务器
    thd = threading.Thread(target=sendmessage, args=())
    # thd.setDaemon(True)
    thd.start()
    thd = threading.Thread(target=getmessage, args=())
    # thd.setDaemon(True)
    thd.start()

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值