python----------基于TCP的交互式游戏设计

通过在远端主机上搭建一个远程骰宝服务器,主机可以服务器联系,进行交互式游戏设计。

  • 游戏要求
  • 思路
  • 源码
    • bet_code_sample.py
    • server.py
    • client.py
  • 测试
  • 问题

游戏要求

规则如下:
ya tc <数量> 押头彩(两数顺序及点数均正确) 一赔三十五
ya dc <数量> 押大彩(两数点数正确) 一赔十七
ya kp <数量> 押空盘(两数不同且均为偶数) 一赔五
ya qx <数量> 押七星(两数之和为七) 一赔五
ya dd <数量> 押单对(两数均为奇数) 一赔三
ya sx <数量> 押散星(两数之和为三、五、九、十一) 一赔二

思路

在用户首次连接到服务器时,服务器发送两个骰子(作为头彩骰子号)以及游戏规则,同时将其暂时保存在列表中,之后等待用户回复;用户买定离手,客户端将消息回送给服务器端;服务器执行以下操作:随机丢出两个骰子、计算用户玩家的得失、清空暂存信息表和更新用户资金数,最后两个骰子和得失信息回送给客户端。
对于 client 端,接收到的消息被切分保存在message_list列表中:
message_list[0] 保存了标识符(rule,头彩和掷骰)用以确定执行的操作;
message_list[1]、message_list[2] 分别保存了第一个头彩骰子(或者第一个正式骰子)和第二个头彩骰子(或者第二个正式骰子);
message_list[3]、message_list[4] 分别保存了第一个正式骰子和第二个正式骰子对应的数
message_list[5] 保存了正式骰子对应的类型(头彩、七星等)
message_list[6] 保存了用户本轮的收益
对于 server 端,接收到的消息同样被切分保存在message_list列表中:
message_list[0] 保存了标识符,用以确定服务端执行的操作;
message_list[1] 用户本轮游戏选择的骰子类型
message_list[2] 用户本轮游戏所压的金额
message_list[3] 用户本轮游戏压的金额类型(金,银等)

源码

bet_code_sample.py

#!/usr/bin/env python3

num_dict = {
    1: "一",
    2: "二",
    3: "三",
    4: "四",
    5: "五",
    6: "六",
}

money_dict = {
    'gold': '金',
    'silver': '银',
    'coin': '铜',
}

money_num = {
    "gold": 50,
    "silver": 50,
    "coin": 50,
}

tz_type_dict = {
    'tc': '头彩',
    'dc': '大彩',
    'kp': '空盘',
    'qx': '七星',
    'dd': '单对',
    'sx': '散星',
    'zy': '庄赢',
}

dice = [
    """
┌─────┐
│     │
│  ●  │
│     │
└─────┘""", """
┌─────┐
│  ●  │
│     │
│  ●  │
└─────┘""", """
┌─────┐
│  ●  │
│     │
│ ● ● │
└─────┘""", """
┌─────┐
│ ● ● │
│     │
│ ● ● │
└─────┘""", """
┌─────┐
│ ● ● │
│  ●  │
│ ● ● │
└─────┘""", """
┌─────┐
│ ● ● │
│ ● ● │
│ ● ● │
└─────┘"""
]

toucai = {}

temp_dice = {}

#记录顺序:key:地址;value:下注类型,金额,钱币类型
User = {}

server.py

import socket
import bet_code_sample
import random
import gevent
from gevent import monkey


PORT = 9999
ADDRESS = '127.0.0.1'
MAX_BYTES = 65535


#产生一个随机骰子
def random_dice():
    num = random.randint(0 ,5)
    return bet_code_sample.dice[num] ,str(num+1)

#选项菜单
def menu(sc):
    print('[+] connected with', addr)
    bet_code_sample.User[addr] = [0 ,0 ,0 ,bet_code_sample.money_num]
    while True:
        data = sc.recv(MAX_BYTES)
        message = data.decode('utf-8')
        message_list = message.split('@')
        if message_list[0] == 'rule':
            message = ('rule@规则如下:\n'
                       'ya tc <数量>  押头彩(两数顺序及点数均正确)      一赔三十五\n'
                       'ya dc <数量>  押大彩(两数点数正确)      一赔十七\n'
                       'ya kp <数量>  押空盘(两数不同且均为偶数)       一赔五\n'
                       'ya qx <数量>  押七星(两数之和为七)      一赔五\n'
                       'ya dd <数量>  押单对(两数均为奇数)      一赔三\n'
                       'ya sx <数量>  押散星(两数之和为三、五、九、十一)   一赔二\n')
        elif message_list[0] == 'begin':
            dice1, num1 = random_dice()
            dice2, num2 = random_dice()
            # 头彩骰子存入数组
            bet_code_sample.toucai[addr] = [dice1 ,dice2]
            message = '头彩' + '@' + dice1 + '@' + dice2 + '@' + num1 + '@' + num2
        elif message_list[0] == 'cheak':
            message = '金' + str(bet_code_sample.User[addr][3]['gold']) + ';' +\
                      '银' + str(bet_code_sample.User[addr][3]['silver']) + ';' +\
                      '铜' + str(bet_code_sample.User[addr][3]['coin']) + '\n'
        elif message_list[0] == 'exit':
            reply = 'finished'
            return reply
        else:
            if int(bet_code_sample.User[addr][3][message_list[2]]) < int(message_list[1]):
                message = 'deficient'
            else:
                print('有鱼上钩了')
                #记录顺序:key:地址;value:类型,金额,钱币类型,用户初始账户金钱
                bet_code_sample.User[addr][0] = message_list[0]
                bet_code_sample.User[addr][1] = message_list[1]
                bet_code_sample.User[addr][2] = message_list[2]
                print(bet_code_sample.User)
                #4、发送随机骰子
                dice1, num1 = random_dice()
                dice2, num2 = random_dice()
                bet_code_sample.temp_dice[addr] = [dice1 ,dice2]
                response, additional = result(addr ,num1, num2)
                profit = calculate(response, additional, addr)
                message = '掷骰' + '@' + dice1 + '@' + dice2 + '@' + num1 + '@' + num2 + '@' + response + '@' + profit
        data = message.encode('utf-8')
        sc.sendall(data)



