用python写2048_用python写一个2048游戏

原标题:用python写一个2048游戏

大家好,欢迎来到Crossin的编程教室!

《2048》是一个几年前曾经火爆一时的小游戏(查了一下,竟然是将近7年前上线的)。今天我们就用Python来仿制一个2048小游戏吧。废话不多说,让我们愉快地开始吧~

公众号内回复‘game23’获取。

Python版本:3.6.4

相关模块:

pygame模块;

以及一些Python自带的模块。

安装Python并添加到环境变量,pip安装需要的相关模块即可。

注意需要下载代码文件夹中的所有文件,并保持原有目录结构。

在代码所在目录打开CMD,运行如下命令即可:

pythonGame23.py

效果如下:

不瞒大家说,我以前还真没玩过2048这个小游戏。于是找了个网页版的2048小游戏先体验了一下:

https: //newdoku.com/zh/2048.php

感觉玩法还是挺简单的,无非就是:

"使用方向键移动方块,两个数字相同的方块撞在一起后,将会合并为一个数字是原来两倍的新方块。游戏的时候尽可能多地合并这些数字方块就行了。"

大概了解了游戏规则之后,我们就可以开始写这个游戏啦~

首先,进行一下游戏初始化操作并播放一首自己喜欢的游戏背景音乐:

# 游戏初始化pygame.initscreen = pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.set_caption('2048')# 播放背景音乐pygame.mixer.music.load(cfg.BGMPATH)pygame.mixer.music.play(-1, 30)

接着,我们来定义一个2048游戏类,里面主要负责实现2048的各种游戏规则:

'''2048游戏'''classGame2048(object):def__init__(self, matrix_size= ( 4, 4), max_score_filepath=None, **kwargs):# matrix_size: (num_rows, num_cols)self.matrix_size = matrix_size# 游戏最高分保存路径self.max_score_filepath = max_score_filepath# 初始化self.initialize

具体而言,我们先用一个二维的列表来保存当前的游戏状态:

self.game_matrix = [[ 'null'for_inrange( self.matrix_size[ 1])] for_inrange( self.matrix_size[ 0])]

其中 null表示当前的块里没有数字。否则,对应的位置则用当前的数字表示。很显然地,2048小游戏的当前游戏状态是可以用一个4*4的列表表示的:

游戏一开始,我们需要在这个二维列表里随机地选择两个位置生成数字(即2或者4):

'''在新的位置随机生成数字'''defrandomGenerateNumber(self):empty_pos = []fori inrange(self.matrix_size[ 0]):forj inrange(self.matrix_size[ 1]):ifself.game_matrix[i][j] == 'null': empty_pos.append([i, j])i, j = random.choice(empty_pos)self.game_matrix[i][j] = 2ifrandom.random > 0.1else4

self.randomGenerateNumberself.randomGenerateNumber

然后,当玩家按下方向键(↑↓←→)时,这个二维列表要根据玩家的操作指令进行更新,主要分为两个部分:

移动所有的数字块并进行必要的合并和记分; 随机地在一个还没有数字的位置上生成一个数字。

具体而言,代码实现如下:

'''更新游戏状态'''defupdate( self):game_matrix_before = copy.deepcopy( self.game_matrix)self.moveifgame_matrix_before != self. game_matrix:self.randomGenerateNumber

其中,移动所有的数字并进行必要的合并的代码实现如下:

