Python makes 2048 games with only 8 lines of code

Recently, I saw that someone wrote 2048 in C language with 418B. I wanted to try the ability of py language, so I used 890B to complete it.

This is just my current limit, not much to enter the text, the simplest code is at the end

Here is the effect picture, which is to change the pixel value of 16 points continuously, and then print it out

The key is how to reduce the amount of code

The py language is not like the C language where multiple lines of code can be written on one line. py has strict indentation and branching requirements

So if you want to reduce the number of lines, a feasible idea is to write a line of strings, use format to replace the line/tab, and then exec

If you want to reduce the memory, that is, reduce the text, the variable names must be all abcd, the conditional statements are all single-line if else, and the assignment can be written in one line.

Next, we will enter the main part of the game a little bit; I forgot to say that there is no import in the whole process.

You can see 36 lines of code, the idea of ​​2048 is

If the direction is up:

Starting from the second row, the second row moves to the first row (or adds)

Then there is the third row, the third moves (or adds) to the second row, and then moves or adds to the first row

Then the fourth line, the 4th line moves (or adds) to the 3rd line, to 2, to 1

If the direction is down, it is the 3rd row, the 2nd row, and the 1st row

If it is left or right, first transpose the coordinate system, change horizontally to vertically, vertically to horizontally, and then transpose back after transformation

The above is the main part, and there are some details. For example, if a move is made, 2 or 4 will be randomly generated from the remaining empty coordinates after the move. If there is no movement, it will not be newly generated, you can think about it as follows

Like this, I definitely don’t want to go up and right, because the big number in the lower left corner may be dangerous and I can’t go back, but in fact, 2048 is not allowed to go left and down in order to increase (game experience), that is, if the position is completely unchanged , then no new ones will be generated. This function has been implemented in two lines of code

In addition, the synthesis of blocks, the newly synthesized ones cannot continue to be synthesized, the far ones must be synthesized first, and then the near ones

For example, if you swipe 4440 to the left on a line, it will be 8400 instead of 4800

Swiping 4444 to the left is 8800 instead of 16 000. This place has not been added due to the amount of code,

analyze code,

This is the first few lines, the first one is range(4), it is obvious that range(4) will be used many times later, so replace

w is 16 points 0

Change a point, otherwise it won’t come out

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

Guess you like

Origin blog.csdn.net/m0_52285505/article/details/128587266