python利用C/S实现简单的小游戏

游戏规则

交互式游戏设计(RemoteBet) (基于TCP)
 通过在远端主机上搭建一个远程骰宝服务器,其它主机可以通过客户端程序RemoteBet与远程的骰宝服务器联系,进行交互式游戏设计。命令行格式如下:
	RemoteBet <ServerIP> 
  如:		RemoteBet 127.0.0.1
	规则如下:
	ya tc <数量> <coin|silver|gold> 押头彩(两数顺序及点数均正确)       一赔三十五
	ya dc <数量> <coin|silver|gold> 押大彩(两数点数正确)               一赔十七
	ya kp <数量> <coin|silver|gold> 押空盘(两数不同且均为偶数)         一赔五
	ya qx <数量> <coin|silver|gold> 押七星(两数之和为七)               一赔五
	ya dd <数量> <coin|silver|gold> 押单对(两数均为奇数)               一赔三
	ya sx <数量> <coin|silver|gold> 押散星(两数之和为三、五、九、十一)   一赔二
每盘按从上到下的顺序只出现一种点型(头彩和大彩可同时出现),其他情况都算庄家赢。

	庄家唱道:新开盘!预叫头彩!
	庄家将两枚玉骰往银盘中一撒。
	┌───┐  ┌───┐
	│● ● │  │      │
	│● ● │  │  ●  │
	│● ● │  │      │
	└───┘  └───┘
	庄家唱道:头彩骰号是六、一!
	输入你压的值:
	ya tc 10 gold
	庄家将两枚玉骰扔进两个金盅,一手持一盅摇将起来。
	庄家将左手的金盅倒扣在银盘上,玉骰滚了出来。
	┌───┐
	│●  ●│
	│  ●  │
	│●  ●│
	└───┘
	庄家将右手的金盅倒扣在银盘上,玉骰滚了出来。
	┌───┐
	│  ●  │
	│      │
	│  ●  │
	└───┘
	庄家叫道:五、二……七星。
	你赢了多少?or 你输了多少?

假设服务器的IP地址为127.0.0.1,客户端程序连接到服务器进行远程骰宝游戏,然后按照服务器发回的游戏规则和提示进行游戏。

程序设计思路

客户端:

  1. 用户运行程序后,客户端在CMD中输出程序的规则
  2. 当用户点击开始后,程序首先输出头彩(这个头彩由客户端输出,然后开始等待用户输入)
  3. 当用户输入自己想要的选择后,发送给服务器,服务器处理,然后将用户的信息存储起来(需要发送他的地址),对用户发出博彩信息,先是第一个(存储),然后第二个(存储),然后根据与用户发过来的信息进行对比,然后再次发送给用户结果
  4. 客户端界面显示结果

服务端:

  1. 处于不断接收用户传来的信息的状态
  2. 将用户发来的信息存储,然后进行处理(因为用户是使用空格分离,所以取出对应的信息)然后发送数字(1~6,让客户端对应数字输出对应的图案,这里一次发送两个数字避免出现问题)并存储这两个数字并与客户端进行对比
  3. 然后发送给客户端结果

应用层协议设计

1、 先使用TCP协议将客户端同服务端连接
2、 然后服务端在服务器中将客户信息记录下来
3、 然后客户端开始传输信息
4、 服务器接收信息并处理
5、 处理结束后反馈给客户端

所选用的Python库介绍
一共选了以下几个库:
1、 Socket:这个就是套接字库,进行通讯
2、 Threading:这个库的作用是在服务器进行多线程的时候使用的
3、 Json:这个库是为了在信息传输加密的时候使用的
4、 Random:这个库的作用是选取随机数
5、 Datetime:这个库的作用是输出当前的时间

测试流程

1、 首先是客户端的登入界面:
在这里插入图片描述
在这里插入图片描述

2、 然后用户输入自己的选择:

在这里插入图片描述
3、 然后用户界面会显示用户的结果

在这里插入图片描述
4、 如果用户选择退出的话:

在这里插入图片描述5、 服务端的显示界面:

在这里插入图片描述6、 程序支持多线程连入:
在这里插入图片描述

分析总结及心得

1、 我认识到了多线程的重要性和便携性,上次的UDP实验我记得当时只能一方面,如果当时用上了多线程的话,就可以同时进行了
2、 TCP相对于UDP来说方便多了,而且个人也感觉更容易实现
3、 而且这个对于实现远程服务器来说,难度不大,亲测

源代码

client.py:

