如何用python写2048

Python (254) 2023-06-19 11:09:03

2048游戏规则:简单的移动方向键让数字叠加,并且获得这些数字每次叠加后的得分,当出现2048这个数字时游戏胜利。同时每次移动方向键时,都会在这个4*4的方格矩阵的空白区域随机产生一个数字2或者4,如果方格被数字填满了,那么就GameOver了。

来一步步的进行剖析:

(1)生成4*4的棋盘, 其中数据结构为列表嵌套列表

field=[[0forjinrange(4)]foriinrange(4)]

(2)创建函数random_create, 在棋盘的一个随机位置插入一个数字2或者4,其中2的几率大

importrandom
defrandom_create():
i=random.choice(range(4))
j=random.choice(range(4))
value=random.choice([2,2,2,4])
field[i][j]=value

(3)如果随机插入数字的位置已经有内容, 如何解决覆盖原有数字的问题

defrandom_creat():
whileTrue:
i=random.choice(range(4))
j=random.choice(range(4))
ifli[i][j]==0:
li[i][j]=4ifrandom.randint(1,100)>80else2
break
random_creat()
random_creat()

(4)将生成的数据, 通过图像画出来

defdraw_sep():
print('+-----'*4+'+')
defdraw_num(row):
print(''.join('|{:^5}'.format(num)ifnum!=0else'|'fornuminrow)+'|')
forrowinli:
draw_sep()
draw_num(row)
draw_sep()

(5)矩阵的反转

definvert(field):
return[row[::-1]forrowinfield]

(6)矩阵的转秩

deftranspose(field):
return[list(row)forrowinzip(*field)]

(7)判断棋盘是否可移动

defis_row_change(row):
#row
#判断一行内容是否可以移动
defis_change(i):
#判断每两个元素之间是否可以移动
ifrow[i]==0androw[i+1]!=0:
returnTrue
ifrow[i]!=0androw[i+1]==row[i]:
returnTrue
else:
returnFalse
returnany([is_change(index)forindexinrange(len(row)-1)])

(8)判断这个棋盘是否可左右上下移动

defis_move_left(field):
returnany([is_row_change(row)forrowinfield])
defis_move_right(field):
#对于列表元素进行反转
field=invert(field)
print(field)
returnis_move_left(field)
defis_move_up(field):
#对于列表元素进行转置
field=transpose(field)
returnis_move_left(field)
defis_move_down(field):
#反转+转置
field=transpose(field)
returnis_move_right(field)

棋盘的移动,相加

deftight(row):#[2,0,2,0]
#最快的方式,通过排序实现...........
returnsorted(row,key=lambdax:ifx==0)
score=0
#相加
defmerge(row):#[2,2,0,0]
#[0,1,2]
foriinrange(len(row)-1):
#如果两个值相等,前一个元素*2,后一个元素改为0。
ifrow[i]==row[i+1]:
row[i]*=2
row[i+1]=0
#如果覆盖成功,就给得分
globalscore
score+=row[i]
returnrow

棋盘左右上下移动相加

defmove_row_left(self,row):
returnself.tight(self.merge(self.tight(row)))
defmove_left(self,field):
return[self.move_row_left(row)forrowinfield]
defmove_right(self,field):
field=self.invert(field)
returnself.invert([self.move_row_left(row)forrowinfield])
defmove_up(self,field):
returnself.transpose([self.move_row_left(row)forrowinself.transpose(field)])
defmove_down(self,field):
returnself.invert(self.transpose([self.move_row_left(row)
forrowinself.invert(self.transpose(field))]))

(9)判断游戏的胜利与结束

#判断游戏何时胜利:当棋盘中出现2048时,就代表着游戏胜利
defvictory(field):
li=[yforrowinliforyinrow]
ifmax(li)>=2048:
print('Victory')
defgame_over(filed):
ifall((is_move_left(filed),is_move_right(filed),is_move_up(filed),is_move_down(filed)))==False:
print('GameOver')

这样程序的各个部分就写好了,将各个部分封装到一个类里面,再导入curses模块来控制游戏,就可以了。

相关推荐:《Python教程》

下面是完整的代码:

