以前遊戲2048火的時候,正好用其他的語言編寫了一個,現在學習python,正好想起來,便決定用python寫一個2048,由於沒學過python裡面的界面編程,所以寫了一個極其簡單的無介面2048。遊戲2048的原理和實現都不難,正好可以拿來練手,要是不知道這遊戲的話,可以去網上查一下,或者下載一個到手機來玩一下,我就不在說其原理。我知道不放圖的話大家一點興趣都沒,下面先放一張遊戲成型圖,然後我們在來講如何一步步用最基礎的知識來實現。
一、產生4*4的矩陣
遊戲的第一步便是生成一個4*4的矩陣,當作我們遊戲的主介面,其實說起來也比較簡單,這裡用了最原始的方法,直接用
print將其列印出來。首先我們要產生一個全為0的4*4二維列表,然後用一些類似 '┌ ├└,┤,┘┐│,─,┬,┴'這樣的字符來組成我們的邊框,下面來看一下程式碼的實作
matix=[[ for i in range()] for i in range()] # 用列表推导式初始化生成一个*的列表,列表元素全为 # notzero函数的作用:游戏界面上非零的时候才显示,当为的时候,让其显示空, def notzero(s): return s if s!= else '' # 非零的话返回本身,否则返回 '' def display(): # 显示界面函数,用┌ ├└,┤,┘┐│,─,┬,┴ 等显示边框,中间显示*矩阵里的的元素 print("\r\ ┌──┬──┬──┬──┐\n\ │%s│%s│%s│%s│\n\ ├──┬──┬──┬──┤\n\ │%s│%s│%s│%s│\n\ ├──┬──┬──┬──┤\n\ │%s│%s│%s│%s│\n\ ├──┬──┬──┬──┤\n\ │%s│%s│%s│%s│\n\ └──┴──┴──┴──┘"\ %(notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),\ notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),\ notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),notzero(matix[][]), \ notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),notzero(matix[][]),) ) display()
來看一下上面程式碼的效果,是不是感覺一個遊戲的框架已經到搭好了,由於初始化的時候,矩陣元素都為零,下面的圖也就沒有顯示出0,是不是很簡單,一個遊戲的介面就被我們搭好了,不過畢竟沒學過介面,所以大家就不要抱怨這介面有多醜了哈。
二、初始化生成隨機數
這個遊戲每次開始的時候都會隨機在上面的一個矩陣中產生兩個隨機數2或4,那麼我們要如何來實現在上面矩陣中隨機的一個位置生成一個隨機數2或4了,當然是用到我們前面學過的random模組以及pmod(),下面我們就來看看如何用random模組實現一功能。
def init(): # 初始化矩阵 initNumFlag = while : k = if random.randrange(, ) > else # 当生成随机数大于的时候k=否则k= 生成和的概率为: s = pmod(random.randrange(, ), ) # 生成矩阵初始化的下标 比如pmod(,)的话,s为(,)正好可以作为矩阵下标 if matix[s[]][s[]] == : # 只有当其值不为的时候才赋值,避免第二个值重复 matix[s[]][s[]] = k initNumFlag += if initNumFlag == : # 当initNumFlag== 的话表示矩阵里两个随机数都已经生成了,退出循环 break init() display( )
來看一下上面程式碼的效果,是不是已經在兩個隨機的位置產生了兩個數,如果大家有時間的試一下,可以看見每次執行的時候,出現在矩陣上面位置不一樣,而且每次出現的數也不一樣,因為我上面設定了出現2:4的機率為9:1所以大多時候出現2,這也是遊戲的需要。到了這裡矩陣已經可以動起來了,遊戲的功能也可以說完成了一半。
三、遊戲邏輯部分實作
如果玩過這遊戲的話就知道,遊戲中每次向上下左右移動的時候,比如像下移動的話,所有的數都會向下移動,碰到相同的數,就會成一個新的數,比如2和2碰到的話,就會生成4,然後再隨機在其他位置生成一個2或4 ,同理4和4碰到的話也會生成8,直到合成了2048遊戲就算成功了,或者說矩陣中的數字都不能移動那就是Game Over。當然我們在手機上玩遊戲的話,隨便滑動一下,所有的數字就可以向其中一個方向滑動,但是這裡沒有界面,條件比較艱苦,所以只能從控制台讀入用戶輸入的字母,然後一個個來判斷是往哪裡移動了,所以我們要寫4個函數來分別處理使用者的上下左右移動,讓後一個函數處理在每次使用者移動後,如何加上一個隨機數,下面先寫一段偽代碼來解釋流程
def addRandomNum(): #每次移动后随机在矩阵中在生成一个数 pass def moveDown(): #向上移动的处理函数 pass<br> addRandomNum() #移动处理完成后,随机生成一个数 def moveLeft(): #向左移动的处理函数 pass addRandomNum() def moveUp(): #向上移动的处理函数 pass addRandomNum() def moveRight(): #向右移动的处理函数 pass addRandomNum() def main(): while flag: #定义一个死循环,不断读入用户的输入,然后在做判断,看是向哪里移动 d = input(' (↑:w) (↓:s) (←:a) (→:d),q(uit) :“) if d == 'a': moveLeft() elif d == 's': moveDown() elif d == 'w': moveUp() elif d == 'd': moveRight() elif d == 'q': break else: pass
上面是一段為了理解的偽代碼,下面我們來看看如何實現移動處理函數,這裡是整個遊戲中最難處理的部分,完成了這一部分的話,整個遊戲也就基本上實現了,這裡我以向下的移動處理函數為例,其他的都一樣,當用戶輸入向下移動的時候,所有的數字都向下移動,如果碰到相同的數字要和併,有數字的方塊向沒有數字的方塊移動。這裡要用循環實現,有4列所以最外層的循環有4次,每一列裡面又需要循環處理,下面來看一下具體怎麼實現,
def addRandomNum(): # 跟初始化生成随机数一样,只不过这里只是生成一个随机数 while : k = if random.randrange(, ) > else s = pmod(random.randrange(, ), ) if matix[s[]][s[]] == : matix[s[]][s[]] = k break display() # 随机数添加完成后就直接调用显示函数,直接显示一下游戏界面 def moveDown(): #处理向下移动的函数 for i in range(): #外层次循环处理例,内层两个层循环,来处理相邻的两个数 for j in range(, , -): for k in range(j - , -, -): if matix[k][i] > : # 从最下面的数开始处理相邻的两个数 if matix[j][i] == : matix[j][i] = matix[k][i] # 如果下面的数为空,上面的数字不为空就移动上面的数为下面的数 matix[k][i] = elif matix[j][i] == matix[k][i]: # 如果相邻的两个数相等的话,就和并,并把上面的输置零,下面的数变成两倍 matix[j][i] *= matix[k][i] = break addRandomNum() # 移动完成后再随机生成一个数
写完了向下移动的处理函数,那么向其他方向的移动函数也一样,照着写,就可以,到这里游戏中最难的部分就完成,可以说胜利就在眼前了,好了在这之前,我们还需要处理一下其他问题,那就是每次移动后都要检查,游戏是不是Game Over了,还有就是定义一个变量来纪录分数了,这些实现起来都比较简单。
四、游戏纪录分数和检查游戏是否结束
游戏结束的标志是矩阵中所有的数都不为0,而且所有相邻的数都不能合并,根据这个我们就可以来写一个函数来判断游戏是否GG,至于分数纪录,我们只需定义一个变量,然后每次有何并的时候,就加上一定的分数即可。下面我们来看检查函数的实现。
def check(): for i in range(4): #按每一排循环4 次 for j in range(3): # 如果矩阵中有0存在,或者有相邻的数就表示游戏还可以继续经行,否则就是GG if matix[i][j] == 0 or matix[i][j] == matix[i][j + 1] or matix[j][i] == matix[j + 1][i]: return True else: return False
五、完整游戏源码
完成了上面的部分,整个游戏的过程就实现了,下面附上整个游戏的源码。游戏还有很多不够完善的地方,比如说游戏中如果出现2048的话,就表示玩家胜利,游戏结束,但是我这里没有做处理,所以这个游戏可以一直玩到4096....没有结束,除非你游戏中GG了,要处理也很简单,还可以将矩阵存在文件中,完成一个游戏存档的功能。有兴趣的话大家去实现一下。
import random score = 0 # 纪录游戏的分数 matix = [[0 for i in range(4)] for i in range(4)] # 初始化生成一个4*4的列表 def notzero(s): return s if s != 0 else '' def display(): print("\r\ ┌──┬──┬──┬──┐\n\ │%4s│%4s│%4s│%4s│\n\ ├──┬──┬──┬──┤\n\ │%4s│%4s│%4s│%4s│\n\ ├──┬──┬──┬──┤\n\ │%4s│%4s│%4s│%4s│\n\ ├──┬──┬──┬──┤\n\ │%4s│%4s│%4s│%4s│\n\ └──┴──┴──┴──┘" \ % (notzero(matix[0][0]), notzero(matix[0][1]), notzero(matix[0][2]), notzero(matix[0][3]), \ notzero(matix[1][0]), notzero(matix[1][1]), notzero(matix[1][2]), notzero(matix[1][3]), \ notzero(matix[2][0]), notzero(matix[2][1]), notzero(matix[2][2]), notzero(matix[2][3]), \ notzero(matix[3][0]), notzero(matix[3][1]), notzero(matix[3][2]), notzero(matix[3][3]),) ) def init(): # 初始化矩阵 initNumFlag = 0 while 1: k = 2 if random.randrange(0, 10) > 1 else 4 # 随机生成 2 或 4 s = pmod(random.randrange(0, 16), 4) # 生成矩阵初始化的下标 if matix[s[0]][s[1]] == 0: # 只有当其值不为0的时候才赋值,避免第二个值重复 matix[s[0]][s[1]] = k initNumFlag += 1 if initNumFlag == 2: break display() def addRandomNum(): #处理完移动后添加一个新的随机数 while 1: k = 2 if random.randrange(0, 10) > 1 else 4 s = pmod(random.randrange(0, 16), 4) if matix[s[0]][s[1]] == 0: matix[s[0]][s[1]] = k break display() def check(): #检查游戏是否GG for i in range(4): for j in range(3): if matix[i][j] == 0 or matix[i][j] == matix[i][j + 1] or matix[j][i] == matix[j + 1][i]: return True else: return False def moveRight(): # 向右移动处理函数 global score for i in range(4): for j in range(3, 0, -1): for k in range(j - 1, -1, -1): if matix[i][k] > 0: if matix[i][j] == 0: matix[i][j] = matix[i][k] matix[i][k] = 0 elif matix[i][j] == matix[i][k]: matix[i][j] *= 2 score += matix[i][j] #将当前数作为score加上 matix[i][k] = 0 break addRandomNum() def moveUp(): global score for i in range(4): for j in range(3): for k in range(j + 1, 4): if matix[k][i] > 0: if matix[j][i] == 0: matix[j][i] = matix[k][i] matix[k][i] = 0 elif matix[k][i] == matix[j][i]: matix[j][i] *= 2 score += matix[j][i] matix[k][i] = 0 break addRandomNum() def moveDown(): global score for i in range(4): for j in range(3, 0, -1): for k in range(j - 1, -1, -1): if matix[k][i] > 0: if matix[j][i] == 0: matix[j][i] = matix[k][i] matix[k][i] = 0 elif matix[j][i] == matix[k][i]: matix[j][i] *= 2 score += matix[j][i] matix[k][i] = 0 break addRandomNum() def moveLeft(): global score for i in range(4): for j in range(3): for k in range(1 + j, 4): if matix[i][k] > 0: if matix[i][j] == 0: matix[i][j] = matix[i][k] matix[i][k] = 0 elif matix[i][j] == matix[i][k]: matix[i][j] *= 2 score += matix[i][j] matix[i][k] = 0 break addRandomNum() def main(): print(" \033[33;1mWelcome to the Game of 2048!\033[0m") flag = True init() while flag: #循环的标志 print(' \033[33;1m You Score:%s\033[0m' % (score)) d = input('\033[33;1m (↑:w) (↓:s) (←:a) (→:d),q(uit) :\033[0m') #不断处理用户输入 if d == 'a': moveLeft() if not check(): #检查游戏是否GG print('GG') flag = False #GG的话直接退出 elif d == 's': moveDown() if not check(): print('GG') flag = False elif d == 'w': moveUp() if not check(): print('GG') flag = False elif d == 'd': moveRight() if not check(): print('GG') flag = False elif d == 'q': # 退出 break else: # 对用户的其他输入不做处理 pass if __name__ == '__main__': main()
最后在附上一张图片最为结束
以上所述是小编给大家介绍的用Python寫一個無介面的2048小遊戲,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网的支持!
更多Python寫一個無介面的2048小遊戲相关文章请关注PHP中文网!