Featured image of post 利用ChatGPT开发一例

利用ChatGPT开发一例

没有JavaScript基础也可以借助AI改出来的小游戏——2048iáng

因为实在很闲所以做了,之前就想过做这个。基于Gabriele Cirulli的2048源码,基本靠ChatGPT完成了代码部分的修改。

下面简要记录开发的过程。

首先,把GameManager喂给AI,我甚至不知道这是什么,AI告诉我这是用于2048游戏的类。类就类吧,我让它给我解释了每一部分代码都是干什么的,之后我才发现,甚至这一步都是多余的。

接下来我开始提需求了。我还是先对我要实现的游戏进行了简单的抽象化的:我让1~9分别代表“幺”“言”“长”“马”“月”“刂”“穴”“心”“辶”,然后比如55,是两个5,就代表“朋”。这样“𰻝”就可以表示成75121343689(问就是按笔顺排列的)。

我: 假设我现在要设计一种新型的2048,它是这样的:会随机产生1~9这9种不同的方块,两个1可以合并成11,两个2可以合并成22,两个3可以合并成33,但是两个4不能合并成44。此外,1和2可以合并成12,3和4可以合并成34,1和12可以合并成121,3和34可以合并成343,121和343可以合并成121343,121343和5可以合并成5121343,121343和6可以合并成1213436,5121343和6或者5和1213436都可以合并成51213436,51213436和7可以合并成751213436,51213436和8可以合并成512134368,512134368和7或者751213436和8都可以合并成7512134368,最后,7512134368和9可以合并成75121343689。除了我提到的方块种类之外不存在其他种类的方块,除了我提到的合并方法之外的方块都不可以合并,这个代码需要进行怎样的改动?
ChatGPT: 为了实现这种新型的2048游戏,需要在整个游戏的代码中进行一些修改。
1.首先要在Tile类中增加一个新属性,用来存储方块的种类。
2.修改随机生成新方块的代码,使得生成的方块可以是1~9这9种不同的方块。
3.修改合并方块的代码,使得只有满足新的合并规则的方块才能进行合并。
4.修改判断游戏结束的代码,使得当没有可移动或可合并的方块时,游戏才结束。
5.最后需要对游戏的UI部分进行修改,使得游戏界面能够展示新的方块种类以及新的合并规则。
这些修改都需要对代码进行大量的更改,并且需要具备较为丰富的javascript开发经验。

开发经验?不需要!既然它已经把需求分解好了,我一个一个问就是了。

我: 请告诉我怎么在Tile类中增加一个新属性,用来存储方块的种类

我不会,但是它当然能给出来:

1
2
3
4
5
6
function Tile(position, value, type) {
  this.x                = position.x;
  this.y                = position.y;
  this.value            = value || 2;
  this.type             = type;//新增的属性
}

不过我突然想到,为什么要加新的type属性,我不能利用value属性吗?可惜,ChatGPT对此的回答是,不可以,我必须新增一个属性来存储这些1~9、11等数字。我让它思考值是否仍有意义,它说是有意义的,可以用于计算分数,这一点倒是启发了我。我暂时跳过这条,仍然打算把方块的种类存在value中。它还提到了胜利条件,当然是拼出“𰻝”字。由此我想到了新的问题,也是它提出的第二点需求。

我: 根据我的合并规则与胜利条件,随机生成1~9的概率分别是多大能使得游戏难度适中?

经过反复调教,它最终给我的概率是:

  • 1: 0.1
  • 2: 0.2
  • 3: 0.1
  • 4: 0.2
  • 5: 0.1
  • 6: 0.1
  • 7: 0.05
  • 8: 0.05
  • 9: 0.01

加起来不到1也是意料之中的,它一直没给出过加和为1的概率,不过大致可以参考这个比例了。

我: 现在请你修改随机生成新方块的代码(addRandomTile),使得生成的方块可以是1~9这9种不同的方块且概率如你所说

它给我的写法我没看懂,我让它换一种写法,令数组直接存储概率,它也做到了。接下来让它继续实现需求。

我: 谢谢你,我改好了。接下来,如何修改合并方块的代码,使得只有满足新的合并规则的方块才能进行合并?

几下引导后,它给出了判断能否合并的方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
GameManager.prototype.canMerge = function(first, second) {
    // 判断两个方块的类型是否允许合并
    var firstType = first.type;
    var secondType = second.type;
    var pattern = firstType + secondType;
    if(/^(11|22|33|12|34|121|343|5121343|1213436|51213436|751213436|512134368|7512134368|75121343689)$/.test(pattern)){
        return true;
    }else{
        return false;
    }
}

