游戏测试 做一次 “不太靠谱” 的游戏抽卡概率入门级统计

陈随想 · 2021年06月16日 · 最后由 陈随想 回复于 2021年06月28日 · 6250 次阅读

背景

现在游戏都有抽卡,抽卡概率测试怎么尽可能去保证正确?
本文不讲为何要做统计,抽卡随机种子怎么产生,随机原理又如何等等,我不太会讲这些,如果有兴趣,请参考https://zhuanlan.zhihu.com/p/263526568
本文主要内容:基于我个人目前的测试环境,带你实操做一次入门级抽卡概率统计(其实就是把以前做过的事,记录一遍)。

方案思索

最理想的方案:多客户端并发抽卡,服务器日志记录,想办法获取数据,最后统计数据。这是最切合玩家的实际情况:几乎所有游戏,都会在卡池开放的那一刻,大量玩家涌入抽卡。多客户端并发旨在确保服务器随机数产生是线程安全的;服务器日志能很方便的记录所有的抽卡结果。
实际情况:目前有多并发协议工具,个人维护,本机电脑很难并发多个号执行抽卡(小几个倒是可以,毕竟服务器也是搭在我这台电脑);服务器日志,没有,问程序,答曰:你就抽卡能抽到,抽的问题不大就不用管了,日志不加。是的,你没看错,就是这么个答复。小公司就一个测试,你还能指望从程序那获得什么尊重与帮助(日常被某个程序鄙视)。
故采用另一种 “不太靠谱” 的曲线救国方式:
1:客户端自己收集 log。有一说一,每个游戏项目内网的包,肯定是有控制台打印收发协议数据的,因此这个貌似也可行;
2:客户端多开,然后模拟人工点击去生产足够的抽卡数据(当然,单开客户端来测试,也是有必要的,比如可以关注到单个玩家获取 SSR 的难度,最长多少抽不出 SSR。多开客户端模拟(假的)并发来做最后的概率计算,则更可靠一些。)
3:利用 pandas 以及 matplotlib 处理数据,生成我需要的图片
话不多说,接下来请看实操过程。

log 收集

我拥有的客户端代码是经过编译混淆的,但是仍然可以在 F12 控制台 sources 的 js 中找到代码并注入新的代码。

收到消息,以及发送协议这几个字,肯定是写在代码中的,于是搜索关键中文找到对应位置,并在对应位置注入我写的代码。
忽然发现我不太会 js,写起来费时间。于是我再绕个弯,注入一下代码:

static posthttp(data){
            var xhr = new XMLHttpRequest()
            xhr.open('POST', 'http://这里是ip地址:8888/api/v1/user', false);
            xhr.send(String(data)); 
        }

一个极其简单的 post,以及另外搭了一个极其简单的服务器来接受数值。
接下来在客户端 js 中根据协议号以及协议数据筛选出我要的数据:

