python二维游戏编程 最强大脑游戏_用Python 写游戏之 2048

2048这个游戏相信大家都不陌生吧。

需要控制所有方块向上下左右的某一方向运动,方向上两个相同数字合并会相加,每次移动后在空白处生成一个2或者4,最终得到一个“2048”的方块就算胜利了。

虽然简单但却虐心,今天我们就来分析这个游戏的算法原理,并用python把这个游戏写出来。游戏分析的思路就是给游戏来一个二向箔,降维打击,如何做,可以往下看。

首先把游戏4*4的方格,称之为棋盘,然后忽略棋盘的背景和颜色,使之变成4*4的田字格,田字格里是对应的数字,空白的方格用0填充。

图变成了一个4*4的方格,接下来去除方格,把每一行提取出来写到python的列表里,比如第一行变成 [2, 0, 2, 0], 那么这个4*4的方格,就变成了一个4*4的二维矩阵。

抽象成python的数据格式之后,我们看数字移动和数字加减的操作。以向左移动为例,移动的结果,第一行会变成[4, 0, 0, 0 ], 第三行会变成[8, 0, 0, 0],即

可以想象每一行计算的方法是一致的,只要搞定了一行数字的移动算法,那么整体4行就是把这个算法执行4遍即可。所以我们就完成了初步的降维,把4*4的计算,变成了4*1的计算。

接下来以第一行的数字的移动为例,介绍数字该怎么移动。

还看移动之前该矩阵的第一行 [2, 0, 2, 0], 向左移动时,需要把不为零的数字,一起向左移动,第一位的2不需要移动,第二位是0,不看,第三位的2,需要往左一位。那么我们换个思路,2向左移动,是不是可以看成是第二位的0向后移动,如果我们把第二位的0先删掉,[2, 0, 2, 0] 变成 [2, 2, 0], 然后再把0在最后添加进去,[2, 2, 0]变成[2, 2, 0, 0],这样2就向左移动了,神奇不神奇?

那完成了移动,怎么完成相同的数字相加呢?

其实只要从行的第一位开始,比较它和它后边的那一位,如果一样,就把它乘以2,然后把它后边的那一位删掉,最后在行的末尾添加一个0,保证矩阵的shape一直是 4*4。

ok,到这里完成了一行的向左移并相加的算法,那么四行的算法是一致的,也就完成了整个4*4矩阵左移并相加的操作。

那么问题来了,向右移该怎么做呢?

其实右移和左移的操作很相似,只在行的方位上移动数字,行与行之间没有什么直接操作,那么在右移时,先把每一行逆序一下,也就是 [2, 0, 2, 0]变成 [0, 2, 0, 2], 再做左移的操作,完成之后,把结果再逆序一下,是不是就ok了呢?

再问你一遍,神奇不神奇?

更神奇的还在后边呢,目前完成了左移和右移的操作,那么上移和下移呢?接下来我们要给这个游戏来第二次降维打击。

这里要用到一个我们学过的线代的知识,矩阵的转置,行转列,列转行。

细心观察之后,你会发现,原本矩阵数字上移的操作,经过转置之后就变成了左移的操作。又可以用我们之前的算法了。(鼓掌)

那么上移的操作就变成了 转置-->左移-->再转置。

那么下移呢,聪明的你肯定已经猜出来了。

没错下移就是 转置-->右移-->再转置。

ok,至此,2048游戏核心逻辑,分析完毕,来个总结:

1. 以左移为基础,把4行的操作看成1行的操作。

2. 左移的操作,先把0全部移到行的末尾

3. 然后从行第一位开始,判断与后一位是否相等且不等0,若相等该位乘以2,删除后一位,末尾添加0

4. 右移操作是 行逆序--左移--再逆序

5. 上移操作是 矩阵转置--左移--再转置

6. 下移操作是 矩阵转置--右移--再转置

上代码:

class AlgorithmLogic:

def __init__(self, matrix_shape=(4, 4)):

self.matrix = [[0 for i in range(matrix_shape[0])]

for i in range(matrix_shape[1])]

self.generate_new_num()

self.generate_new_num()

def zero_to_end(self, row):

# 倒着遍历

for i in range(len(row) - 1, -1, -1):

if row[i] == 0:

row.pop(i)

row.append(0)

def merge(self, row):

# 移动并合并

self.zero_to_end(row)

for i in range(len(row) - 1):

if row[i] == 0:

break

if row[i] == row[i + 1]:

row[i] *= 2

row.pop(i + 1)

row.append(0)

def left(self):

for row in self.matrix:

self.merge(row)

def right(self):

for row in self.matrix:

row.reverse()

self.merge(row)

row.reverse()

def matrix_transpose(self):

# 矩阵转置

for col_index in range(1, len(self.matrix)):

for row_index in range(col_index, len(self.matrix)):

self.matrix[row_index][col_index - 1], self.matrix[

col_index - 1][row_index] = self.matrix[

col_index -

1][row_index], self.matrix[row_index][col_index - 1]

def up(self):

self.matrix_transpose()

self.left()

self.matrix_transpose()

def down(self):

self.matrix_transpose()

self.right()

self.matrix_transpose()

def move(self, direction):

dir_dict = {

'left': self.left,

'right': self.right,

'up': self.up,

'down': self.down

}

func = dir_dict.get(direction)

if func:

func()

def get_empty_position(self):

empty_position = []

for row_index in range(len(self.matrix)):

for col_index in range(len(self.matrix[row_index])):

if self.matrix[row_index][col_index] == 0:

empty_position.append((row_index, col_index))

return empty_position

def generate_new_num(self):

self.empty_position = self.get_empty_position()

if not self.empty_position:

return False

row_index, col_index = random.choice(self.empty_position)

self.matrix[row_index][col_index] = 4 if random.randint(1,

10) == 1 else 2

self.empty_position.remove((row_index, col_index))

return True

def is_game_win(self):

for r in self.matrix:

if 2048 in r:

return True

return False

def is_game_over(self):

for r in range(len(self.matrix)):

for c in range(len(self.matrix[r]) - 1):

# 判断是否还可以走

if self.empty_position:

return False

# 判断是否还可以相加

if self.matrix[r][c] == self.matrix[r][

c + 1] or self.matrix[c][r] == self.matrix[c + 1][r]:

return False

return True

这里展示算法的主要逻辑代码

完整的代码移至打代码的shy--python写游戏系列​github.com

初来乍到,请多关照。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值