找回密码
 会员注册
查看: 29|回复: 0

python|闲谈2048小游戏和数组的旋转及翻转和转置

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
69864
发表于 2024-9-10 08:09:44 | 显示全部楼层 |阅读模式
目录2048生成数组n阶方阵方阵旋转顺时针旋转逆时针旋转mxn矩阵矩阵旋转测试代码测试结果翻转和转置2048《2048》是一款比较流行​的数字游戏​,最早于2014年3月20日发行。原版2048由GabrieleCirulli首先在GitHub上发布,后被移植到各个平台,并且衍生出不计其数的版本。但在网上看到,居说它也不算是原创,是基于《1024》和《小3传奇》的玩法开发而成的;还有一说,它来源于另一款游戏《Threes!》,由Asher Vollmer和Greg Wohlwend合作开发,于2014年2月6日在App Store上架。2048游戏规则很简单,游戏开始时在4x4的方格中随机出现数字2,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,相邻的相同数字在靠拢时会相加,系统也会在空白的格子里随机增加一个数字2或4。玩家要想办法在这16格范围中,不断上下左右滑动相加数字,从而凑出“2048”这个数字方块。实际上,这个游戏就是在操作一个4x4的二维数组,数组的元素只要1-11就行了,因为2的11次方就是2048。同样,相邻相同数字的累加就变成了相邻相同指数的递增1。在编写这个2048游戏前,先来谈谈4x4数组的操作,对python来说虽然也有数组,但通常会用列表来操作。以下就在IDLEshell上流水账操作:生成数组16个数字的列表推导式:>>>[iforiinrange(16)][0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]用*解包更pythonic:>>>[*range(16)][0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]分割成4x4二维列表:>>>[[*range(16)][i*4:i*4+4]foriinrange(4)][[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]只是数列如此写法可能更好:>>>[[*range(i*4,i*4+4)]foriinrange(4)][[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]全0列表:>>>[[0]*4for_inrange(4)][[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]n阶方阵从4阶方阵扩展到n阶:>>>matrix=lambdan:[[*range(i*n,i*n+n)]foriinrange(n)]>>>matrix(4)[[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]>>>matrix(5)[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14],[15,16,17,18,19],[20,21,22,23,24]]>>>matrix(6)[[0,1,2,3,4,5],[6,7,8,9,10,11],[12,13,14,15,16,17],[18,19,20,21,22,23],[24,25,26,27,28,29],[30,31,32,33,34,35]]随机生成数字1或2,比例为3:1:>>>fromrandomimportsampleasrnd>>>rnd([1,1,1,2],1)[1]>>>rnd([1,1,1,2],1)[2]>>>rnd([1,1,1,2],1)[2]>>>rnd([1,1,1,2],1)随机产生1或者2个“1”,比例为2:1:>>>fromrandomimportsampleasrnd>>>x=4>>>rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0]>>>rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0]>>>rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0]x=5rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0]rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1]rnd([0]*(x*x-2)+rnd([0,1,1],2),x*x)[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0]方阵旋转numpy有现成的函数rot90(),表示顺时针旋转数组90度。>>>importnumpyasnp>>>np.array(range(16))array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15])>>>np.array([[*range(i*4,i*4+4)]foriinrange(4)])array([[0, 1, 2, 3],    [4, 5, 6, 7],    [8, 9,10,11],    [12,13,14,15]])>>>array=np.array([[*range(i*4,i*4+4)]foriinrange(4)])逆时针旋转,参数k为正数:>>>np.rot90(array)array([[3, 7,11,15],    [2, 6,10,14],    [1, 5, 9,13],    [0, 4, 8,12]])>>>np.rot90(array,k=2)array([[15,14,13,12],    [11,10, 9, 8],    [7, 6, 5, 4],    [3, 2, 1, 0]])>>>np.rot90(array,k=3)array([[12, 8, 4, 0],    [13, 9, 5, 1],    [14,10, 6, 2],    [15,11, 7, 3]])顺时针旋转,参数k为负数:>>>np.rot90(array,k=-1)array([[12, 8, 4, 0],    [13, 9, 5, 1],    [14,10, 6, 2],    [15,11, 7, 3]])>>>np.rot90(array,k=-2)array([[15,14,13,12],    [11,10, 9, 8],    [7, 6, 5, 4],    [3, 2, 1, 0]])>>>np.rot90(array,k=-3)array([[3, 7,11,15],    [2, 6,10,14],    [1, 5, 9,13],    [0, 4, 8,12]])不使用numpy,只用列表推导式也能实现旋转:顺时针旋转>>>matrix=lambdan:[[*range(i*n,i*n+n)]foriinrange(n)]>>>mat4=matrix(4)>>>mat4[[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]>>>[[mat[len(mat[0])-j-1][i]forjinrange(len(mat[0]))]foriinrange(len(mat))][[12,8,4,0],[13,9,5,1],[14,10,6,2],[15,11,7,3]]写一个模拟np.array的__repr__方法来检测旋转效果:classList():#仅支持二维数组的展示def__init__(self,lst):self.x=lstdef__repr__(self):n=len(str(max(sum(self.x,[]))))res=[]formatinself.x:res.append(','.join(f'{x:>{n}}'forxinmat))return'],\n\t['.join(res).join(['Array([[',']])'])'运行运行检测结果如下:>>>matrix=lambdan:[[*range(i*n,i*n+n)]foriinrange(n)]>>>rotate=lambdam:[[m[len(m)-j-1][i]forjinrange(len(m))]foriinrange(len(m[0]))]>>>mat4=matrix(4)>>>List(mat4)Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])>>>List(rotate(mat4))Array([[12, 8, 4, 0],   [13, 9, 5, 1],   [14,10, 6, 2],   [15,11, 7, 3]])>>>List(rotate(rotate(mat4)))Array([[15,14,13,12],   [11,10, 9, 8],   [7, 6, 5, 4],   [3, 2, 1, 0]])>>>List(rotate(rotate(rotate(mat4))))Array([[3, 7,11,15],   [2, 6,10,14],   [1, 5, 9,13],   [0, 4, 8,12]])>>>List(rotate(rotate(rotate(rotate(mat4)))))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])结果符合预期,旋转4次恢复原样;同样更高阶方阵也符合:>>>List(matrix(5))Array([[0, 1, 2, 3, 4],   [5, 6, 7, 8, 9],   [10,11,12,13,14],   [15,16,17,18,19],   [20,21,22,23,24]])>>>List(rotate(matrix(5)))Array([[20,15,10, 5, 0],   [21,16,11, 6, 1],   [22,17,12, 7, 2],   [23,18,13, 8, 3],   [24,19,14, 9, 4]])逆时针旋转>>>matrix=lambdan:[[*range(i*n,i*n+n)]foriinrange(n)]>>>rotate2=lambdam:[[m[j][len(m[0])-i-1]forjinrange(len(m))]foriinrange(len(m[0]))]>>>List(rotate2(matrix(4)))Array([[3, 7,11,15],   [2, 6,10,14],   [1, 5, 9,13],   [0, 4, 8,12]])>>>List(rotate2(rotate2(matrix(4))))Array([[15,14,13,12],   [11,10, 9, 8],   [7, 6, 5, 4],   [3, 2, 1, 0]])>>>List(rotate2(rotate2(rotate2(matrix(4)))))Array([[12, 8, 4, 0],   [13, 9, 5, 1],   [14,10, 6, 2],   [15,11, 7, 3]])>>>List(rotate2(rotate2(rotate2(rotate2(matrix(4))))))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])>>>List(rotate2(matrix(5)))Array([[4, 9,14,19,24],   [3, 8,13,18,23],   [2, 7,12,17,22],   [1, 6,11,16,21],   [0, 5,10,15,20]])>>>List(rotate2(rotate2(matrix(5))))Array([[24,23,22,21,20],   [19,18,17,16,15],   [14,13,12,11,10],   [9, 8, 7, 6, 5],   [4, 3, 2, 1, 0]])mxn矩阵把方阵拓展到矩阵:>>> matrix=lambdam,n:[[i*n+jforjinrange(n)]foriinrange(m)]>>>List(matrix(3,4))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11]])>>>List(matrix(5,4))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15],   [16,17,18,19]])>>>List(matrix(5,5))Array([[0, 1, 2, 3, 4],   [5, 6, 7, 8, 9],   [10,11,12,13,14],   [15,16,17,18,19],   [20,21,22,23,24]])矩阵旋转rotate顺时针旋转,rotate2逆时针旋转>>>matrix=lambdam,n:[[i*n+jforjinrange(n)]foriinrange(m)]>>>rotate=lambdam:[[m[len(m)-j-1][i]forjinrange(len(m))]foriinrange(len(m[0]))]>>>rotate2=lambdam:[[m[j][len(m[0])-i-1]forjinrange(len(m))]foriinrange(len(m[0]))]>>>List(matrix(3,4))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11]])>>>List(rotate(matrix(3,4)))Array([[8, 4, 0],   [9, 5, 1],   [10, 6, 2],   [11, 7, 3]])>>>List(rotate2(rotate2(rotate2(matrix(3,4)))))Array([[8, 4, 0],   [9, 5, 1],   [10, 6, 2],   [11, 7, 3]])>>>List(rotate(rotate(matrix(3,4))))Array([[11,10, 9, 8],   [7, 6, 5, 4],   [3, 2, 1, 0]])>>>List(rotate2(rotate2(matrix(3,4))))Array([[11,10, 9, 8],   [7, 6, 5, 4],   [3, 2, 1, 0]])>>>List(rotate(rotate(rotate(matrix(3,4)))))Array([[3, 7,11],   [2, 6,10],   [1, 5, 9],   [0, 4, 8]])>>>List(rotate2(matrix(3,4)))Array([[3, 7,11],   [2, 6,10],   [1, 5, 9],   [0, 4, 8]])>>>List(rotate(rotate(rotate(rotate(matrix(3,4))))))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11]])List(rotate2(rotate2(rotate2(rotate2(matrix(3,4))))))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11]])旋转函数还能写成如下形式,只是坐标与range参数的互调形式:>>>rotate=lambdam:[[m[j][i]forjinrange(len(m)-1,-1,-1)]foriinrange(len(m[0]))]>>>rotate2=lambdam:[[m[j][i]forjinrange(len(m))]foriinrange(len(m[0])-1,-1,-1)]lambda匿名函数虽然很简洁,但没有普通函数易懂,我们把lambda函数改成模拟np.rot90()的普通函数rotate(matrix,k=1),其中参数k为90度的倍数,正数顺时针旋转,负数则逆时针旋转:defrotate(matrix,k=1):rows=len(matrix)cols=len(matrix[0])res=[[0]*rowsfor_inrange(cols)]k%=4ifk==1:foriinrange(rows):forjinrange(cols):res[j][rows-i-1]=matrix[i][j]elifk==2:res=[[0]*colsfor_inrange(rows)]foriinrange(rows):forjinrange(cols):res[rows-i-1][cols-j-1]=matrix[i][j]elifk==3:foriinrange(rows):forjinrange(cols):res[cols-j-1][i]=matrix[i][j]else:returnmatrixreturnres'运行运行测试代码defrotate(matrix,k=1):rows=len(matrix)cols=len(matrix[0])res=[[0]*rowsfor_inrange(cols)]k%=4ifk==1:foriinrange(rows):forjinrange(cols):res[j][rows-i-1]=matrix[i][j]elifk==2:res=[[0]*colsfor_inrange(rows)]foriinrange(rows):forjinrange(cols):res[rows-i-1][cols-j-1]=matrix[i][j]elifk==3:foriinrange(rows):forjinrange(cols):res[cols-j-1][i]=matrix[i][j]else:returnmatrixreturnresdefshow(matrix):n=len(str(max(sum(matrix,[]))))res=[]formatinmatrix:res.append(','.join(f'{x:>{n}}'forxinmat))print('],\n\t['.join(res).join(['Array([[',']])']))matrix=lambdam,n:[[i*n+jforjinrange(n)]foriinrange(m)]foriinrange(-4,5):show(rotate(matrix(4,4),i))foriinrange(-4,5):show(rotate(matrix(5,3),i))'运行运行测试结果Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])Array([[12, 8, 4, 0],   [13, 9, 5, 1],   [14,10, 6, 2],   [15,11, 7, 3]])Array([[15,14,13,12],   [11,10, 9, 8],   [7, 6, 5, 4],   [3, 2, 1, 0]])Array([[3, 7,11,15],   [2, 6,10,14],   [1, 5, 9,13],   [0, 4, 8,12]])Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])Array([[12, 8, 4, 0],   [13, 9, 5, 1],   [14,10, 6, 2],   [15,11, 7, 3]])Array([[15,14,13,12],   [11,10, 9, 8],   [7, 6, 5, 4],   [3, 2, 1, 0]])Array([[3, 7,11,15],   [2, 6,10,14],   [1, 5, 9,13],   [0, 4, 8,12]])Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])Array([[0, 1, 2],   [3, 4, 5],   [6, 7, 8],   [9,10,11],   [12,13,14]])Array([[12, 9, 6, 3, 0],   [13,10, 7, 4, 1],   [14,11, 8, 5, 2]])Array([[14,13,12],   [11,10, 9],   [8, 7, 6],   [5, 4, 3],   [2, 1, 0]])Array([[2, 5, 8,11,14],   [1, 4, 7,10,13],   [0, 3, 6, 9,12]])Array([[0, 1, 2],   [3, 4, 5],   [6, 7, 8],   [9,10,11],   [12,13,14]])Array([[12, 9, 6, 3, 0],   [13,10, 7, 4, 1],   [14,11, 8, 5, 2]])Array([[14,13,12],   [11,10, 9],   [8, 7, 6],   [5, 4, 3],   [2, 1, 0]])Array([[2, 5, 8,11,14],   [1, 4, 7,10,13],   [0, 3, 6, 9,12]])Array([[0, 1, 2],   [3, 4, 5],   [6, 7, 8],   [9,10,11],   [12,13,14]])翻转和转置翻转可以是水平方向和重置方向的:>>> matrix=lambdam,n:[[i*n+jforjinrange(n)]foriinrange(m)]>>>flipH=lambdam:[[m[i][len(m[0])-j-1]forjinrange(len(m[0]))]foriinrange(len(m))]>>>flipV=lambdam:[[m[len(m)-j-1][i]foriinrange(len(m[0]))]forjinrange(len(m))]>>>List(flipH(matrix(4,4)))Array([[3, 2, 1, 0],   [7, 6, 5, 4],   [11,10, 9, 8],   [15,14,13,12]])>>>List(flipV(matrix(4,4)))Array([[12,13,14,15],   [8, 9,10,11],   [4, 5, 6, 7],   [0, 1, 2, 3]])>>>List(flipH(matrix(3,5)))Array([[4, 3, 2, 1, 0],   [9, 8, 7, 6, 5],   [14,13,12,11,10]])>>>List(flipV(matrix(3,5)))Array([[10,11,12,13,14],   [5, 6, 7, 8, 9],   [0, 1, 2, 3, 4]])>>>List(flipH(matrix(5,4)))Array([[3, 2, 1, 0],   [7, 6, 5, 4],   [11,10, 9, 8],   [15,14,13,12],   [19,18,17,16]])>>>List(flipV(matrix(5,4)))Array([[16,17,18,19],   [12,13,14,15],   [8, 9,10,11],   [4, 5, 6, 7],   [0, 1, 2, 3]])转置可以看作是翻转和旋转的组合,对方阵来说就是以对角线为轴的翻转:>>>transpose=lambdam:[[m[j][i]forjinrange(len(m))]foriinrange(len(m[0]))]>>>List(transpose(matrix(4,4)))Array([[0, 4, 8,12],   [1, 5, 9,13],   [2, 6,10,14],   [3, 7,11,15]])>>>List(transpose(transpose(matrix(4,4))))Array([[0, 1, 2, 3],   [4, 5, 6, 7],   [8, 9,10,11],   [12,13,14,15]])>>>List(rotate(matrix(4,4)))Array([[12, 8, 4, 0],   [13, 9, 5, 1],   [14,10, 6, 2],   [15,11, 7, 3]])>>>List(flipH(rotate(matrix(4,4))))Array([[0, 4, 8,12],   [1, 5, 9,13],   [2, 6,10,14],   [3, 7,11,15]])>>>List(rotate2(matrix(4,4)))Array([[3, 7,11,15],   [2, 6,10,14],   [1, 5, 9,13],   [0, 4, 8,12]])>>>List(flipV(rotate2(matrix(4,4))))Array([[0, 4, 8,12],   [1, 5, 9,13],   [2, 6,10,14],  [3, 7,11,15]])在numpy中,转置由.T属性完成>>>importnumpyasnp>>>arr=np.array(matrix(3,4))>>>arrarray([[0, 1, 2, 3],    [4, 5, 6, 7],    [8, 9,10,11]])>>>arr.Tarray([[0, 4, 8],    [1, 5, 9],    [2, 6,10],    [3, 7,11]])>>>arr=np.array(matrix(4,4))>>>arr.Tarray([[0, 4, 8,12],    [1, 5, 9,13],    [2, 6,10,14],    [3, 7,11,15]])>>>arr.T.Tarray([[0, 1, 2, 3],    [4, 5, 6, 7],    [8, 9,10,11],    [12,13,14,15]])>>>arr=np.array(matrix(5,4))>>>arr.Tarray([[0, 4, 8,12,16],    [1, 5, 9,13,17],    [2, 6,10,14,18],    [3, 7,11,15,19]])完
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-7 07:13 , Processed in 0.423144 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表