Python はわずか 8 行のコードで 2048 個のゲームを作成します

最近、C言語で2048を418Bで書いている人を見かけたので、py言語の能力を試してみたかったので、890Bで完成させました。

これは私の現在の制限です。テキストを入力することはあまりありません。最も単純なコードは最後にあります

16点の画素値を連続的に変化させてプリントアウトしたエフェクト画像です。

いかにコード量を減らすかがカギ

py 言語は、1 行に複数行のコードを記述できる C 言語とは異なり、厳密なインデントと分岐の要件があります。

したがって、行数を減らしたい場合は、実行可能なアイデアは、文字列の行を記述し、format を使用して行/タブを置き換えてから、exec を実行することです。

メモリを減らしたい場合、つまりテキストを減らしたい場合は、変数名はすべて abcd にする必要があり、条件ステートメントはすべて 1 行 if else であり、代入は 1 行で記述できます。

次に、ゲームの本編に少し入りますが、プロセス全体にインポートがないことを忘れていました。

36行のコードを見ることができます.2048のアイデアは

方向が上である場合:

2 行目から開始し、2 行目は 1 行目に移動 (または追加)

次に 3 番目の行があり、3 番目は 2 番目の行に移動 (または追加) し、次に最初の行に移動または追加します。

次に4行目、4行目は3行目、2行目、1行目に移動(または追加)

方向が下なら3列目、2列目、1列目

左または右の場合は、まず座標系を転置し、水平を垂直に、垂直を水平に変更し、変換後に転置を戻します。

以上が大まかな部分で、細かいところもありますが、例えば、わざを行うと、わざを行った後に残った空き座標からランダムで2個か4個が生成されます。動きがなければ新たに生成されるわけではなく、次のように考えることができます

このように、左下の大きな数字は危険で戻れないかもしれないので、絶対に上下に行きたくないのですが、実は2048は順番に左右に行ってはいけません(ゲーム体験) を増やす, つまり, 位置が完全に変更されていない場合, 新しいものは生成されません. この関数は 2 行のコードで実装されています.

また、ブロックの合成は、新たに合成したものを続けて合成することはできず、先に遠いものを合成してから、近いものを合成する必要があります。

たとえば、4440 を左にスワイプすると、4800 ではなく 8400 になります。

4444 を左にスワイプすると、16 000 ではなく 8800 になります。この場所はコードの量のために追加されていませんが、

コードを分析し、

これは最初の数行です。最初の行は range(4) です。range(4) は後で何度も使用されることは明らかなので、置き換えてください。

wは16点 0

ポイントを変えないと出てこない

定义的这个d()函数是xorshift函数,就是生成随机数的,感兴趣的可以查查xorshift算法,我不懂所以直接抄的代码,W每次都是一个随机的很大的int(每次调用这个函数W随机,不同,但是W出现的顺序是相同的,也就是说你每次运行这个程序,W序列是固定的,所以不同的地方在于传入的参数,是允许生成点的列表,也就是现在16个点中为0的点)

这里是上面说的核心部分,o是转置坐标系,s是用来检测是否变化的,也就是上面提到的不允许生成新的,当下面有方块移动或者合成是s改为1,函数最后用s判定是否生成新点,如果整个坐标系中,经过了变换之后还是占满格子(其实就是既没合成也没转移而且满了,那就gameover了,实际上呢,要四个方向都gameover才是over了,你只用了单一一个方向,所以其实我压根没有成功/失败的判定,你自己玩玩着玩着发现不会变了就知道了)

n是目前的坐标系,上下就是w,左右就是转置。记住这行代码(n=w if r ……),这里用到了单行条件语句

x,y,z就是,x是上面提到的234行或者321行,y:如果上,那么在第2行要运行换1次,在第3行要两次,在第4行要3次,还有后面的-1,自己慢慢想把。反正这样就能把上下合并成一个for x了,左右也是