#返回对应骰子类型
def result(addr ,num1 ,num2):
    additional = 'None'
    #注:是头彩一定是大彩
    if ((num1 == bet_code_sample.toucai[addr][0]) and (num2 == bet_code_sample.toucai[addr][1])) or \
            ((num1 == bet_code_sample.toucai[addr][1]) and (num2 == bet_code_sample.toucai[addr][0])):
        if (num1 == bet_code_sample.toucai[addr][0]) and (num2 == bet_code_sample.toucai[addr][1]):
            additional = 'tc'
        else:
            additional = 'dc'
    if (num1 != num2) and (int(num1) % 2 == 0) and (int(num2) % 2 == 0):
        return 'kp' ,additional
    elif (int(num1) + int(num2)) == 7:
        return 'qx' ,additional
    elif (int(num1) % 2 == 1) and (int(num2) % 2 == 1):
        return 'dd' ,additional
    elif (int(num1) + int(num2)) in [3 ,5 ,9 ,11]:
        return 'sx' ,additional
    else:
        return 'None' ,additional


#计算对应内容的收益,返回字符串
def calculate(response ,additional ,addr):
    money_type = bet_code_sample.User[addr][2]
    #特殊情况response为头彩时
    if additional != 'None':
        if bet_code_sample.User[addr][0] == additional:
            if additional == 'tc':
                #赋予该用户新的金钱持有数
                bet_code_sample.User[addr][3][money_type] = str(
                    int(bet_code_sample.User[addr][3][money_type]) + int(bet_code_sample.User[addr][1]) * 34)
                return '+' + str(int(bet_code_sample.User[addr][1]) * 34) + ' ' + bet_code_sample.money_dict[bet_code_sample.User[addr][2]]
            elif additional == 'dc':
                bet_code_sample.User[addr][3][money_type] = str(
                    int(bet_code_sample.User[addr][3][money_type]) + int(bet_code_sample.User[addr][1]) * 17)
                return '+' + str(int(bet_code_sample.User[addr][1]) * 17) + ' ' + bet_code_sample.money_dict[bet_code_sample.User[addr][2]]
    #其他情况response等于压的注
    if response == bet_code_sample.User[addr][0]:
        if response == 'kp' or response == 'qx':
            bet_code_sample.User[addr][3][money_type] = str(
                int(bet_code_sample.User[addr][3][money_type]) + int(bet_code_sample.User[addr][1]) * 4)
            return '+' + str(int(bet_code_sample.User[addr][1]) * 4) + ' ' + bet_code_sample.money_dict[bet_code_sample.User[addr][2]]
        elif response == 'dd':
            bet_code_sample.User[addr][3][money_type] = str(
                int(bet_code_sample.User[addr][3][money_type]) + int(bet_code_sample.User[addr][1]) * 2)
            return '+' + str(int(bet_code_sample.User[addr][1]) * 2) + ' ' + bet_code_sample.money_dict[bet_code_sample.User[addr][2]]
        elif response == 'sx':
            bet_code_sample.User[addr][3][money_type] = str(
                int(bet_code_sample.User[addr][3][money_type]) + int(bet_code_sample.User[addr][1]) * 1)
            return '+' + str(int(bet_code_sample.User[addr][1]) * 1) + ' ' + bet_code_sample.money_dict[bet_code_sample.User[addr][2]]
    else:
        bet_code_sample.User[addr][3][money_type] = str(
            int(bet_code_sample.User[addr][3][money_type]) - int(bet_code_sample.User[addr][1]) * 1)
        return '-' + str(int(bet_code_sample.User[addr][1])) + ' ' + bet_code_sample.money_dict[bet_code_sample.User[addr][2]]


if __name__ == '__main__':
    monkey.patch_all()
    # 创建空套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 地址端口绑定
    sock.bind((ADDRESS, PORT))
    # 端口监听,且限制后备连接数为5
    sock.listen(5)
    print('listen at', sock.getsockname())
    while True:
        sc ,addr = sock.accept()
        gevent.spawn(menu ,sc)
    sock.close()
    sc.close()

