python 小游戲《2048》字符版非圖形界面

參考鏈接:?閑談2048小游戲和數組的旋轉及翻轉和轉置

目錄

2048?

一、方陣類

二、隨機插入1或2

三、 合并和遞增

四、 判斷和移動

五、 鍵盤控制

完整源代碼

玩法過程


2048?

上回說到2048小游戲中數組的各種旋轉、翻轉的方法,就是為代碼編程作準備的;有了這些再就加上二維數組各行列上元素的合并、能否被合并的判斷、成功失敗的判斷等等;以及再加上鍵盤按鍵的控制,小游戲就基本完成了。

一、方陣類

方陣就是高寬相同的矩陣,2048用方陣就行了,寫代碼也省事一點,方陣的類如下:

>>> from random import sample
>>> class Matrix:
... ? ? def __init__(self, order=4):
... ? ? ? ? self.order = order
... ? ? ? ? self.matrix = self.new()
... ? ? def __repr__(self):
... ? ? ? ? m, n = [], len(str(2**max(sum(self.matrix,[]))))
... ? ? ? ? for mat in self.matrix:
... ? ? ? ? ? ? m.append(', '.join(f'{2**x if x else 0:>{n}}' for x in mat))
... ? ? ? ? return '],\n ['.join(m).join(['[[',']]'])
... ? ? def new(self):
... ? ? ? ? n = self.order
... ? ? ? ? m = sample([0]*(n*n-2)+sample([0,1,1],2),n*n)
... ? ? ? ? return ?[m[i*n:i*n+n] for i in range(n)]
...?
... ? ??
>>> Matrix()
[[0, 0, 2, 0],
?[0, 0, 0, 0],
?[0, 0, 2, 0],
?[0, 0, 0, 0]]
>>> Matrix()
[[0, 0, 0, 0],
?[0, 0, 0, 0],
?[0, 0, 2, 0],
?[0, 0, 0, 0]]

在方陣中隨機產生1~2個1,sample([0,1,1],2) 生成的1個還是2個,比例為2:1;

在__repr__方法中顯示時,這些1作為2的指數,所以顯示為2^1=2。

二、隨機插入數字