if (是我要的协议号){
                for (x in t[1].drawingIds){
                    // u.Log("中文牛逼",  t[1].drawingIds[x]);    PS:是的,中文很牛逼。如果你说不牛逼,好,那么你是对的。
                    myArray.splice(0,0,t[1].drawingIds[x])
                }    

在我的服务器处理一下数据
处理类 class APIUserHandler
处理方法 post
把抽卡的 id 处理转换成最终的抽卡的品质(sr,r,ssr)。
我是做的十连抽卡(确认过就是单抽循环十次),我直接把十连的数据处理为 DataFrame 数据并写入文件(预计想搞个几十万数据,所以写入 csv 是比较合适的)

df = pd.DataFrame(np.array(temp))
df.to_csv('D:/Users/User/PycharmProjects/untitled/test.csv', mode='a', index=False, header=False)

接下来模拟点击几万次:如果你很牛逼,建议你手点;如果你非常牛逼,可以搞按键精灵;如果你和我一样菜的扣脚,自己写一个。
先前已经有了点击脚本,双线程,支持 esc 停止程序。恩,以前写的,拿过来用。


两个客户端两个点击位置。(别和我说你游戏 debug 包没有提供输入发送协议或者提供指令的功能,不然你怎么做协议测试?)
点第一个客户端再点第二个客户端,切换着点,搞出 20 万条数据(两个号一起抽卡获得的数据)如下:

数据处理

我需要得到指定品质出现两次的(次数)差值,比如第 5 次抽出了 SSR,第 90 次又出了 SSR,差值为 85;同时计算差值出现的次数

data = pd.read_csv('D:/Users/User/PycharmProjects/untitled/test.csv')
data_list = data['0'].values.tolist()#我往测试数据手动加入0作为colunm name,方便直接取出pd数据
def difference(value, datalist):
    j = 0
    result = []
    for i in range(0, len(datalist)):
        if datalist[i] == value:
            if i-j == 100:
                print(i)
            result.append(i-j)
            j = i
    return result

接下来出图,恩,ssr,r,sr 一起画的图太丑了(差值太多),于是我干脆不组合了,单独先看下 ssr。
关键代码

df2 = pd.DataFrame(np.array(ssr), columns=['ssr'])
result2 = df2.apply(pd.value_counts).sort_index()
result4 = pd.concat([result2], axis=1)
result4.plot(kind='bar', figsize=(20, 10), rot=0)
y_major_locator=MultipleLocator(10)
x_major_locator = MultipleLocator(10)
ax=plt.gca()
ax.xaxis.set_major_locator(x_major_locator)
ax.yaxis.set_major_locator(y_major_locator)

出图例子(其他图,散图等,不列举):

组合图示例:

最后:计算概率综合看下是否有问题;单个玩家收集数据看下最长多少次不出 ssr(上图两个玩家最多合计 155 抽不出 ssr,但是单个玩家不能看这个);r 卡条形图,sr 条形图会不会有什么异常数据等等。
综上:就是玩(不负责靠谱不靠谱)。为啥,我一个人测不来,策划没找我确认概率,直接找程序,程序就随便模拟了几万次给了个概率说没问题。
所以自己玩呗,加班有空弄点数据做个图,自己最后确认概率没问题就行,有问题再找程序(其实还有其他保底设定,幸运值什么的,也是经过反复测试确认没问题了)。

注:实际抽卡测试不只是做数据统计,要做的很多;另外战斗概率测试则更复杂(客户端混淆的代码偶尔也可以被我拿来做白盒测试)。

共收到 11 条回复 时间 点赞

用这种方式也是为难楼主了 😂 但概率统计,直接调接口就好了呀。通过前端去操作,效率非常低。

小怪兽 回复

其实效率很高的。具体为啥效率高,真的得看环境的(游戏行业超多外包以及众多小公司,我相信很多外包同学以及小公司小测试,拥有的环境就是能看到 debug 窗协议内容、能知道抽卡协议,除此之外什么都没有)。如果按照你说的,那么我也可以说,你直接让程序写个单测给数据,那不是效率最高了。

陈随想 回复

按道理就是应该单测

槽神 回复

老哥说的对,单测有一定是最好的;数据统计也是要有的。前者是在代码层面来保证问题,后者是给策划、测试一剂定心丸,在有数据的基础上,策划会更放心,测试也可以更有信心说没问题。不过,我感觉单测真的国内没法展开的。敏捷开发嘛,要的就是速度。老哥是否见过国内厂商做单测的,多不多?我对此挺好奇的。

陈随想 回复

全项目单测基本就别想了,没几个团队能做到
你这种特定功能,需要大样本测试的,单测最简单最经济,或者你可以管这个叫特定 service 的功能测试,不叫单测也许心里开心点

槽神 回复

确实。以前做个某个贸易类测试(python 写的),其中某个算法刚好 diff 可以看到,于是饶有兴趣地复制下来在自己本机上测试。这种最经济实惠了,而我也很开心。给别人算法研究 bug,能不开心么。

小团队一个测试,真是难为你了,哈哈哈。
不过 http 协议还好,起码收发包这块工具能快速上手。哪怕不用 js,用 python 啥的也都可以。
我现在这个项目是 socket 协议的,就 hin 头疼了。。

JarvanRookie 回复

恩。。。我这个就是 socket 的,而且数据格式用的 protobuf。我的协议工具也是基于 protobuf 数据来发送的。游戏不可能用 http 的吧,肯定都是长连接,要保持通讯的。

JarvanRookie 回复

我这里用 XMLHttpRequest 只是把客户端的 log 收集到我自己写的简易服务器,因为我觉得在客户端源码(混淆过的)上处理我要的数据有些麻烦,所以我就用 http 协议转到我自己服务器处理。整个游戏通讯肯定都是用长连接的。

陈随想 回复

我以前也是这么觉得的,游戏起码得有个心跳吧?但自从我来了现在这家公司之后,他们用 http 做游戏,而且线上运营了好几年了,也没事😂 😂 😂

JarvanRookie 回复

好吧,我孤陋寡闻了😌 😌 😌

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册