client.py

import socket
import sys
import os
import bet_code_sample
import time
import random

PORT = 9999
MAX_BYTES = 65535


#连接服务端
def init_connection(sock):
    addr = input('请输入游戏服务器地址:\n')
    try:
        #连接地址端口
        sock.connect((addr ,PORT))
    except Exception:
        print('Error')
        sys.exit()
    print('连接成功!')
    return addr


#实现屏幕摇骰子特效
def dice_Special_effects(dice_data=None ,rule=None):
    if dice_data == None:
        count = random.randint(10 ,15)
        for i in range(count):
            print(rule)
            print('庄家唱道:新开盘!预叫头彩!')
            print('第一次掷骰子:')
            print(bet_code_sample.dice[random.randint(0 ,5)])
            time.sleep(0.01+0.001*i*i)
            os.system('cls')
    else:
        count = random.randint(10 ,15)
        for i in range(count):
            print(rule)
            print('庄家唱道:新开盘!预叫头彩!')
            print('第一次掷骰子:')
            print(dice_data)
            print('第二次掷骰子:')
            print(bet_code_sample.dice[random.randint(0 ,5)])
            time.sleep(0.01+0.001*i*i)
            os.system('cls')
        print(rule)
        print('第一次掷骰子:')
        print(dice_data)
        print('第二次掷骰子:')


#消息处理
def msgmng(message ,rule=None):
    while True:
        message_list = message.split('@')

        if message_list[0] == 'rule':
            return message
        elif message_list[0] == '头彩':
            dice_Special_effects(rule=rule)
            print(message_list[1])
            dice_Special_effects(message_list[1] ,rule)
            print(message_list[2])
            print('庄家唱道:头彩骰号是' + bet_code_sample.num_dict[int(message_list[3])] + '、' + bet_code_sample.num_dict[int(message_list[4])] + '!')
        elif message_list[0] == '掷骰':
            dice_Special_effects(rule=rule)
            print(message_list[1])
            dice_Special_effects(message_list[1], rule)
            print(message_list[2])
            print('庄家叫道:' + bet_code_sample.num_dict[int(message_list[3])] + '、' +
                  bet_code_sample.num_dict[int(message_list[4])] + '......' + bet_code_sample.tz_type_dict[message_list[5]] + '!')
            print('您的净收益为:' + message_list[6])

        return message


#消息发送接受
def msgsend_rcv(sock ,message):
    data = message.encode('utf-8')
    sock.sendall(data)
    data = sock.recv(MAX_BYTES)
    message = data.decode('utf-8')
    return message


#持续连接状态下进行的操作
def connecting(sock):
    #显示规则
    rule = msgsend_rcv(sock, 'rule')
    print(rule)
    os.system('pause')
    while True:
        message = msgsend_rcv(sock, 'begin')
        #显示摇骰子  头彩  特效
        msgmng(message ,rule = rule)
        #用户操作投注
        while True:
            temp_message = input('请输入:\n'
                                 '投注(如:ya tc 10 gold)\n'
                                 '退出:exit\n'
                                 '查看金钱:cheak\n')
            temp_message_list = temp_message.split(' ')
            if temp_message_list[0] == 'exit':
                message = 'exit'
                msgsend_rcv(sock, message)
                sock.close()
                break
            elif temp_message_list[0] == 'cheak':
                message = 'cheak'
                message = msgsend_rcv(sock, message)
                print(message)
                time.sleep(0.001)
            elif temp_message_list[0] == 'ya':
                try:
                    if bet_code_sample.tz_type_dict[temp_message_list[1]]:
                        if int(temp_message_list[2]):
                            if bet_code_sample.money_num[temp_message_list[3]]:
                                message = temp_message_list[1] + '@' + temp_message_list[2] + '@' + temp_message_list[3]
                                break
                except Exception:
                    pass
            print('请重新输入!')
        message = msgsend_rcv(sock, message)
        if message == 'deficient':
            print('资金不足!请充值!')
        else:
            # 显示摇骰子  真骰子  特效
            msgmng(message ,rule=rule)
        os.system('pause')


if __name__ == '__main__':
    # 空套接字创建
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    addr = init_connection(sock)
    connecting(sock)

测试

服务器连接:
python----------基于TCP的交互式游戏设计_第1张图片
玩家押注:
python----------基于TCP的交互式游戏设计_第2张图片
居然赚钱了:
python----------基于TCP的交互式游戏设计_第3张图片
查看金钱(默认均为50):
python----------基于TCP的交互式游戏设计_第4张图片

问题

1、暂存界面有些地方文字显示有些许错误,但是不涉及关键的代码,也懒得改了
2、对比网上大部分的代码来看,着重将投掷骰子的代码放在服务器端的代码中,扔出来以后再发送给客户端,这样一来可以避免客户修改客户端代码达到无限谋利的情况,二来我可以随时更改投骰子的算法(现在采用的时简单的随机数种子生成器即random),以达到商家骗取玩家金钱的目的。因此,千万记得,赌博害人啊!!!

你可能感兴趣的:(Python)