importcurses
fromitertoolsimportchain
fromrandomimportchoice
classGameField(object):
#初始化信息
def__init__(self,width=4,height=4,win_value=8):
self.width=width
self.height=height
self.win_value=win_value
self.score=0#当前得分
self.highscore=0#最高分
self.moves={}
self.moves['Left']=self.is_move_left
self.moves['Right']=self.is_move_right
self.moves['Down']=self.is_move_down
self.moves['Up']=self.is_move_up
self.movesDict={}
self.movesDict['Left']=self.move_left
self.movesDict['Right']=self.move_right
self.movesDict['Down']=self.move_down
self.movesDict['Up']=self.move_up
defreset(self):#重置棋盘
ifself.score>self.highscore:
self.highscore=self.score#更新最高分
self.score=0
#需求1:生成4*4的棋盘,其中数据结构选择列表嵌套列表;
self.field=[[0forjinrange(self.width)]
foriinrange(self.height)]
#在棋盘的一个随机位置插入一个数字2或者4
self.random_create()
self.random_create()
defrandom_create(self):
#在棋盘的一个随机位置插入一个数字2或者4
#field[0][3]=2
whileTrue:
i,j=choice(range(self.height)),choice(range(self.width))
ifself.field[i][j]==0:
self.field[i][j]=choice([2,2,2,4])
break
defdraw(self,stdscr):
defdraw_sep():
stdscr.addstr('+'+"-----+"*self.width+'\n')
defdraw_one_row(row):
stdscr.addstr("".join('|{:^5}'.format(num)ifnum!=0else"|"fornuminrow)+'|'+'\n')
#清屏
stdscr.clear()
stdscr.addstr("2048".center(50,'-')+'\n')
stdscr.addstr("当前分数:"+str(self.score)+'\n')
ifself.highscore!=0:
stdscr.addstr("最高分:"+str(self.highscore)+'\n')
forrowinself.field:
draw_sep()
draw_one_row(row)
draw_sep()
#判断是否赢或者输
ifself.is_win():
stdscr.addstr("胜利!!!!"+'\n')
ifself.is_gameover():
stdscr.addstr("游戏结束!!!!"+'\n')
stdscr.addstr("游戏帮助:上下左右键(R)RestartQ(Quit)")
defis_win(self):
returnmax(chain(*self.field))>=self.win_value
defis_gameover(self):
#任何方向都不能移动的时候,游戏结束
returnnotany([self.move_is_possible(direction)
fordirectioninself.moves])
@staticmethod
definvert(field):
#矩阵进行反转
return[row[::-1]forrowinfield]
#print(invert(li))
@staticmethod
#矩阵的转置
deftranspose(field):
return[list(row)forrowinzip(*field)]
@staticmethod
defis_row_change(row):
#row
#需求3.判断一行内容是否可移动。
defis_change(i):#0
#判断每两个元素之间是否可移动
ifrow[i]==0androw[i+1]!=0:
returnTrue
ifrow[i]!=0androw[i]==row[i+1]:
returnTrue
returnFalse
returnany([is_change(index)forindexinrange(len(row)-1)])
#判断这个棋盘是否可向左移动
defis_move_left(self,field):
returnany([self.is_row_change(row)forrowinfield])
defis_move_right(self,field):
#对于列表元素进行反转
field=self.invert(field)
print(field)
returnself.is_move_left(field)
defis_move_up(self,field):
#对于列表元素进行转置
field=self.transpose(field)
returnself.is_move_left(field)
defis_move_down(self,field):
#反转+转置
field=self.transpose(field)
returnself.is_move_right(field)
defmove_is_possible(self,direction):#'left'
#判断用户选择的方向是否可移动
ifdirectioninself.moves:
returnself.moves[direction](self.field)
else:
returnFalse
#将棋盘每一行的非0数向前移动,0向后移动;
@staticmethod
deftight(row):#[2,0,2,0]
#最快的方式,通过排序实现...........
returnsorted(row,key=lambdax:1ifx==0else0)
defmerge(self,row):#[2,2,0,0]
#[0,1,2]
foriinrange(len(row)-1):
#如果两个值相等,前一个元素*2,后一个元素改为0。
ifrow[i]==row[i+1]:
row[i]*=2
row[i+1]=0
#如果覆盖成功,就给得分
self.score+=row[i]
returnrow#[4,0,0,0]
defmove_row_left(self,row):
returnself.tight(self.merge(self.tight(row)))
defmove_left(self,field):
return[self.move_row_left(row)forrowinfield]
defmove_right(self,field):
field=self.invert(field)
returnself.invert([self.move_row_left(row)forrowinfield])
defmove_up(self,field):
returnself.transpose([self.move_row_left(row)forrowinself.transpose(field)])
defmove_down(self,field):
returnself.invert(self.transpose([self.move_row_left(row)
forrowinself.invert(self.transpose(field))]))
defmove(self,direction):#'left'
#判断用户选择的方向是否可移动
ifdirectioninself.movesDict:
#判断是否可移动
ifself.move_is_possible(direction):
self.field=self.movesDict[direction](self.field)
self.random_create()
returnTrue
else:
returnFalse
defget_user_action(stdscr):
action=stdscr.getch()
ifaction==curses.KEY_UP:
return'Up'
ifaction==curses.KEY_DOWN:
return'Down'
ifaction==curses.KEY_LEFT:
return'Left'
ifaction==curses.KEY_RIGHT:
return'Right'
ifaction==ord('r'):
return'Restart'
ifaction==ord('q'):
return'Exit'
defmain(stdscr):
action=stdscr.getch()
definit():
#初始化棋盘的操作
game_field.reset()
game_field.draw(stdscr)
return'Game'
defgame():
game_field.draw(stdscr)
action=get_user_action(stdscr)
ifaction=='Restart':
return'Init'
ifaction=='Exit':
return'Exit'
ifgame_field.move(action):
ifgame_field.is_win():
return'Win'
ifgame_field.is_gameover():
return'GameOver'
return'Game'
defnot_game():
game_field.draw(stdscr)
whileTrue:
action=get_user_action(stdscr)
ifaction=='Restart':
return'Init'
ifaction=='Exit':
return'Exit'
state_actions={
'Init':init,
'Game':game,
'Win':not_game,
'GameOver':not_game,
}
game_field=GameField()
state='Init'
#如果当前状态不是退出,那么一直执行
whilestate!='Exit':
#执行当前状态需要操作的内容,并返回,下一次的状态为什么.
state=state_actions[state]()
curses.wrapper(main)