# 这个为客户端代码,大部分功能是在客户端代码上实现的

import socket
import random
import json


# 配置基础信息
HOST = '127.0.0.1'  # 服务器IP
PORT = 8022  # 服务器端口IP
BUFSIZE = 65535  # 缓冲区大小(1K)
ADDR = (HOST, PORT)  # 这是一个双元组


# rule 这个函数的作用是向用户输出这个游戏的规则
def rule():
    print("ya tc <数量> <coin|silver|gold> 押头彩(两数顺序及点数均正确) 一赔三十五\n"
          "ya dc <数量> <coin|silver|gold> 押大彩(两数点数正确) 一赔十七\n"
          "ya kp <数量> <coin|silver|gold> 押空盘(两数不同且均为偶数) 一赔五\n"
          "ya qx <数量> <coin|silver|gold> 押七星(两数之和为七) 一赔五\n"
          "ya dd <数量> <coin|silver|gold> 押单对(两数均为奇数) 一赔三\n"
          "ya sx <数量> <coin|silver|gold> 押散星(两数之和为三、五、九、十一) 一赔二\n"
          "每盘按从上到下的顺序只出现一种点型(头彩和大彩可同时出现),其他情况都算庄家赢\n")


# judge函数是用来根据服务发送过来的数字输出对应的图案
def judge(number):
    if number == 1:
        print("    ┌───────┐         \n"
              "    │       │         \n"
              "    │   ●  │         \n"
              "    │       │         \n"
              "    └───────┘        \n")
    elif number == 2:
        print("    ┌───────┐         \n"
              "    │       │         \n"
              "    │ ●  ●│         \n"
              "    │       │         \n"
              "    └───────┘        \n")
    elif number == 3:
        print("    ┌───────┐         \n"
              "    │ ●    │         \n"
              "    │   ●  │         \n"
              "    │     ●│         \n"
              "    └───────┘        \n")
    elif number == 4:
        print("    ┌───────┐         \n"
              "    │ ●  ●│         \n"
              "    │       │         \n"
              "    │ ●  ●│         \n"
              "    └───────┘        \n")
    elif number == 5:
        print("    ┌───────┐         \n"
              "    │ ●  ●│         \n"
              "    │   ●  │         \n"
              "    │ ●  ●│         \n"
              "    └───────┘        \n")
    elif number == 6:
        print("    ┌───────┐         \n"
              "    │ ●  ●│         \n"
              "    │ ●  ●│         \n"
              "    │ ●  ●│         \n"
              "    └───────┘        \n")


# result 这个函数的作用是判断服务发送过来的结果参数,然后输出对应的结果 1 表示胜利, 0 表示失败
def result(parameter, grade):
    if parameter == 1:
        print("Congratulation! You are Winner!")
        print("You got the grade is {}".format(grade))
    else:
        print("Sorry!You lose the game...")
        print("You lose the grade is {}".format(grade))


# theFirstPrice 这个头彩函数是用来在客户端输出两个随机数,减轻服务端的负担
def thefirstprice():
    # 首先获得两个随机数
    theFirstRandom = random.randint(1, 6)
    theSecondRandom = random.randint(1, 6)

    # 然后庄家开始预叫头彩
    print("新开盘,预叫头彩!")
    judge(theFirstRandom)
    judge(theSecondRandom)


# encodeoperate 这个函数的作用是将消息加密和json化统一操作
def encodeoperate(msg):
    msg = json.dumps(msg)
    msg = msg.encode('utf-8')
    return msg


# decodeoperate 这个函数的作用是将消息解码和json化统一操作
def decodeoperate(msg):
    msg = msg.decode('utf-8')
    msg = json.loads(msg)
    return msg


# inputoperate 这个函数的作用是将用户的操作集中
def inputoperate():
    # 开启一个无限循环如果用户想要一直玩的话
    while True:
        # 输入用户的押注
        choice = input("Please input your choice!//If you want to quit Please input quit!\n")
        # 判断是否要退出
        if choice == "quit":
            print("thank you for playing......")
            break

        # 对消息进行加密编码
        data = encodeoperate(choice)
        # 将消息发送给服务器
        tcpCliSock.sendall(data)

        # 然后等待服务的回应
        information = tcpCliSock.recv(BUFSIZE)
        msgFromSever = decodeoperate(information)

        # 从服务器接收来的是一个含有四个元素的列表
        # 然后客户端开始一个一个输出骰子
        print("The first one is :")
        judge(msgFromSever[0])
        print("The second one is :")
        judge(msgFromSever[1])

        # 输出用户的结果
        result(msgFromSever[2], msgFromSever[3])