'''根据指定的方向, 移动所有数字块'''def move(self):# 提取非空数字def extract(array):array_new = []for item in array:if item != 'null': array_new.append(item)return array_new# 合并非空数字def merge( array):score = 0iflen( array) < 2: returnarray, scorefori inrange( len( array) -1):ifarray[i] == 'null':breakifarray[i] == array[i+ 1]:array[i] *= 2array.pop(i+ 1)array.append( 'null')score += array[i]returnextract( array), score# 不需要移动的话直接returnifself.move_direction isNone: return# 向上ifself.move_direction == 'up':forj inrange(self.matrix_size[ 1]):col= []fori inrange(self.matrix_size[ 0]):col.append(self.game_matrix[i][j])col= extract( col)col.reversecol, score = merge( col)self.score += scorecol.reversecol= col+ [ 'null',] * (self.matrix_size[ 0] - len( col))fori inrange(self.matrix_size[ 0]):self.game_matrix[i][j] = col[i]# 向下elif self.move_direction == 'down':forj inrange(self.matrix_size[ 1]):col= []fori inrange(self.matrix_size[ 0]):col.append(self.game_matrix[i][j])col= extract( col)col, score = merge( col)self.score += scorecol= [ 'null',] * (self.matrix_size[ 0] - len( col)) + colfori inrange(self.matrix_size[ 0]):self.game_matrix[i][j] = col[i]# 向左elif self.move_direction == 'left':foridx, rowinenumerate(copy.deepcopy(self.game_matrix)):row= extract( row)row.reverserow, score = merge( row)self.score += scorerow.reverserow= row+ [ 'null',] * (self.matrix_size[ 1] - len( row))self.game_matrix[idx] = row# 向右elif self.move_direction == 'right':foridx, rowinenumerate(copy.deepcopy(self.game_matrix)):row= extract( row)row, score = merge( row)self.score += scorerow= [ 'null',] * (self.matrix_size[ 1] - len( row)) + rowself.game_matrix[idx] = rowself.move_direction = None

懒得动脑子了(反正就4*4那么大T_T),所以直接遍历了这个二维列表以实现我们想要的所有操作了。最后,我们再写个函数以根据当前的游戏状态来判断游戏是否结束就ok啦:

'''游戏是否结束'''@propertydef isgameover( self):fori in range( self.matrix_size[ 0]):forj in range( self.matrix_size[ 1]):ifself.game_matrix[i][j] == 'null': returnFalseif(i == self.matrix_size[ 0] - 1) and(j == self.matrix_size[ 1] - 1):continueelif (i == self.matrix_size[ 0] - 1):if( self.game_matrix[i][j] == self.game_matrix[i][j+ 1]):returnFalseelif (j == self.matrix_size[ 1] - 1):if( self.game_matrix[i][j] == self.game_matrix[i+ 1][j]):returnFalseelse:if( self.game_matrix[i][j] == self.game_matrix[i+ 1][j]) or( self.game_matrix[i][j] == self.game_matrix[i][j+ 1]):returnFalsereturnTrue

其实很简单,如果二维列表被数字填满,且数字不能再进行合并的话,这局游戏就结束了,否则,游戏就没有结束。

定义完2048游戏类,我们的游戏基本上算是写完了。只需要在游戏主循环里根据用户操作来更新当前的游戏状态并将游戏里所有必要的元素显示在屏幕上就ok啦:

# 游戏主循环clock = pygame.time.Clockis_running = Truewhileis_running:screen.fill(pygame.Color(cfg.BG_COLOR))# --按键检测foreventinpygame. event. get:ifevent.type == pygame.QUIT:pygame.quitsys.exitelif event.type == pygame.KEYDOWN:ifevent.key in[pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT]:game_2048.setDirection({pygame.K_UP: 'up', pygame.K_DOWN: 'down', pygame.K_LEFT: 'left', pygame.K_RIGHT: 'right'}[ event.key])# --更新游戏状态game_2048.updateifgame_2048.isgameover:game_2048.saveMaxScoreis_running = False# --将必要的游戏元素画到屏幕上drawGameMatrix(screen, game_2048.game_matrix, cfg)start_x, start_y = drawScore(screen, game_2048.score, game_2048.max_score, cfg)drawGameIntro(screen, start_x, start_y, cfg)# --屏幕更新pygame.display.updateclock.tick(cfg.FPS)returnendInterface(screen, cfg)

最后的效果大概是这样的:

大功告成,完整源代码详见相关文件~

公众号内回复‘game23’获取。(需要下载文件夹中的所有文件)

作者:Charles未晞

来源:Charles的皮卡丘

爆款游戏《贪吃蛇大作战》的Python实现 返回搜狐,查看更多

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值