实现双人版的2048游戏

importcurses
importrandom
fromitertoolsimportchain
classGameField(object):
def__init__(self,width=4,height=4,win_value=2048):
self.width=width
self.height=height
self.win_value=win_value
self.score1=0
self.score2=0
self.highscore=0
self.moves={}
self.moves['Left1']=self.is_left_move
self.moves['Right1']=self.is_right_move
self.moves['Up1']=self.is_up_move
self.moves['Down1']=self.is_down_move
self.moves['Left2']=self.is_left_move
self.moves['Right2']=self.is_right_move
self.moves['Up2']=self.is_up_move
self.moves['Down2']=self.is_down_move
self.movesDict1={}
self.movesDict2={}
self.movesDict1['Left1']=self.left_move
self.movesDict1['Right1']=self.right_move
self.movesDict1['Up1']=self.up_move
self.movesDict1['Down1']=self.down_move
self.movesDict2['Left2']=self.left_move
self.movesDict2['Right2']=self.right_move
self.movesDict2['Up2']=self.up_move
self.movesDict2['Down2']=self.down_move
defrandom_create1(self):
whileTrue:
i,j=random.randint(0,self.height-1),random.randint(0,self.width-1)
ifself.field1[i][j]==0:
self.field1[i][j]=random.choice([2,2,2,4])
break
defrandom_create2(self):
whileTrue:
i,j=random.randint(0,self.height-1),random.randint(0,self.width-1)
ifself.field2[i][j]==0:
self.field2[i][j]=random.choice([2,2,2,4])
break
defreset(self):
self.field1=[[0forjinrange(self.width)]foriinrange(self.height)]
self.score1=0
self.field2=[[0forjinrange(self.width)]foriinrange(self.height)]
self.score2=0
self.random_create1()
self.random_create1()
self.random_create2()
self.random_create2()
defdraw(self,stdscr):
stdscr.clear()
self.score1=sum(chain(*self.field1))
self.score2=sum(chain(*self.field2))
ifmax(self.score1,self.score2)>self.highscore:
self.highscore=max(self.score1,self.score2)
stdscr.addstr('最高分:'+str(self.highscore)+'')
stdscr.addstr('玩家1分数:'+str(self.score1)+'')
stdscr.addstr('玩家2分数:'+str(self.score2)+'\n')
forrowinself.field1:
stdscr.addstr('+'+'-----+'*self.width+'\n')
stdscr.addstr("".join('|{:^5}'.format(num)ifnum!=0else"|"fornuminrow)+'|'+'\n')
stdscr.addstr('+'+'-----+'*self.width+'\n')
ifself.is_win1():
stdscr.addstr('胜利\n')
ifself.is_gameover1():
stdscr.addstr('游戏结束\n')
forrowinself.field2:
stdscr.addstr('+'+'-----+'*self.width+'\n')
stdscr.addstr("".join('|{:^5}'.format(num)ifnum!=0else"|"fornuminrow)+'|'+'\n')
stdscr.addstr('+'+'-----+'*self.width+'\n')
ifself.is_win2():
stdscr.addstr('胜利\n')
ifself.is_gameover2():
stdscr.addstr('游戏结束\n')
stdscr.addstr("玩家1:上下左右键玩家2:wasd键(R)重置(Q)退出")
defis_win1(self):
returnmax(chain(*self.field1))>=self.win_value
defis_win2(self):
returnmax(chain(*self.field2))>=self.win_value
defis_gameover1(self):
returnnotany([self.is_move_possible1(direction)fordirectioninself.moves])
defis_gameover2(self):
returnnotany([self.is_move_possible2(direction)fordirectioninself.moves])
@staticmethod
definvert(field):
return[row[::-1]forrowinfield]
@staticmethod
deftranspose(field):
return[list(row)forrowinzip(*field)]
@staticmethod
defis_row_change(row):
foriinrange(len(row)-1):
ifrow[i]==0androw[i+1]!=0:
returnTrue
elifrow[i]!=0androw[i]==row[i+1]:
returnTrue
else:
returnFalse
defis_left_move(self,field):
returnany([self.is_row_change(i)foriinfield])
defis_right_move(self,field):
returnany([self.is_row_change(i)foriinself.invert(field)])
defis_up_move(self,field):
returnany([self.is_row_change(i)foriinself.transpose(field)])
defis_down_move(self,field):
returnany([self.is_row_change(i)foriinself.invert(self.transpose(field))])
defis_move_possible1(self,direction):
ifdirectioninself.moves:
returnself.moves[direction](self.field1)
else:
returnFalse
defis_move_possible2(self,direction):
ifdirectioninself.moves:
returnself.moves[direction](self.field2)
else:
returnFalse
@staticmethod
defrow_move(row):
row=sorted(row,key=lambdax:1ifx==0else0)
foriinrange(len(row)-1):
ifrow[i]==row[i+1]:
row[i]*=2
row[i+1]=0
returnsorted(row,key=lambdax:1ifx==0else0)
defleft_move(self,field):
return[self.row_move(i)foriinfield]
defright_move(self,field):
returnself.invert([self.row_move(i)foriinself.invert(field)])
defup_move(self,field):
returnself.transpose([self.row_move(i)foriinself.transpose(field)])
defdown_move(self,field):
returnself.transpose(self.invert([self.row_move(i)foriinself.invert(self.transpose(field))]))
defmove1(self,direction):
ifdirectioninself.movesDict1andself.is_move_possible1(direction):
self.field1=self.movesDict1[direction](self.field1)
self.random_create1()
returnTrue
else:
returnFalse
defmove2(self,direction):
ifdirectioninself.movesDict2andself.is_move_possible2(direction):
self.field2=self.movesDict2[direction](self.field2)
self.random_create2()
returnTrue
else:
returnFalse
defget_user_action(stdscr):
action=stdscr.getch()
ifaction==curses.KEY_UP:
return'Up1'
elifaction==curses.KEY_DOWN:
return'Down1'
elifaction==curses.KEY_LEFT:
return'Left1'
elifaction==curses.KEY_RIGHT:
return'Right1'
elifaction==ord('r'):
return'Restart'
elifaction==ord('q'):
return'Exit'
elifaction==ord('w'):
return'Up2'
elifaction==ord('s'):
return'Down2'
elifaction==ord('a'):
return'Left2'
elifaction==ord('d'):
return'Right2'
defmain(stdscr):
definit():
game_field.reset()
game_field.draw(stdscr)
return'Game'
defgame():
game_field.draw(stdscr)
action=get_user_action(stdscr)
ifaction=='Restart':
return'Init'
ifaction=='Exit':
return'Exit'
ifactionin('Up1','Down1','Left1','Right1'):
ifgame_field.move1(action):
ifgame_field.is_win1():
return'Win'
ifgame_field.is_gameover1():
return'GameOver'
ifactionin('Up2','Down2','Left2','Right2'):
ifgame_field.move2(action):
ifgame_field.is_win2():
return'Win'
ifgame_field.is_gameover2():
return'GameOver'
return'Game'
defnot_game():
game_field.draw(stdscr)
whileTrue:
action=get_user_action(stdscr)
ifaction=='Restart':
return'Init'
ifaction=='Exit':
return'Exit'
game_field=GameField()
state='Init'
state_actions={
'Init':init,
'Game':game,
'Win':not_game,
'GameOver':not_game
}
whilestate!='Exit':
state=state_actions[state]()
curses.wrapper(main)
THE END

发表回复