? ? def insert(self):
? ? ? ? n = self.order
? ? ? ? m = [i for i,n in enumerate(sum(self.matrix,[])) if not n]
? ? ? ? if m:
? ? ? ? ? ? i = sample(m, 1)[0]
? ? ? ? ? ? self.matrix[i//n][i%n] = sum(sample([1,1,1,2],1))

或者:

? ? def insert(self):
? ? ? ? n = self.order
? ? ? ? m = [(i,j) for j in range(n) for i in range(n) if not self.matrix[i][j]]
? ? ? ? if m:
? ? ? ? ? ? i, j = sample(m, 1)[0]
? ? ? ? ? ? self.matrix[i][j] = sum(sample([1,1,1,2],1))

為加快數字的拼合速度,從5隊開始,除了只插入1和2,可以考慮加入更大的數字:

self.matrix[i][j] = sum(sample([1,1,1,2]*3+([1,2,3,3]+[i for i in range(n+4,n,-1)] if n>4 else []),1))

如 n = 5 時,擬插入的各數字比例為:

>>> n = 5
>>> t = [1,1,1,2]*3+[1,2,3,3]+[i for i in range(n+4,n,-1)]
>>> for i in set(t):
... ? ? print([i,t.count(i)/20])
...?
... ? ??
[1, 0.5]
[2, 0.2]
[3, 0.1]
[6, 0.05]
[7, 0.05]
[8, 0.05]
[9, 0.05]?

三、 合并和遞增

? ?......? ? ?
? ?for i,array in enumerate(self.matrix):
? ? ? ? ? ? self.matrix[i] = Matrix.update(array)
? ? ......
? ? def update(array):
? ? ? ? split = lambda a: [_ for _ in a if _]+[_ for _ in a if not _]
? ? ? ? array = split(array)
? ? ? ? for i,a in enumerate(array):
? ? ? ? ? ? if i and a and a==array[i-1]:
? ? ? ? ? ? ? ? array[i-1] += 1
? ? ? ? ? ? ? ? array[i] = 0
? ? ? ? return split(array)

四、 判斷和移動

略……寫得有點復雜,可以到完整代碼中閱讀。

五、 鍵盤控制

引入keyboard庫控制鍵盤,示例如下:

import keyboard  def keys0():  print("Left key pressed")  def keys1():  print("Right key pressed")  def keys2():  print("Up key pressed")  def keys3():  print("Down key pressed")  def restart():  print("Enter key pressed")  # 添加熱鍵  
keyboard.add_hotkey('left', keys0)  
keyboard.add_hotkey('right', keys1)  
keyboard.add_hotkey('up', keys2)  
keyboard.add_hotkey('down', keys3)  
keyboard.add_hotkey('enter', restart)  # 等待用戶按下esc鍵  
print("Waiting for ESC to exit...")  
keyboard.wait('esc')  # 在這里移除所有熱鍵  
print("Removing all hotkeys...")  
keyboard.unhook_all_hotkeys()

Waiting for ESC to exit...
Left key pressed
Right key pressed
Up key pressed
Down key pressed
Enter key pressed
Removing all hotkeys...
>>>?

注:最后一行代碼keyboard.unhook_all_hotkeys()很關鍵,一定都有否則即使按了ESC鍵退出程序,熱鍵還是駐留在內存里,鍵盤還會響應keyboard.add_hotkey()添加的熱鍵。


完整源代碼

import keyboard
from random import sampleclass Matrix:def __init__(self, order=4):self.over = Falseself.order = orderself.matrix = self.new()self.victory = Falsedef __repr__(self):m, n = [], len(str(2**max(sum(self.matrix,[]))))for mat in self.matrix:m.append(', '.join(f'{2**x if x else 0:>{n}}' for x in mat))return '],\n ['.join(m).join(['[[',']]'])def new(self):n = self.orderm = sample([0]*(n*n-2)+sample([0,1,1],2),n*n)return  [m[i*n:i*n+n] for i in range(n)]def show(self):if self.over or self.victory:print('Enter to restart...')else:print(self)print()def insert(self):n = self.orderm = [(i,j) for j in range(n) for i in range(n) if not self.matrix[i][j]]if m:i, j = sample(m, 1)[0]self.matrix[i][j] = sum(sample([1,1,1,2],1))def full(self):return all(sum(self.matrix,[]))def move(self, direction=0):if self.over or self.victory: returndirection %= 4if direction == 0:  #leftif self.cannotmove(0): returnelif direction == 1:  #rightif self.cannotmove(1): returnself.matrix = self.flipH()elif direction == 2:  #upif self.cannotmove(2): returnself.matrix = self.rotL()elif direction == 3:  #downif self.cannotmove(3): returnself.matrix = self.rotR()for i,array in enumerate(self.matrix):self.matrix[i] = Matrix.update(array)if direction == 1:self.matrix = self.flipH()elif direction == 2:self.matrix = self.rotR()elif direction == 3:self.matrix = self.rotL()indexmax = max(sum(self.matrix,[]))if self.order==2 and indexmax==4 or self.order==3 and indexmax==7 or indexmax==self.order+7:self.victory = Trueprint(self)print('Win! Enter to restart...')returnself.insert()self.over = self.cannotmove()if self.over:print(self)print('Gave over!')def cannotmove(self, direction = 4):m, n = self.matrix, self.rotR()p, q = self.rotL(), self.flipH()if direction==0:return all(n[0]) and Matrix.cannotupdate(m)elif direction==1:return all(n[-1]) and Matrix.cannotupdate(q)elif direction==2:return all(m[0]) and Matrix.cannotupdate(n)elif direction==3:return all(m[-1]) and Matrix.cannotupdate(p)else:return (self.full() and self.cannotmove(0) and self.cannotmove(1)and self.cannotmove(2) and self.cannotmove(3))def cannotupdate(matrix):return all([m==Matrix.update(m) for m in matrix])def update(array):split = lambda a: [_ for _ in a if _]+[_ for _ in a if not _]array = split(array)for i,a in enumerate(array):if i and a and a==array[i-1]:array[i-1] += 1array[i] = 0return split(array)def flipH(self):m, n = self.matrix, self.orderreturn [[m[i][n-j-1] for j in range(n)] for i in range(n)]def flipV(self):m, n = self.matrix, self.orderreturn [[m[n-j-1][i] for i in range(n)] for j in range(n)]def rotL(self):m, n = self.matrix, self.orderreturn [[m[j][n-i-1] for j in range(n)] for i in range(n)]def rotR(self):m, n = self.matrix, self.orderreturn [[m[n-j-1][i] for j in range(n)] for i in range(n)]def move(i):mat.move(i)mat.show()
def keys0():  move(0)
def keys1():  move(1)
def keys2():  move(2)
def keys3():  move(3)
def restart():global matif mat.victory:mat.order += 1mat = Matrix(mat.order)mat.show()if mat.over:if mat.order>3:mat.order -= 1mat = Matrix(mat.order)mat.show()if __name__ == '__main__':print("《2048小游戲》")print("上下左右前頭控制方向,按ESC退出...") mat = Matrix(2)mat.show()keyboard.add_hotkey('left', keys0)keyboard.add_hotkey('right', keys1) keyboard.add_hotkey('up', keys2)keyboard.add_hotkey('down', keys3)keyboard.add_hotkey('enter', restart)keyboard.wait('esc')  # 等待用戶按下esc鍵退出print('bye!')keyboard.unhook_all_hotkeys()  # 退出后移除所有熱鍵

玩法過程

《2048小游戲》
上下左右前頭控制方向,按ESC退出...
[[0, 0],
?[0, 2]]

[[0, 0],
?[2, 2]]

[[0, 4],
?[0, 4]]

[[0, 2],
?[0, 8]]

[[2, 2],
?[8, 0]]

[[4, 2],
?[8, 0]]

[[4, 4],
?[8, 2]]

[[8, 2],
?[8, 2]]

[[ 0, ?0],
?[16, ?4]]
Win! Enter to restart...
Enter to restart...
[[0, 2, 0],
?[0, 0, 2],
?[0, 0, 0]]

[[0, 0, 0],
?[2, 0, 0],
?[0, 2, 2]]

[[4, 0, 0],
?[0, 0, 2],
?[0, 0, 4]]

[[0, 2, 0],
?[0, 0, 2],
?[4, 0, 4]]

[[0, 0, 2],
?[0, 0, 2],
?[4, 0, 8]]

[[0, 0, 2],
?[0, 2, 2],
?[0, 4, 8]]

[[0, 0, 0],
?[0, 2, 4],
?[2, 4, 8]]

[[2, 0, 0],
?[2, 4, 0],
?[2, 4, 8]]

[[2, 0, 0],
?[2, 0, 0],
?[4, 8, 8]]

[[ 0, ?2, ?2],
?[ 0, ?0, ?2],
?[ 0, ?4, 16]]

[[ 0, ?0, ?0],
?[ 2, ?2, ?4],
?[ 0, ?4, 16]]

[[ 0, ?0, ?0],
?[ 0, ?4, ?4],
?[ 4, ?4, 16]]

[[ 2, ?0, ?0],
?[ 0, ?0, ?4],
?[ 4, ?8, 16]]

[[ 2, ?0, ?0],
?[ 2, ?0, ?4],
?[ 4, ?8, 16]]

[[ 2, ?0, ?0],
?[ 4, ?0, ?4],
?[ 4, ?8, 16]]

[[ 0, ?4, ?0],
?[ 2, ?0, ?4],
?[ 8, ?8, 16]]

[[ 0, ?2, ?4],
?[ 0, ?2, ?4],
?[ 0, 16, 16]]

[[ 2, ?2, ?4],
?[ 0, ?2, ?4],
?[ 0, ?0, 32]]

[[ 0, ?0, ?0],
?[ 2, ?0, ?8],
?[ 2, ?4, 32]]

[[ 0, ?0, ?0],
?[ 2, ?0, ?8],
?[ 4, ?4, 32]]

[[ 0, ?0, ?2],
?[ 0, ?2, ?8],
?[ 0, ?8, 32]]

[[ 0, ?0, ?2],
?[ 0, ?2, ?8],
?[ 2, ?8, 32]]

[[ 2, ?0, ?4],
?[ 2, ?8, ?0],
?[ 2, ?8, 32]]

[[ 0, ?0, ?2],
?[ 2, ?0, ?4],
?[ 4, 16, 32]]

[[ 2, ?0, ?2],
?[ 2, ?4, ?0],
?[ 4, 16, 32]]

[[ 0, ?0, ?4],
?[ 4, ?4, ?2],
?[ 4, 16, 32]]

[[ 2, ?0, ?4],
?[ 0, ?4, ?2],
?[ 8, 16, 32]]

[[ 2, ?2, ?4],
?[ 0, ?4, ?2],
?[ 8, 16, 32]]

[[ 0, ?4, ?4],
?[ 2, ?4, ?2],
?[ 8, 16, 32]]

[[ 2, ?0, ?4],
?[ 2, ?8, ?2],
?[ 8, 16, 32]]

[[ 0, ?2, ?4],
?[ 4, ?8, ?2],
?[ 8, 16, 32]]

[[ 2, ?4, ?2],
?[ 4, ?8, ?2],
?[ 8, 16, 32]]

[[ 2, ?4, ?2],
?[ 4, ?8, ?4],
?[ 8, 16, 32]]
Gave over!
Enter to restart...

注:二階方陣玩出16就過關,三階方陣玩出128就過關,四階就要到2048才能過關,五階則要到4096才過關,六階以上類推。演示時玩到三階方陣就over了,如果三階方陣過關會自動升級到四階方陣,以此類推。


本文完

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/718356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718356.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第十六天-爬蟲selenium庫

目錄 1.介紹 2.使用 selenium 1.安裝 2.使用 1.測試打開網頁,抓取雷速體育日職乙信息 2.通過xpath查找 3.輸入文本框內容 send_keys 4.點擊事件 click 5.獲取網頁源碼: 6.獲取cookies 7.seleniumt提供元素定位方式:8種 8.控制瀏覽…

Spring Security OAuth2如何自定義返回的 Token 信息

文章目錄 Spring Security OAuth2如何自定義返回的 Token 信息定制不透明令牌的信息Springsecurity-oauth2之TokenEndPoint參考Spring Security OAuth2如何自定義返回的 Token 信息 Spring Boot+OAuth2,如何自定義返回的 Token 信息? 參考URL: https://www.jianshu.com/p/b7…

【Go】指針的聲明和初始化

package mainimport "fmt"func main() {// 聲明一個整數變量var num int 42// 聲明一個指向整數的指針變量,并將其初始化為指向整數變量的地址var ptr *int &num// 打印整數變量的值和指針變量的值(即整數變量的地址)fmt.Pri…

2024第24屆中國國際工業博覽會新能源與智能網聯汽車展電池制造展館

2024第24屆中國國際工業博覽會新能源與智能網聯汽車展電池制造展館 時間:2024年9月24日-28日 地點:國家會展中心(上海) 主辦單位:工業和信息化部、國家發展和改革委員會、科學技術部、商務部、中國科學院、中國工程…

【游記】GDOI2024

GDOI2024游記 老年退役選手。NOIP 218 分,GDOI 純純旅游。 Day -5 周日返校,開始停課。 開始攢 rp。 Day -4 模擬賽,犯困,啥也不會。 下午打球。 Day -3 模擬賽,不困,還是啥也不會。 下午打球。 …

CSS3單獨制作移動端頁面布局方式(流式布局、flex彈性布局)

目錄 1. 流式布局(百分比布局)2. flex彈性布局(強烈推薦)2.1 介紹2.2 Flex容器常見屬性2.2.1 flex-direction2.2.2 justify-content2.2.3 flex-wrap2.2.4 align-items2.2.5 align-content2.2.6 flex-flow 2.3 Flex項目常見屬性2.3.1 flex2.3.2 align-self和order 1. 流式布局(百…

銀河麒麟之Workstation安裝

一、VMware Workstation簡介 VMware Workstation是一款由VMware公司開發的虛擬化軟件,它允許用戶在一臺物理計算機上運行多個操作系統,并在每個操作系統中運行多個虛擬機。VMware Workstation提供了一個可視化的用戶界面,使用戶可以輕松創建、…

程序環境和預處理(2)

文章目錄 3.2.7 命名約定 3.3 #undef3.4 命令行定義3.5 條件編譯3.6 文件包含3.6.1 頭文件被包含的方式3.6.2 嵌套文件包含 4. 其他預處理指令 3.2.7 命名約定 一般來講函數和宏的使用語法很相似,所以語言本身沒法幫我們區分二者,那我們平時的一個習慣是…

linux條件判斷之if-then

if..then是最常見的條件判斷語句,簡而言之,就是當符合某個條件判斷的時候,就予以進行某項工作。 1.if-then格式 if-then格式1: if [ 條件判斷表達式 ];then 當條件判斷表達式成立時,需執行的命令 fi if-then格式2…

Redis安全加固策略:綁定Redis監聽的IP地址 修改默認端口 禁用或者重命名高危命令

Redis安全加固策略:綁定Redis監聽的IP地址 & 修改默認端口 & 禁用或者重命名高危命令 1.1 綁定Redis監聽的IP地址1.2 修改默認端口1.3 禁用或者重命名高危命令1.4 附:redis配置文件詳解(來源于網絡) 💖The Beg…

驅動開發面試復習

創建字符設備 1 創建設備號 alloc_chrdev_region 2.創建cdev cdev_init 3.添加一個 cdev,完成字符設備注冊到內核 cdev_add 4.創建類 class_create 5.創建設備 device_create 1.內核空間與用戶空間數據 copy_from_user 和copy_to_user 倆個函數來完成。 copy_from_user 函數…

618快遞準點到達,別忘了感謝它!

進入6月以來,全國快遞日均業務量飛速上漲。 雖然618大促是電商的主場,但作為不可或缺的物流環節,為了這場年中大考,快遞企業在此期間也使盡渾身解數,競相比拼配送速度。那么,為了更快的時效,快遞…

uniapp 的video播放如何實現小窗功能

在頁面中使用<video>組件來展示視頻&#xff0c;并設置好相應的屬性和事件監聽&#xff1a; <video src"video.mp4" play"onVideoPlay" pause"onVideoPause"></video>在頁面的data中定義一個變量來表示是否開啟小窗模式&#…

【Wio Terminal】使用WiFi(3)- Wi-F的高級使用

使用WiFi&#xff08;3&#xff09; Wi-F的高級使用HTTPClient 的使用HTTP GETHTTPs GETHTTP POSTWebServerHTTP Authentication Web ServerDNSServermDNSmDNS-SDWiFiManager Wi-F的高級使用 本節介紹了一些WiFi的高級庫用法&#xff0c;如HTTPClient、DNSServer和WebServer庫…

美國亞利桑那州立大學宣布與OpenAI建立合作伙伴關系!

美國亞利桑那州立大學 (Arizona State University) 在官網宣布—— 將與OpenAI建立合作伙伴關系&#xff01; 該校也成為了第一個與OpenAI合作的高等教育機構。 來源&#xff1a;亞利桑那州立大學官網 亞利桑那州立大學校長表示&#xff1a; “我們認識到人工智能系統將持續…

高并發IO底層原理淺析(四)

Java NIO中的Selector&#xff08;選擇器&#xff09;是一個用于檢測多個非阻塞通道&#xff08;Channel&#xff09;是否準備就緒進行讀寫操作的關鍵組件&#xff0c;它實現了I/O多路復用技術。在單個線程中&#xff0c;Selector可以監聽和管理多個Channel上的事件&#xff0c…

Redis安全加固策略:配置文件權限設置 配置本地日志存儲目錄 連接超時時間限制

Redis安全加固策略&#xff1a;配置文件權限設置 & 配置本地日志存儲目錄 & 連接超時時間限制 1.1 配置文件權限設置1.2 配置本地日志存儲目錄1.3 連接超時時間限制 &#x1f496;The Begin&#x1f496;點點關注&#xff0c;收藏不迷路&#x1f496; 1.1 配置文件權限…

如何理解template<size_t N>?

template<size_t N> 是C中的模板參數&#xff0c;用于定一個非類型參數的值。它可以在編譯時確定&#xff0c;并且可以在編譯時進行計算和使用。 例如&#xff0c;我們可以定義一個模板函數&#xff0c;接受一個大小為N的數組作為參數&#xff1a; template<size_t …

Qt/事件分發器/事件過濾器

事件分發器 //事件分發器bool event(QEvent* e); //事件分發器&#xff1a;&#xff1a;用途 分發事件 bool MyLabel::event(QEvent* e) {if(e->type() QEvent::MouseButtonPress){//如果是鼠標摁下 攔截事件 不向下分發QMouseEvent* ev static_cast<QMouseEvent*>…

Qt-Qss 樣式表屬性大全

目錄 前言 源碼文件信息 QSS屬性大全 1.控件常用的屬性 2.控件常用屬性值 3.控件常用狀態 4.其他 前言 相信很大一部分開發者真的被Qt樣式表的屬性搞挺頭痛的&#xff01; 一方面Qss的示例Demo太過簡單&#xff0c; 另一方面&#xff0c;Qss的所有屬性在Qt的官方文…