求助编写python 编写程序程序来自动玩2048游戏

Python学习第13日--2048 - 博客频道 - CSDN.NET
送故事的妖怪
那一年,我十六岁...
分类:Python
这是一个基于dos窗口的2048小游戏,本来在《python基础教程》上面有图形用户界面的编程介绍,但是因为我个人的情感原因(图形界面非编程核心),所以暂时没有使用图形界面的打算。
所以,继续练习python语法!
下面是2048的需求:
实现一个简单的dos下的2048小游戏
1、除了界面是dos窗口外,其他方面应该同窗口程序2048
2、2048游戏逻辑如下:
a、玩家可以通过键盘上下左右四个方向键来控制整体的方块坠落方向
b、数值相同的两个方块可以合并,并且合并后的值为其两个方块之和
c、在当前最大数值N(N&=8)的情况下,随即产生1-N/4之间2的正整数幂的数字作为每次移动后的补充数据
d、当当前最大数值N==2048时,游戏胜利。当16格方块在四个方向均无法移动时,游戏失败
其实2048小游戏挺简单的,我曾经使用Qt写过2048的游戏,界面风格比较朴素。
2048的的实现关键点在于数字移动时候的处理逻辑:相邻的两个相同数字的方块可以合并,空方块不产生阻隔。这个逻辑相信大家都能很容易以代码实现,但是怎样才能使代码更加简洁才是我们的重点所在
下面是我当时的设计方案:
1、使用一个整数的4*4二维列表Map来记录当前界面上的所有数值
2、Map中,0表示该处没有数字,并不作打印
3、使用os.system(“cls”)来实时刷新界面
4、创建类Game2048
5、在Game2048中的成员函数:
def init(self)
def MoveLeft(self)
def MoveRight(self)
def MoveUp(self)
def MoveDown(self)
def IsGameOver(self)
判断游戏是否结束
def GameOverSurface(self,info)
游戏结束界面
def PlayingSurface(self)
def run(self)
def CreateNewDigit(self)
产生新的数字
def GetKeyEvent(self)
获取按键信息
def GetNoneZeroSeq(self,seq)
获取列表中所有非零元素,返回非零元素列表
def Combine(self,seq,dir)
合并列表中相邻的相同元素
6、需要查阅的技术
a、python获取按键消息
查获方案:使用pyHook模块监控键盘输入
使用pythoncom模块来设置消息循环
使用win32api模块来发送程序退出消息
b、python随机数
解决方案:python 2.7自带random模块
依然是计划赶不上变化,在实际编程过程中,代码写了一半,又去修改了方案,有一种方案跟着代码走的感觉。哎,可能是自己还是有些浮躁。
我的代码总共是180行,当然其实可以压缩很多。但是为了代码的可读性以及模块化,行数就显得不重要了。
2048我已经传到CSDN了,这是下载地址:
StoryMonster
排名:千里之外
(15)(2)(1)(2)(12)(4)(1)(4)(12)Python 2048游戏实现 - 苏徽.w - 博客园
2048游戏算是一个比较完整的项目,项目中我们需要将游戏过程建模,通过有限状态机将游戏主流程模拟出来如下:
对于游戏的整体代码中,关于矩阵逆转,移动处理逻辑算法初学者可以暂时不关注,重点在于游戏主流程代码,这样可以锻炼初学者的思维,让大家更好的学习!
此外,代码中比较常用的库与类是需要初学者去积累的。
# -*- coding: utf-8 -*-
import curses
from random import randrange, choice
# generate and place new tile
from collections import defaultdict
#定义按键并将asc码转换为十进制整数
letter_codes = [ord(ch) for ch in 'WASDRQwasdrq']
#定义用户的行为
actions = ['Up', 'Left', 'Down', 'Right', 'Restart', 'Exit']
#將按键与用户行为关联 形成dict
actions_dict = dict(zip(letter_codes, actions * 2))
#阻塞+循环,直到获得用户有效输入才返回对应行为:
def get_user_action(keyboard):
char = "N"
while char not in actions_dict:
char = keyboard.getch()
return actions_dict[char]
初学者可不要在此深究
def transpose(field):
return [list(row) for row in zip(*field)]
def invert(field):
return [row[::-1] for row in field]
class GameField(object):
def __init__(self, height=4, width=4, win=2048):
self.height = height
self.width = width
self.win_value = 2048
self.score = 0
self.highscore = 0
self.reset()
def reset(self):
if self.score & self.highscore:
self.highscore = self.score
self.score = 0
#此行循环打印行和列并赋值为0 类似与9*9乘法表
self.field = [[0 for i in range(self.width)] for j in range(self.height)]
self.spawn()
self.spawn()
#代码主流程,不过感觉并不适合初学者阅读,这个地方大家可以简易的阅读
def move(self, direction):
def move_row_left(row):
def tighten(row):
# squeese non-zero elements together
new_row = [i for i in row if i != 0]
new_row += [0 for i in range(len(row) - len(new_row))]
return new_row
def merge(row):
pair = False
new_row = []
for i in range(len(row)):
new_row.append(2 * row[i])
self.score += 2 * row[i]
pair = False
if i + 1 & len(row) and row[i] == row[i + 1]:
pair = True
new_row.append(0)
new_row.append(row[i])
assert len(new_row) == len(row)
return new_row
return tighten(merge(tighten(row)))
moves = {}
moves['Left'] = lambda field: \
[move_row_left(row) for row in field]
moves['Right'] = lambda field: \
invert(moves['Left'](invert(field)))
moves['Up'] = lambda field: \
transpose(moves['Left'](transpose(field)))
moves['Down'] = lambda field: \
transpose(moves['Right'](transpose(field)))
if direction in moves:
if self.move_is_possible(direction):
self.field = moves[direction](self.field)
self.spawn()
return True
return False
def is_win(self):
return any(any(i &= self.win_value for i in row) for row in self.field)
def is_gameover(self):
return not any(self.move_is_possible(move) for move in actions)
def draw(self, screen):
help_string1 = '(W)Up (S)Down (A)Left (D)Right'
help_string2 = '
(R)Restart (Q)Exit'
gameover_string = '
GAME OVER'
win_string = '
def cast(string):
screen.addstr(string + '\n')
def draw_hor_separator():
line = '+' + ('+------' * self.width + '+')[1:]
separator = defaultdict(lambda: line)
if not hasattr(draw_hor_separator, "counter"):
draw_hor_separator.counter = 0
cast(separator[draw_hor_separator.counter])
draw_hor_separator.counter += 1
def draw_row(row):
cast(''.join('|{: ^5} '.format(num) if num & 0 else '|
' for num in row) + '|')
screen.clear()
cast('SCORE: ' + str(self.score))
if 0 != self.highscore:
cast('HGHSCORE: ' + str(self.highscore))
for row in self.field:
draw_hor_separator()
draw_row(row)
draw_hor_separator()
if self.is_win():
cast(win_string)
if self.is_gameover():
cast(gameover_string)
cast(help_string1)
cast(help_string2)
def spawn(self):
new_element = 4 if randrange(100) & 89 else 2
(i, j) = choice([(i, j) for i in range(self.width) for j in range(self.height) if self.field[i][j] == 0])
self.field[i][j] = new_element
def move_is_possible(self, direction):
def row_is_left_movable(row):
def change(i):
# true if there'll be change in i-th tile
if row[i] == 0 and row[i + 1] != 0:
return True
if row[i] != 0 and row[i + 1] == row[i]:
return True
return False
return any(change(i) for i in range(len(row) - 1))
check = {}
check['Left'] = lambda field: \
any(row_is_left_movable(row) for row in field)
check['Right'] = lambda field: \
check['Left'](invert(field))
check['Up'] = lambda field: \
check['Left'](transpose(field))
check['Down'] = lambda field: \
check['Right'](transpose(field))
if direction in check:
return check[direction](self.field)
return False
#遊戲实现的主流程思路,重点
def main(stdscr):
def init():
# 重置游戏棋盘
game_field.reset()
return 'Game'
def not_game(state):
# 画出 GameOver 或者 Win 的界面
game_field.draw(stdscr)
# 读取用户输入得到action,判断是重启游戏还是结束游戏
action = get_user_action(stdscr)
responses = defaultdict(lambda: state)
# 默认是当前状态,没有行为就会一直在当前界面循环
responses['Restart'], responses['Exit'] = 'Init', 'Exit'
# 对应不同的行为转换到不同的状态
return responses[action]
def game():
# 画出当前棋盘状态
game_field.draw(stdscr)
# 读取用户输入得到action
action = get_user_action(stdscr)
if action == 'Restart':
return 'Init'
if action == 'Exit':
return 'Exit'
if game_field.move(action):
# move successful
if game_field.is_win():
return 'Win'
if game_field.is_gameover():
return 'Gameover'
return 'Game'
state_actions = {
'Init': init,
'Win': lambda: not_game('Win'),
'Gameover': lambda: not_game('Gameover'),
'Game': game
curses.use_default_colors()
game_field = GameField(win=32)
state = 'Init'
# 状态机开始循环
while state != 'Exit':
state = state_actions[state]()
#curses 是python 对c中 curses的封装,并没有卵用
curses.wrapper(main)
阅读(...) 评论()算法(14)
问题 by&nitish712
我最近偶然发现一款叫。你需要通过上下左右方向键来移动合并值相同的方块(Title)。每一次移动之后,一个值为2或者4的新方块会随机出现在某个空位置。如果所有位置都塞满方块,并且没有值相同的方块可以合并的时候,游戏结束。游戏的目标是合并出一个值为2048的方块。
我需要遵循一套定义良好的策略来实现这个目标。所以我想到写个程序来实现。我当前的算法如下:
while(!game_over)
for each possible move:
count_no_of_merges_for_2-tiles and 4-tiles
choose the move with large number of merges
我所做的是,在任何时刻,我都尝试合并值为2或者4的方块,也就是我会尝试让值为2和4的方块越少越好。如果我尝试那么做,其它的方块会自动的合并,看起来像是个好策略。
但是当我真正使用这套算法的时候,我大概只能得到4000分,游戏就结束了。游戏的最高分应该是20000多点,远超我当前的分数。有比上面策略更好的算法吗?
最佳回答 by&ovolve
我是AI程序的作者,前面也有人提到AI程序。你可以看,或者直接阅读。
当前,这套运行在我笔记本浏览器的javascript程序能够达到90%左右的胜率,每次移动的思考时间是100毫秒。尽管不是最完美,但做得还不赖。
既然这个游戏是一个离散状态空间,信息完备的回合制游戏,类似于象棋和国际跳棋,那么我就使用了针对这些游戏的证明过的行之有效的方法。一套叫的算法,结合了。既然已经有很多信息解释了这套算法,那么我就仅谈谈我在中使用到的两个重要概念。这将会把一些人在这里表达的直觉形式化。
单调性(Monotonicity)
这个概念保证方块的值沿着上下左右方向的,要么增加,要么减少。这个概念单独地解释了一个大家提到的直觉,值较大的方块应该聚集到某一个角落。这将有助于阻止值小的方块被孤立起来,也将让面板保持良好的组织结构,使得值小的方块渐进层叠式的并逐步合并为值大的方块。
下图是一个有完美单调性格子的截屏。我通过运行eval函数被设置为忽略其它概念的算法获得,仅仅考虑单调性。
平滑性(Smoothness)
上面的概念倾向于构造值递减的结构,但如要合并,相邻的方格值必须相同。因此,平滑性衡量相邻方格值的差,并尝试减少差。
Hacker News上的一个评论者用图论给出了一个平滑性的有趣解释。来源于2048的一个优秀。
下图是个有完美单平滑性的截屏。
空闲方块(Free Tiles)
最后,有一个针对空闲格子过少的惩罚。毕竟面板过于拥挤的时候,选择受限且很快会被用完。
就是这样。扫描游戏格子,同时优化以上标准,这会产生相当好的表现。与明确硬编码的移动策略相比,这种使用通用性的方法有一个优点,这种算法可以找到有趣且难以预料的解决方案。如果你观察它运行,它经常会做出一些惊奇但有效的移动,比如突然转向一个相反的墙或者角落。
这是该方法强大能力的一个展示。我拿掉了方格值大小的限制(到2048之后还可以继续运行,下图是8次尝试中最好一次的截屏,是的,那可是一个4096外加一个2048),那意味着在同一个面板上它完成了3次困难的2048方块。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11527次
排名:千里之外
转载:46篇
(1)(17)(28)一起来写行python代码) - 推酷
一起来写行python代码)
Life is short ,you need python.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
--Bruce Eckel
我与2048的缘,不是缘于一个玩家,而是一次,一次,又一次的ACM比赛.四月份校赛初赛,第一次碰到2048,两周后决赛再次遇到2048,后来五月份的广东省赛,又出现了2048。在这三次比赛过程中,我一次2048都没玩过..全靠队友的解释,直到昨天,我突然想起写个2048吧,于是下了个2048玩了几盘,之后就开始用python来写了,心想就不写界面了,为了简洁。
我对python并不熟悉,但是我在之前的博文就提过我希望成为一个python的玩家,所以我选择了python,同时,也希望大家也可以用非常简单的代码取实现2048。
首先,如果你没有玩过2048,没关系,你只要随便在网上或电子市场一搜索肯定会有各种版本,之后玩几把就会了。
来到这里,我假设大家都玩过2048了,于是我们先分析一下怎么来写一个简单的2048?回想一下,游戏的过程是很简单的:
&&&&&&&&&&&&&
开始===&(& 进行操作(上下左右)===&矩阵移动===&数字合并===&计分& )===&退出
括号内就是游戏的进行过程了,我们退出大概就是两个:1.出现2048,胜利退出 2.无法合并同时无法出现新数(是且的关系)
懂得这个运行过程后,我们就一步步来写,整个过程也不会难,哪怕你跟我一样基本是
先看看简略图,看起来虽然真的很朴素,但是爱美的你,可以在看完我的程序后自己美化。
储存结构:
列表,其中包括二维矩阵列表,即所谓的mtr[4][4],以及栈,栈是用于退回,如果大家不想要这个功能可以直接忽略。
我们的变量定义:
declare = &←:a/h
↓: s/j ↑: w/k →: d/l ,q(uit),b(ack)&
illegal = &Illegal operation!&
noefficient = &This move has no efficient&
mtr = init()
# init the matrix
mtr_stk = []
# use step for back
scr_stk = []
稍微解释一下: declare是解释操作提示,自己喜欢怎么写就怎么写~
&&&&&&&&&&&&&&&&&&&&&&&&&&&& illegal是我们输入非正常操作提示,,可以省略
&&&&&&&&&&&&&&&&&&&&&&&&&&&& noefficient是我们往这个方向没效果,也可以省略~
&&&&&&&&&&&&&&&&&&&&&&&&&&&& score是得分,step是走了多少步,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& mtr是我们的二维方阵,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& mtr_stk,scr_stk是储存栈,用于后退功能,如果不要后退,还是可以省略~
算法实现:
&&「注:其实没有算法可言....更准确叫函数实现。」
(1).在我们这个没有界面的2048中,我们只能用制表符啦,所以我们需要一个display函数。
&这是一个非常简单的事情,跟C语言的printf基本一致, 像如下代码,基本就能绘制出一个
的表格了。
print &┌&+(&─&*5+&┬&)*3+&─&*5+&┐&
print &│%4d │%4d │%4d │%4d │&%(1,)
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4d │%4d │%4d │%4d │&%(1,)
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4d │%4d │%4d │%4d │&%(1,)
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4d │%4d │%4d │%4d │&%(1,)
print &└&+(&─&*5+&┴&)*3+&─&*5+&┘&
但是我们需要的是将固定的数字变成我们矩阵mtr的数字。
另外可以,注意到一点,数字输出的形式是固定的,表格边线,只有交叉点是不同,其他是0。而交叉点有五个,我们可以走循环(觉得麻烦可以直接忽略)
为了美观,我们
,所以我们输出时候选择的是字符串即%s,这样,我们遇到0,就可以输出' ',其他直接输出。
我们可以用python的
三目运算符号
print &%4s & %(mtr[i][j] if mtr[i][j] else ' ')
所以我们的绘制表格写成这样子:
最直接的方法!
return a if a else ' '
def display(mtr):
print &┌&+(&─&*5+&┬&)*3+&─&*5+&┐&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[0][0]),T(mtr[0][1]),T(mtr[0][2]),T(mtr[0][3]))
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[1][0]),T(mtr[1][1]),T(mtr[1][2]),T(mtr[1][3]))
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[2][0]),T(mtr[2][1]),T(mtr[2][2]),T(mtr[2][3]))
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[3][0]),T(mtr[3][1]),T(mtr[3][2]),T(mtr[3][3]))
print &└&+(&─&*5+&┴&)*3+&─&*5+&┘&
可以这样写:就是枚举交叉点情况。
def display(mtrx): #output function
a = (&┌&, &├&, &├&, &├&, &└&)
b = (&┬&, &┼&, &┼&, &┼&, &┴&)
c = (&┐&, &┤&, &┤&, &┤&, &┘&)
for i in range(4):
print a[i] + (&─& * 5 + b[i]) * 3 + (&─& * 5 + c[i])
for j in range(4):
print &│%4s& % (mtrx[i][j] if mtrx[i][j] else ' '),
print &│&
print a[4] + (&─& * 5 + b[4]) * 3 + (&─& * 5 + c[4])
(2)有了表格雏形,我们需要对矩阵进行初始化,then,我们就可以看到一个像模像样的2048开始啦!
初始化矩阵是非常简单的,我们在矩阵中选两个不同位置,设置为2其他为0即可。
先设置为0(没有memset,╮(╯▽╰)╭)
但是这样就可以啦:(看不惯?没关系,非常容易理解,慢慢习惯吧!)
mtr = [[0 for i in range(4)] for j in range(4)]
我们选的位置是采取随机的,要保证不同,方法很多,但是我们python的random.sample就非常棒了!
我们用简单的一句
ran_pos = random.sample(range(16), 2)
便可以得到一个由两个不同组成的片段
之后我们通过 4*i+j 进行二维到一维的映射,同样也用( num/4 ,num%4)进行一维到二维的映射
所以我们初始话的过程也是十分简单。(要是偷懒,也可以直接忽略随机过程,自己指定吧!哈哈)
def init(): #initial of matrix
mtr = [[0 for i in range(4)] for j in range(4)]
ran_pos = random.sample(range(16), 2)
mtr[ran_pos[0]/4][ran_pos[0]%4] = mtr[ran_pos[1]/4][ran_pos[1]%4] = 2
return mtr
怎么样?啦!!!O(∩_∩)O哈哈~
(3)动起来!!让我们的2048动起来!
老实说,这个过程是全个程序最核心的部分,也是最难过的~不过理解了也就不难了。
我们先看向左移动吧。
记得我们玩的时候,合并过的格子是不会再在这次合并的,比如 某一行为 2 2 2 2 最后移动到的结果是4 4 0 0 而不是 8 0 0 0。我们要理解这个过程:
& 我们对于每一行的操作是一样的,即行间无关,所以我们现在要讨论第i行,当我们向左动起来的时候,我们从最左开始确定,我们一开始合并前两个,再合并前三个,再合并前4个。比如
&&&& 2 2 4 4&& =& 4 0 4 4 =& 4 4 0 4 =&4 4 4 0 =& 4 8 0 0
注意两点: 1.合并过的不再参与合并,所以我们需要一个visit列表,用到前面所讲的映射
&&&&&&&&&&&&&&&&&&&& 2.合并的情况=&相邻的相等,移动的情况=&当前元素为0
python代码
for i in range(4):
for j in range(1, 4):
for k in range(j,0,-1):
if mtr[i][k - 1] == 0 :
mtr[i][k - 1] = mtr[i][k]
mtr[i][k] = 0
elif mtr[i][k - 1] == mtr[i][k] and 4 * i + k - 1 not in visit and 4 * i + k not in visit:
mtr[i][k - 1] *= 2
mtr[i][k] = 0
score += mtr[i][k - 1]
visit.append(4 * i + k)
visit.append(4 * i + k - 1)
当你想明白这个过程后,整个move过程就自然清晰起来了。
这个是本文第一个,最后一个比较长的函数了!
def move(mtr, dirct):#the core code!move by the four direction
visit = []
if dirct == 0:
for i in range(4):
for j in range(1, 4):
for k in range(j,0,-1):
if mtr[i][k - 1] == 0 :
mtr[i][k - 1] = mtr[i][k]
mtr[i][k] = 0
elif mtr[i][k - 1] == mtr[i][k] and 4 * i + k - 1 not in visit and 4 * i + k not in visit:
mtr[i][k - 1] *= 2
mtr[i][k] = 0
score += mtr[i][k - 1]
visit.append(4 * i + k)
visit.append(4 * i + k - 1)
elif dirct == 1:
for j in range(4):
for i in range(3, 0, -1):
for k in range(0,i):
if mtr[k+1][j] == 0:
mtr[k+1][j] = mtr[k][j]
mtr[k][j]=0
elif mtr[k+1][j]==mtr[k][j] and (4 *(k+1)+j) not in visit and (4*k+j) not in visit:
mtr[k+1][j]*=2
mtr[k][j]=0
score=mtr[k+1][j]
visit.append(4*(k)+j)
visit.append(4*(k+1)+j)
elif dirct == 2:
for j in range(4):
for i in range(1,4):
for k in range(i,0,-1):
if mtr[k-1][j]==0:
mtr[k-1][j]=mtr[k][j]
mtr[k][j]=0
elif mtr[k-1][j]==mtr[k][j] and (4 *(k-1)+j) not in visit and (4*k+j) not in visit:
mtr[k-1][j]*=2
mtr[k][j]=0
score += mtr[k-1][j]
visit.append(4*(k)+j)
visit.append(4*(k-1)+j)
elif dirct == 3:
for i in range(4):
for j in range(3, 0, -1):
for k in range(j):
if mtr[i][k+1]
mtr[i][k+1] = mtr[i][k]
mtr[i][k]=0
elif mtr[i][k] ==mtr[i][k+1] and 4 * i + k + 1 not in visit and 4 * i + k not in visit:
mtr[i][k+1]*=2
mtr[i][k]=0
score+=mtr[i][k+1]
visit.append(4*i+k+1)
visit.append(4*i+k)
return score
(4)当你来到这步,已经进入轻松的状态了,让控制台读入你的操作,短短两行,其中一行是转成小写
dirct = raw_input(&Step :%d Score :%d (%s):& % (step, score, declare))
dirct = dirct.lower()
(5)判断读入操作并处理
if dirct == &q&:
elif dirct == &a& or dirct == &h&:
elif dirct == &s& or dirct == &j&:
elif dirct == &w& or dirct == &k&:
elif dirct == &d& or dirct == &l&:
elif dirct == &b&:
if len(mtr_stk) == 1:
print &Can't Back..&
mtr_stk.pop()
scr_stk.pop()
mtr = copy.deepcopy(mtr_stk[-1])
score = scr_stk[-1]
print illegal
我是vim 的脑残粉,所以还支持了hjkl,如果你没有习惯vim什么的,直接asdw就可以了。
上面最麻烦最值得注意的就是要用深复制.这个bug我调了很久啊亲,用&=&伤不起啊。
上面的处理意思就是: 映射方向,和b,q的处理(有continue是因为我们将嵌套于while中)。
(6)移动的处理
在上面处理后,筛选出移动的操作,之后我们调用移动函数,进行加分,和比较。
tmp = copy.deepcopy(mtr)
op_scr = move(mtr, dirct)
if tmp != mtr:
score = score + op_scr
update(mtr) #更新
display(mtr)
tmp = copy.deepcopy(mtr)
mtr_stk.append(tmp)
# 插入后退队列
scr_stk.append(int(score))
step = step + 1
print noefficient
不能仅仅用加分来判断!因为我们很多时候都是没有碰撞合并,等待下一个2,4出现
我们用深复制,将老的矩阵放在tmp上,再移动,将老新矩阵比较,没改变的时候就输出 noefficient,否则就加分,插入新数字,并显示,最后将矩阵压入栈中,因为要后退!
(7)插入新数字
我们遍历0-16,并映射后,将对应0的位置放入random列表,我们用random.choice选出一个,同理我们生成一个ran_num=[2,4],选取加分
之后对应位置加分咯!但是注意,当我们没有空位时候不要插数字。
def update(mtr):
ran_pos=[]
ran_num=[2,4]
for i in range(4):
for j in range(4):
if mtr[i][j]==0:
ran_pos.append(4*i+j)
if len(ran_pos)&0:
k=random.choice(ran_pos)
n=random.choice(ran_num)
mtr[k/4][k%4]=n
(8)最后一个啦!!!游戏的循环条件
这个还是很简单的。游戏进行,当前仅当:没有2048且(有0或者可以合并)。
所以我们只需要判断2048 in mtr,有就结束,没有 == & 0 in mtr ?有就继续,没有==&可以合并?有继续,没有==》,就返回结束啦
def go_on(mtr, score):
if 2048 in mtr:
print &Great!You win!Your score is &, score
raw_input(&Press any key to continue...&)
if 0 in mtr:
return True
for i in range(4):
for j in range(4):
if i & 3 and mtr[i][j] == mtr[i + 1][j]:
return True
if j & 3 and mtr[i][j] == mtr[i][j + 1]:
return True
print &Gameover!&
return False
(9)一些其他的东西
注意一开始要画出开始的画面(循环外),一开始要将初始矩阵,初始分数,压入栈。
最后来个最终版本的
#!/usr/bin/env python
# coding=utf-8
#********************************************************
: Linux 3.2.0-60-generic #91-Ubuntu
# & Author : yaolong
: 日 星期日 13:13:39
#********************************************************
import random
import copy
return a if a else ' '
def display(mtr):
print &┌&+(&─&*5+&┬&)*3+&─&*5+&┐&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[0][0]),T(mtr[0][1]),T(mtr[0][2]),T(mtr[0][3]))
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[1][0]),T(mtr[1][1]),T(mtr[1][2]),T(mtr[1][3]))
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[2][0]),T(mtr[2][1]),T(mtr[2][2]),T(mtr[2][3]))
print &├&+(&─&*5+&┼&)*3+&─&*5+&┤&
print &│%4s │%4s │%4s │%4s │&%(T(mtr[3][0]),T(mtr[3][1]),T(mtr[3][2]),T(mtr[3][3]))
print &└&+(&─&*5+&┴&)*3+&─&*5+&┘&
def init():
mtr = [[0 for i in range(4)] for j in range(4)]
# 小小蛋疼..
ran_pos = random.sample(range(16), 2)
mtr[ran_pos[0]/4][ran_pos[0]%4] = mtr[ran_pos[1]/4][ran_pos[1]%4] = 2
return mtr
def go_on(mtr, score):
if 2048 in mtr:
print &Great!You win!Your score is &, score
raw_input(&Press any key to continue...&)
if 0 in mtr:
return True
for i in range(4):
for j in range(4):
if i & 3 and mtr[i][j] == mtr[i + 1][j]:
return True
if j & 3 and mtr[i][j] == mtr[i][j + 1]:
return True
print &Gameover!&
return False
def move(mtr, dirct):
visit = []
if dirct == 0:
for i in range(4):
for j in range(1, 4):
for k in range(j,0,-1):
if mtr[i][k - 1] == 0 :
mtr[i][k - 1] = mtr[i][k]
mtr[i][k] = 0
elif mtr[i][k - 1] == mtr[i][k] and 4 * i + k - 1 not in visit and 4 * i + k not in visit:
mtr[i][k - 1] *= 2
mtr[i][k] = 0
score += mtr[i][k - 1]
visit.append(4 * i + k)
visit.append(4 * i + k - 1)
# for i in range(4):
# for j in range(3):
elif dirct == 1:
for j in range(4):
for i in range(3, 0, -1):
for k in range(0,i):
if mtr[k+1][j] == 0:
mtr[k+1][j] = mtr[k][j]
mtr[k][j]=0
elif mtr[k+1][j]==mtr[k][j] and (4 *(k+1)+j) not in visit and (4*k+j) not in visit:
mtr[k+1][j]*=2
mtr[k][j]=0
score=mtr[k+1][j]
visit.append(4*(k)+j)
visit.append(4*(k+1)+j)
elif dirct == 2:
for j in range(4):
for i in range(1,4):
for k in range(i,0,-1):
if mtr[k-1][j]==0:
mtr[k-1][j]=mtr[k][j]
mtr[k][j]=0
elif mtr[k-1][j]==mtr[k][j] and (4 *(k-1)+j) not in visit and (4*k+j) not in visit:
mtr[k-1][j]*=2
mtr[k][j]=0
score += mtr[k-1][j]
visit.append(4*(k)+j)
visit.append(4*(k-1)+j)
elif dirct == 3:
for i in range(4):
for j in range(3, 0, -1):
for k in range(j):
if mtr[i][k+1]
mtr[i][k+1] = mtr[i][k]
mtr[i][k]=0
elif mtr[i][k] ==mtr[i][k+1] and 4 * i + k + 1 not in visit and 4 * i + k not in visit:
mtr[i][k+1]*=2
mtr[i][k]=0
score+=mtr[i][k+1]
visit.append(4*i+k+1)
visit.append(4*i+k)
return score
def update(mtr):
ran_pos=[]
ran_num=[2,4]
for i in range(4):
for j in range(4):
if mtr[i][j]==0:
ran_pos.append(4*i+j)
if len(ran_pos)&0:
k=random.choice(ran_pos)
n=random.choice(ran_num)
mtr[k/4][k%4]=n
# map 0 left,1 down,2 up ,3 right
# a,h=& left ,s,j=&down, w,k=&up, d,l=&right
declare = &←:a/h
↓: s/j ↑: w/k →: d/l ,q(uit),b(ack)&
illegal = &Illegal operation!&
noefficient = &This move has no efficient&
if __name__ == '__main__':
mtr = init()
mtr_stk = []
# for back
scr_stk = []
tmp = copy.deepcopy(mtr)
mtr_stk.append(tmp)
scr_stk.append(0)
display(mtr)
while go_on(mtr, score):
dirct = raw_input(&Step :%d Score :%d (%s):& % (step, score, declare))
dirct = dirct.lower()
if dirct == &q&:
elif dirct == &a& or dirct == &h&:
elif dirct == &s& or dirct == &j&:
elif dirct == &w& or dirct == &k&:
elif dirct == &d& or dirct == &l&:
elif dirct == &b&:
if len(mtr_stk) == 1:
print &Can't Back..&
mtr_stk.pop()
scr_stk.pop()
mtr = copy.deepcopy(mtr_stk[-1])
score = scr_stk[-1]
print illegal
tmp = copy.deepcopy(mtr)
op_scr = move(mtr, dirct)
if tmp != mtr:
score = score + op_scr
update(mtr) #更新
display(mtr)
tmp = copy.deepcopy(mtr)
mtr_stk.append(tmp)
# 插入后退队列
scr_stk.append(int(score))
step = step + 1
print noefficient
还有我github的版本,大致一样,点
如果我的算法有什么不对,请提出,因为写得匆忙,我未能很完整第测试,但是我自己玩了几把还是OK了,没玩到2048╮(╯▽╰)╭。。。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致}

我要回帖

更多关于 python 编写安装程序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信