Python crea juegos de 2048 con solo 8 líneas de código

Recientemente, vi que alguien escribió 2048 en lenguaje C con 418B. Quería probar la capacidad del lenguaje py, así que usé 890B para completarlo.

Este es solo mi límite actual, no hay mucho para ingresar el texto, el código más simple está al final

Aquí está la imagen del efecto, que es cambiar el valor de píxel de 16 puntos continuamente y luego imprimirlo

La clave es cómo reducir la cantidad de código.

El lenguaje py no es como el lenguaje C, donde se pueden escribir varias líneas de código en una línea. py tiene requisitos estrictos de sangría y bifurcación.

Entonces, si desea reducir la cantidad de líneas, una idea factible es escribir una línea de cadenas, usar formato para reemplazar la línea/pestaña y luego ejecutar

Si desea reducir la memoria, es decir, reducir el texto, los nombres de las variables deben ser todos abcd, las declaraciones condicionales son todas de una sola línea si no, y la asignación se puede escribir en una sola línea.

A continuación, entraremos un poco en la parte principal del juego, se me olvidó decir que no hay importación en todo el proceso.

Puedes ver 36 líneas de código, la idea de 2048 es

Si la dirección es hacia arriba:

A partir de la segunda fila, la segunda fila se mueve a la primera fila (o agrega)

Luego está la tercera fila, la tercera se mueve (o agrega) a la segunda fila, y luego se mueve o agrega a la primera fila

Luego, la cuarta línea, la cuarta línea se mueve (o agrega) a la tercera línea, a 2, a 1

Si la dirección es hacia abajo, es la 3.ª fila, la 2.ª fila y la 1.ª fila.

Si es izquierda o derecha, primero transponga el sistema de coordenadas, cambie de horizontal a vertical, de vertical a horizontal y luego vuelva a transponer después de la transformación

Lo anterior es la parte principal, y hay algunos detalles.Por ejemplo, si se realiza un movimiento, se generarán aleatoriamente 2 o 4 a partir de las coordenadas vacías restantes después del movimiento. Si no hay movimiento, no se generará nuevamente, puede pensarlo de la siguiente manera

Así, definitivamente no quiero ir hacia arriba y hacia la derecha, porque el gran número en la esquina inferior izquierda puede ser peligroso y no puedo volver atrás, pero de hecho, 2048 no puede ir hacia la izquierda y hacia abajo en orden. para aumentar (experiencia de juego), es decir, si la posición no cambia por completo, entonces no se generarán nuevas. Esta función se ha implementado en dos líneas de código.

Además, la síntesis de bloques, los recién sintetizados no pueden seguir siendo sintetizados, los lejanos deben sintetizarse primero, y luego los cercanos

Por ejemplo, si desliza 4440 hacia la izquierda en una línea, será 8400 en lugar de 4800

Deslizar 4444 a la izquierda es 8800 en lugar de 16 000. Este lugar no ha sido agregado debido a la cantidad de código,

analizar código,

Estas son las primeras líneas, la primera es range(4), es obvio que range(4) se usará muchas veces más tarde, así que reemplace

w es 16 puntos 0

Cambiar un punto, sino no sale

定义的这个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

Supongo que te gusta

Origin blog.csdn.net/m0_52285505/article/details/128587266
Recomendado
Clasificación