条件语句a-b:这种形式就是说a-b!=0,也就是a!=b,看看是不是少了一个字(哈哈,呜呜,难受,夹缝生存)

for j in range(4): 假如是上,那每一行有4个吧,p,q就是近的和远的数,远的为0,就把近的移过去,近的变成0,远的近的一样,就把两个加起来放到远的,近的为0

下面那个u=set()也是精华,说白了,找到16个点中的0。一般都是新建空列表,两层for 循环(坐标系本身是两层,w也是两层,然后条件判断一下),我这里十分精简了。

首先是列表里面的for循环,这个很基础了,单行的if else不规范,但是简洁。如果那个点是0就加上他的坐标,否则加上0, 这样新的列表就是位置个数0和一些坐标

怎么去掉0呢,又不知道个数又不知道是否存在,pop要索引,remove只删除一个,del更垃圾

所以先转为集合,集合用diacard(没有这个元素不报错),集合.remove没有该元素就报错了

然后转回来为列表,现在就3行代码得到了为0的点,也就是允许生成新点(2&4)的坐标,然后放入之前定义的随机函数里生出来,f很明显是0或1,也就是你生成的是2还是4

核心部分完了,最后加个while循环获取输入即可

小细节又来了,怎么打印呢用for循环?怎么处理空格呢,1位数2位数3位数4位数呢

这里有个tip很多地方可以用,("0"+str(i))[-2::] 也就是1变为01, 2变为02,10是10,43是43,就整齐了

所以这里转为4个字符长度,细节又来了,用join打印不仅更快而且省代码(比for循环打印)

最后,用上前面说的format即可

附上完整代码如下:

A,B="\n","\t"
C='b=(0,1,2,3){0}w=[[0 for i in b] for j in b]{0}w[2][2]=2{0}X,Y,Z,W=123456789,362436069,521288629,88675123{0}def d(r):{1}global X,Y,Z,W{1}t,X,Y,Z=X^(X<<11),Y,Z,W{1}W=W^(W>>19)^t^(t>>8){1}return r[W%len(r)],W%2{0}def e(r):{1}global w{1}o,s,=[[w[i][j] for i in b] for j in b],0{1}n=w if r in "ws" else o{1}x,y,z=([1,2,3],0,-1) if r in "aw" else ([2,1,0],3,1){1}for i in x:{2}while i-y:{3}for j in b:{4}p,q=n[i][j],n[i+z][j]{4}if p and (q==0 or q==p):{5}n[i+z][j]=p if q==0 else p+q{5}n[i][j]=0{5}s=1{3}i+=z{1}u=set([(x,y) if n[x][y]==0 else 0 for x in b for y in b]){1}u.discard(0){1}u,c=list(u),len(u){1}if c and s:{2}e,f = d(u){2}n[e[0]][e[1]] = 2*f+2{1}if r in "da":{2}w=[[n[i][j] for i in b] for j in b]'.format(*[A+D*B for D in range(6)])
exec(C)
while 1:
    e(input("?"))
    for i in w:
        v=[(B+str(j))[-4::] for j in i]
        print("".join(v),end=A+A)

在多说一点,格式化字符也有说法

1最开始是f“{}”型格式化,"\n"、"\t"都是4个字符,换成A,B就简化了

2有的缩进是5缩进,连续5个{B}

3上面的5个{B}改为{5*B}

4{A}{B}改为{A+B}

5发现还是format好用,前面的A+B,A+2*B,A+3*B直接用一个数字即可

6format可以用列表作为参数,加上*号即可

个人愚见,欢迎大家指正以及讨论

对了把上面的C打印出来就是源代码了,exec里不允许有while,所以下面自己添加,

还有直接打印出来的制表符格式不对,不是python标准缩进,总之会报错,自己改改缩进就行

(明显能看出来缩进很宽)而且很少呢,840B

おすすめ

転載: blog.csdn.net/m0_52285505/article/details/128587266