不用一张图片的像素小游戏:小人是字符串,房间是矩形,平衡靠两千个假玩家

发布时间:2026/10/14 7:05:20
不用一张图片的像素小游戏:小人是字符串,房间是矩形,平衡靠两千个假玩家
说明这个小游戏是和 AI 编程助手协作开发的本文也由 AI 协助整理成文。文中代码摘自项目源码注释改成了中文有删节数字来自源码和单元测试的输出。游戏内容纯属虚构和任何 AI 公司无关文中没有、游戏里也没有任何“防封技巧”。前言《AI 封号模拟器》是一个安卓小游戏每天一张事件卡两个选项赶在“自动审核”把你送走之前把项目做完。前两篇讲了它的规则和怎么给它加玩法。这一篇讲最近一次大更新里的三件事给游戏加上像素小人、小房间和成就徽章安装包里没有多一张图片。一天之内加了盲盒、副本、上课、人物关系四套东西胜率没有失控。从两种语言加到四种卡片文件一个字没改。一、小人是 16 行字符串没有美术也不想去找素材版权说不清。办法是把像素画直接写成字符串一个字母一个像素// 一张脸在不同心情下的样子只画第 5 行以下有变化的部分。. 表示这一格不画Mood.UNEASYtolistOf(............b...,// b一滴汗.....e....e..b..,// e眼睛................,.......mm.......,// m嘴拿不准的那种),一个人不是一张图而是拼出来的一个头加一种发型、一件上衣、一张当下的脸一层层盖上去。funperson(look:Look,mood:Mood,blink:Boolean,bob:Boolean):ListString{valrowsArray(SIZE){BLANK.toCharArray()}funlay(over:ListString,from:Int){// 把一层盖到画上. 的地方透过去over.forEachIndexed{y,row-row.forEachIndexed{x,c-if(c!.)rows[fromy][x]c}}}lay(head,0)lay(faces.getValue(mood),5)lay(hairs[look.hair],0)lay(look.extra,0)// 眼镜、黑眼圈lay(tops[look.top],11)returnrows.map{String(it)}}13 个人、6 种表情如果一张张画是 78 张图实际只写了 8 种发型、8 种上衣、6 张脸。加一个新人物就是加一行momtoLook(HAIR_LONG,0xFF4A3328,TOP_TEE,0xFFE58FB0),几个顺手得到的好处改起来像改文字。第一版的眼镜是一条黑杠看着像打了码改成灰色只动了一个字母。能测。有一项测试检查每张画都是 16×16、每个字母都有颜色、任何两个人都不长得一样。图标和游戏里是同一份数据。测试把图标上那个小人导出成“坐标 颜色”一个脚本读它生成启动器图标和商店图标。改了小人图标不会忘了改。被封的样子没有画“难过”。16×16 的脸上嘴角往下撇两个像素几乎看不出来。最后的做法是在眼睛上盖一条红杠这条红杠后来成了图标。二、房间是一个个矩形小人后来有了一个房间24×16 个像素窗、架子、台灯、桌子、屏幕。房间也没有图是代码里一个矩形一个矩形涂上去的vallitview.sanity40// 心态还够灯就亮着valrowsList(HEIGHT){LongArray(WIDTH){if(lit)WALLelseWALL_DIM}}funbox(x:Int,y:Int,w:Int,h:Int,color:Long){/* 把这一块涂成这个颜色 */}box(1,1,6,6,FRAME)// 窗框box(2,2,4,4,if(view.night)NIGHT_SKYelseDAY_SKY)// 答完今天的卡天就黑了if(view.money55)box(18,2,3,2,GREEN)// 钱够架子上有一盆绿植box(20,9,3,2,when{// 屏幕的颜色就是局势view.banned-RED view.nearlyDone-GREENelse-BLUE})房间里的每样东西都对应一个数值昼夜对应“今天答没答”台灯对应心态架子对应钱包屏幕对应账号。玩家不用读数字瞄一眼房间就知道自己什么处境。原来屏幕上只有三条进度条。三、加玩法之前先写“这不是捷径”这次一天里加了四套东西。每一套都可能让游戏变得太容易所以每一套都先写一条测试再调数值。测试的写法很土写几种“假玩家”让它们各玩两千局数赢了多少。valplain(0until2_000).count{play(it,carefultrue).state.endinginshipped}valboxing(0until2_000).count{play(it,carefultrue,boxestrue).state.endinginshipped}assertTrue(盲盒最多帮一点忙,boxingplain240boxing1_800)assertTrue(也不是坑,boxingplain-240)careful true是一个会权衡的假玩家boxes true是在它身上加一个毛病钱包里有闲钱就去开盲盒。跑出来的数两千局里赢的局数假玩家赢胜率认真玩126563%认真玩爱开盲盒136068%认真玩肯上课、接好工作144772%认真玩谁肯帮忙就找谁127364%随便乱选45023%第一版的数值几乎一定偏强。盲盒最初卖 9 块爱开盲盒的假玩家胜率到了 74%测试没过涨到 12 块课最初 6 块一堂肯上课的到了 75%涨到 9 块起。如果没有这条测试这两个数只能凭感觉。还有一条测试专门防“写了但永远出不来的卡”每种身份、每个副本各玩一千五百局96 张卡每一张都必须出现过。一个小坑要比较“有某件道具”和“没有”的差别得让两局的运气完全一样——同一个随机种子开两局。但两边消耗的随机数个数也必须一样否则后面的牌就对不上了。我第一次让一边去打工要随机抽一份零活、另一边去上课不抽第二天两边看到的就不是同一张卡。四、多语言原句当钥匙游戏文字原来在数据里是{zh, en}两个字段。加第三种语言时没有再加字段而是换了个思路中英照旧其他语言各一张“简体原句 → 译文”的表。funget(language:String,ai:String):Stringwhen(language){CHINESE-zh ENGLISH-enelse-Translations.of(language)[zh]?:if(language.startsWith(CHINESE))zhelseen}.replace({ai},ai)加一种语言 加一个表 一份界面文字卡片文件和代码都不动。代价是原句改一个字译文就对不上所以有一条测试把游戏里能出现的每一句话过一遍哪种语言漏了哪句、多了哪句没人用的旧话、占位符少了一个都会报出来。繁体中文是用 OpenCC 在电脑上转好再放进安装包的用的是台湾的说法软件→軟體项目→專案手机上不带转换库。日语是逐句翻的。译文比原文长会把界面撑破日语的“プロジェクト”比“项目进度”宽进度条左边那一栏被截掉了一个字最后改成了“進捗”。每加一种语言至少把主要页面截图看一遍。五、给截图留一个后门商店截图要拍“被封了”“开出了最稀有的道具”这种画面靠在模拟器里一路点过去既慢又碰运气。于是在调试版里留了一个入口启动时带一个参数直接摆出准备好的局面。adb shell am start -n 包名/.MainActivity --es pose banned发布版不认这个参数。四种语言、每种十一个画面一个脚本几分钟拍完文案改了就重拍。小结像素画写成字符串、房间写成矩形好处不只是省了美术它们能被测试、能被脚本读、改起来像改文字。加系统之前先写“不是捷径”的测试数值才有地方落脚。多语言用原句当钥匙再用一条测试守住“别漏翻”。游戏完全离线不要任何权限不收集任何数据。它还在 Google Play 封闭测试里个人开发者的新账号要凑够 12 人连续测 14 天才能发正式版。有兴趣的朋友可以这样参加加入测试群组点“加入群组”就行不用等审批https://groups.google.com/g/ai-ban-simulator-testers打开测试链接点“成为测试人员”https://play.google.com/apps/testing/com.weijiazhao.bansim用同一个账号在 Play 里安装装着别卸载留 14 天