当然,它还惦记它那type,我打算value存。而且if(x) return true; else return false;的写法也很蠢。这些都是小问题,我甩出了代码中明显存在的错误:

我: 万一first是1,second是12,1和12是可以合并成121的,你这样就按112判断不能合并了
ChatGPT: 我错了,应该用判断firstType在secondType中出现的位置来确定是否可以合并。这样就可以避免上面提到的问题了。我会修改代码。

结果它给出的修改居然是:

1
2
3
 if(firstType === 1 && secondType === 2 || firstType === 2 && secondType === 1) {
        return '12';
    } else if // 下略

还没等写完就被我叫停了。不过它刚才的判断方法也给了我新的思路。部件一样不就能合并嘛,只需要给出哪些合并结果是合法的就行了。问题就转化成了

我: 怎么把数字改成各位从小到大排列,如1432改成1234,7512134368改成1123345679

我懒死,有AI用决不去百度。它给我了一段代码,直接就能用了。在它刚才写的正则匹配的判定基础上修改,比如1213436就改成1123346,匹配的就可以合并。不过没想到,接下来这个问题难住它了。

我: 原来的2048中,相等的方块即可合并。现在我写了canMerge函数,原来代码中哪些部分需要用这个函数替换?

它列举了六七处用===连接的地方,告诉我改成用canMerge。可是,整个代码中都没有这么多处判断能否合并!闹鬼的是,它列举的代码在最开始喂给它的代码里根本不存在!也许是达到它的记忆token上限忘记了?我感觉又不想。最终还是靠我人工找到两处判断了能否合并的地方,自己替换成了canMerge。

进行测试,我想要的功能基本全部实现。还差的地方一个是计分,一个是要把数字显示成对应的汉字。原本的2048计分是加上合并出的方块的值。现在合并出的值不能直接反应难度,2的值的位数次幂才是原来的分数记法。

我: value为整数,如何知道它有几位数?
ChatGPT: 可以使用JavaScript中的内置函数toString()将value转换为字符串,然后计算字符串长度,即可得到value有几位数:var valueLength = value.toString().length;
我: 求2的这个长度次幂怎么算
ChatGPT: 2的n次幂可以使用 Math.pow(2, n) 来计算.

计分也改好了,接下来只需要把数字显示成对应的汉字,再补一下字体调一下样式,这就算完工了。

我: 现在我要更改数字的显示,比如1显示为啊,2显示为啦,12显示为去,121343显示为你,应该怎么做

它又告诉我给Tile加属性……可以有没有一种可能就是同样的数字就是会显示同样的汉字?好在它同时给出,也可以在渲染时直接打印值。我让它帮我写了这个把值转换成汉字的函数,就是一个简单的switch,不过我是真的不懂JavaScript语法。它给一个样子我就能照猫画虎了。

现在我需求中的游戏完全成形了,而我还没完整地写过一行代码。太神奇了!

我进行了简单的测试,发现很难。仔细想想这个游戏的话,前半段的目标是拼成“⿱⿲幺言幺⿲长马长”,接下来才是给“⿱⿲幺言幺⿲长马长”依次加月字旁、立刀旁、穴字头、心字底、走之。所以我打算为前后两部分设置不同的概率。当然,我不会自己出手。

我: 帮我写一个返回当前网格中最大数值格子的数值的函数

它写出来了个Grid.prototype.getMaxValue,当然也是直接粘贴进去就能用。if我也懒得自己写,于是

我: 帮我把addRandomTile改成先getMaxValue到最大值,若最大值小于112334,则不会产生方块5-9,最大值大于等于112334时1-9都会产生

它把if也帮我写好了。

剩下的是一点我自己能做的工作了。UI方面,与计分类似,用数字的位数当指数求2的幂,原版2048的样式直接就能用。字体我选择了以LINE Seed的ExtraBold字重为底板来制作,很快也拼好了。因为是日文字体嘛,懒得拼简化字部件所以偷懒把“马”“长”等都换成了“馬”“長”,“𰻝”也换成了繁体的“𰻞”。

真可惜,怎么AI不能帮我拼字体呢?

接下来就是发布了。可是我懒啊。

我: 谢谢你,我已经完成了这个新型2048的开发,UI界面之类的也全都写好了。我将一次性commit以上所有工作,请帮我用约定式提交来写本次提交的commit message

懒死我得了。总之结论就是,ChatGPT太强了,真的很适合我这种啥也不会的懒狗。