if __name__ == '__main__':
    # 下面这个是创建tcp连接
    tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcpCliSock.connect(ADDR)

    # 下面开始了程序部分
    # 首先先向客户输出规则
    rule()

    # 利用input函数的中断,当用户明白规则后按回车继续
    input("Please input Enter to continue!")

    # 输出头彩
    thefirstprice()

    # 用户操作集合
    inputoperate()

server.py:

# 这段代码表示服务器


import socket
import threading
import json
import random
import datetime


# 配置基础信息
HOST = '127.0.0.1'  # 服务器IP
PORT = 8022  # 服务器端口IP
BUFSIZE = 65535  # 缓冲区大小(1K)
ADDR = (HOST, PORT)  # 这是一个双元组
socketList = []  # 这里用存储


# encodeoperate 这个函数的作用是将消息加密和json化统一操作
def encodeoperate(msg):
    msg = json.dumps(msg)
    msg = msg.encode('utf-8')
    return msg


# decodeoperate 这个函数的作用是将消息解码和json化统一操作
def decodeoperate(msg):
    msg = msg.decode('utf-8')
    msg = json.loads(msg)
    return msg


# targetoperate 这个函数的作用不断接收来自客户端的消息并处理
def targetoperate(target, address):
    try:
        # 采用循环不断地从socket中读取客户端发送过来的数据
        while True:
            # 接收客户端的请求
            content = readfromclient(target)

            # 首先先随机两个随机数
            theFirstRandom = random.randint(1, 6)
            theSecondRandom = random.randint(1, 6)

            # 然后对客户端的请求进行处理
            data = solve(content, theFirstRandom, theSecondRandom, address)

            # 对得到的data送至客户端
            target.sendall(data)

    except Exception:
        print("The client has error")
        return


# readfromclient 这个函数的作用是不断处于接受某个客户端的状态,如果客户端退出,就删除这个线程
def readfromclient(target):
    try:
        return decodeoperate(target.recv(BUFSIZE))
    # 如果捕获到异常,则表明该socket对应的客户端已经关闭
    except Exception:
        # 删除该socket
        target.close()


# solve 这个函数是对客户端发送过来的信息进行处理
def solve(content, first, second, address):
    # 因为客户端发送过来的格式是以空格来分开的如:XX XX XX XX,将这个格式变成列表
    content = content.split()
    # 得到用户压的数量
    count = content[2]
    # 首先得到用户选择的类型
    operate = content[1]
    # 初始化一个result
    result = 0
    # 初始化当前的时间
    now = datetime.datetime.now()

    # 下面开始对用户的选择进行判断
    if operate == 'tc':
        # 下面这个表示中了头彩
        if content[3] == first & content[4] == second:
            result = 1
            count = count * 35

    if operate == 'dc':
        if content[4] == first & content[4] == second:
            result = 1
        if content[4] == first & content[3] == second:
            result = 1
            count = count * 17

    if operate == 'kp':
        if first != second:
            if (first + second) % 2 == 0:
                result = 1
                count = count * 5

    if operate == 'qx':
        if first + second == 7:
            result = 1
            count = count * 5

    if operate == 'dd':
        if first % 2 == 1:
            if second % 2 == 1:
                result = 1
                count = count * 3

    if operate == 'sx':
        sumofrandom = first + second
        if sumofrandom % 2 == 1:
            result = 1
            count = count * 2

    if result == 1:
        print("{} has win the game at {}.".format(address, now.strftime("%Y-%m-%d %H:%M:%S")))
    else:
        print("{} has lose the game at {}".format(address, now.strftime("%Y-%m-%d %H:%M:%S")))

    # 将结果发送回客户端
    return encodeoperate([first, second, result, count])


if __name__ == '__main__':
    # 下面这个是创建tcp连接
    tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcpCliSock.bind(ADDR)
    tcpCliSock.listen(16)

    # 服务开始运行
    print("The sever is beginning")

    while True:
        # 此行代码会阻塞,将一直等待别人的连接
        clientTarget, addr = tcpCliSock.accept()
        socketList.append(clientTarget)

        print("{} has connected".format(addr))

        # 每当客户端连接后启动一个线程为该客户端服务
        threading.Thread(target=targetoperate, args=(clientTarget, addr)).start()
发布了41 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42224330/article/details/103433421