利用Python還原方陣游戲詳解
一、前言
寫這篇文章的靈感來源于我玩游戲的時候(為了避免過不了審就不說是啥游戲了),看見一個大佬在游戲里面建造了“還原方陣游戲”,就感覺很牛掰,就想著python不是有矩陣嗎,可不可以還原一下呢?
說干就干,我寫的那個蜘蛛紙牌用了一星期,寫這玩意兒只用了2小時,估計是有了經(jīng)驗吧。
這篇文章會手把手教你完成這個小游戲,算是新手的numpy練手程序了。寫作不易,支持一波~
二、游戲規(guī)則
其實這個游戲我也不知道叫啥,就是自己瞎編的名字(bushi。
游戲規(guī)則:有一個方陣,里面有的點位有棋子,有的點位沒有棋子,我會給出每行每列的棋子個數(shù),請復(fù)原這個方陣。注:如果棋子之間有空位就用空格代替。例如這個方陣:
棋 空 空
棋 空 棋
空 空 棋
第一列里面有兩個連續(xù)的棋子,那我就給出2。第二列里沒有棋子,那我就啥也不給。第三列里有兩個連續(xù)棋子,那我就給出2。
第一行里有一個棋子,那我就給出1。第二行里有一個棋子,空一格又有一個棋子,那我就給出1 1。第三行里有一個棋子,那我就給出1。
通過給出的信息,請還原方陣。
這個游戲是對邏輯思維的推理。為了方便用戶操作,我們給出另一個矩陣,讓用戶在上面標注,當(dāng)標注矩陣=正確矩陣就結(jié)束游戲。
三、numpy模塊
寫代碼之前,我們先了解一下numpy模塊。
numpy模塊,就是矩陣模塊,其中有很多很多的函數(shù),讓我們完成矩陣的相關(guān)操作。
安裝numpy模塊,首先你要有python,之后要有萬能的pip包(沒有自己網(wǎng)上查怎么下載)。之后,我們win+R,輸入cmd打開熟悉的命令行,輸入:
pip install numpy
等一會兒,如果沒出現(xiàn)錯誤就是安裝成功了。之后輸入:
pip list
來查看pip包所有安裝的模塊,有numpy就是成功了。
numpy,其實和嵌套列表差不多,但是人家操作十分方便,有許多函數(shù)都是嵌套列表做不到的。
numpy可以在很多方面發(fā)光發(fā)熱,因為它不像其他模塊那樣,專門做游戲,專門做網(wǎng)站,專門爬蟲等等啥的,無論是什么方面,都常常遇到矩陣,可以說是個金牌輔助了。我之前那做的那個蜘蛛紙牌游戲也是用的他。
numpy的賦值有很多方法,如果你要給其中一個位置賦值,那就要用二級索引,在numpy里面第一個數(shù)字代表第幾行,第二個代表第幾列。注意要用下標數(shù)字哦!例如我們要把一個叫做a的矩陣的第一行第二列變成0,那我們就a[0][1]=0。
接下來,我們就開始寫程序吧!
四、第一步:大循環(huán)and獲取規(guī)格
首先,我們設(shè)置一個規(guī)則:還原矩陣5次時候就勝利了。用while把主體程序套進大框架里面。
為了能調(diào)整不同的大小,我們可以獲取用戶的輸入來調(diào)整規(guī)格。
首先,我們要來幫用戶正骨,就用while True和try-except。
為啥要用他倆兄弟呢?首先,try-except的作用是在用戶輸入不正確或不符合規(guī)定時作出處理,while True則是為了作出處理之后讓用戶重新來輸入一遍。
我們現(xiàn)在就規(guī)定:規(guī)格有4種,讓用戶3x3輸入3,4x4輸入4,5x5輸入5,6x6輸入6。用戶的數(shù)字就必須在3到6之間。
但是如果用戶輸入的是其他數(shù)字呢?
沒事,我們可以用一個條件判斷,如果數(shù)字不是3~6之間就直接掏出raise,拋出異常,程序轉(zhuǎn)移到except那邊。是不是很完美?
別看這樣寫字多了,這是排除所有其他輸入還能正確運行的最佳方案。
那么該怎么退出循環(huán)呢?
nonono,不要想太復(fù)雜了,只要程序執(zhí)行完了還沒有報錯就說明輸入正確,直接加break就行了。
win=0#初始化變量 while win<=5:#主體程序大循環(huán) while True:#while True出山 try:#try出山 guige=int(input("輸入規(guī)格,3x3輸入3,4x4輸入4,5x5輸入5,6x6輸入6"))#獲取用戶輸入 if guige<3 or guige>6:#輸入必須在3到6的數(shù)字之間 raise(VauleError())#否則直接報錯 break#如果程序到了最后還沒有報錯就退出循環(huán),正常執(zhí)行 except:#如果報錯 print("請正確輸入")#讓用戶重新輸入
嗯,就是這樣。第一步,我們就做好了。
五、第二步:初始化棋盤
上文說了,我們要用兩個矩陣,第一個矩陣是正確的矩陣,我們?nèi)∶鹹es_numpy。第二個矩陣是嘗試的矩陣,我們?nèi)∶鹴ry_numpy。這里,我們就用1代表棋子,0代表沒有棋子。
但是try_numpy矩陣沒有標記的位置該怎么弄呢?
這就要用上我們的None了。
None是一個奇怪的值,轉(zhuǎn)化布爾類型為False,他不是0也不是空值,就是啥也沒有。例如你硬要獲取一個沒有返回值的函數(shù)的返回值,那就是None。
矩陣的值雖然不能為字符串,但是可以為None??!
我們要把矩陣的所有值變?yōu)镹one。用兩個嵌套for循環(huán)賦值就行了。
yes_numpy矩陣,則是要0和1隨機。還是用兩個嵌套for循環(huán),賦值0或1的隨機數(shù)。
為了方便,我們把numpy取名為np,random取名為r。
正確程序如下:
import random as r#導(dǎo)入random模塊 import numpy as np#導(dǎo)入numpy模塊 print("正在生成題目…")#提示 yes_numpy=np.zeros((guige,guige))#yes_numpy為全0矩陣 try_numpy=np.zeros((guige,guige))#try_numpy為全0矩陣 for i in range(guige):#第一層循環(huán)為行 for j in range(guige):#第二層循環(huán)為列 try_numpy[i][j]=None#try_numpy全部賦值為None print(try_numpy)#輸出try_numpy for i in range(guige):#第一層循環(huán)為行 for j in range(guige):#第二層循環(huán)為列 yes_numpy[i][j]=r.choice((1,0))#yes_numpy賦值為1 0隨機數(shù)
六、第三步:標注矩陣功能(難)
接下來是主要的程序部分了。
首先,我們要獲取用戶進行的操作。目前更新5個操作:標注矩陣填1,查看標注矩陣填2,勝利偵測填3,查看行列信息填4,重新開始填5。
由于這些操作要重復(fù)執(zhí)行,我們就要用一個while True擴起來。
獲取用戶操作,還是while True和try-except組合,還有raise和break的使用,和第一步思路一樣。但是我們外層已經(jīng)有一個循環(huán)了,所以可以省下來一個while,break可以換成continue。
我們先來完成標注矩陣功能,就是標注try_numpy。如果獲取到的回答是1時就執(zhí)行以下程序。
之后我們還要讓用戶輸入自己要改變的位置的行、列和改變成0還是1還是None,還要再加一層while True和try-except!
知道為啥讓你們有注釋和減少層級了吧?寫這樣的程序的時候經(jīng)常循環(huán)套循環(huán),太亂了!寫到這里已經(jīng)是第五層程序了。
我這么做也是有原因的,因為上一個寫的蜘蛛紙牌程序比較大型,用起來很卡,時間也長,容易輸入錯誤,并且不知道為啥輸入的時候總是自動彈出來一個cde fg,不知道你們有沒有這種問題,導(dǎo)致報錯。這個程序就長教訓(xùn)了。
輸入超出矩陣范圍或者修改的不是0或1,這兩個異常都要考慮到,把異常扼殺在搖籃之中,給用戶的反骨徹底正了。
修改矩陣,很簡單,弄上對應(yīng)的修改位置再修改就行。
以上思路可能理解不了,那就結(jié)合著代碼理解吧:
while True:#游戲開始 try:#還是熟悉的try caozuo=int(input("輸入操作,標注矩陣填1,查看目前改變矩陣填2,勝利偵測填3,查看行列信息填4,重新開始填5。"))#詢問操作 if caozuo<1 or caozuo>4:#必須1到4之內(nèi) raise(ValueError())#報錯 except:#如果錯誤 print("請正確輸入")#提示 continue#從頭開始 if caozuo==1:#如果操作是1 while True: try:#老兩樣 gai_hang,gai_lie,gai_neirong=map(int,input("輸入標注位置的行、列(下標),以及改變成0還是1(用空格隔開三個值)\n").split())#詢問三個標注信息 if gai_neirong<0 or gai_neirong>1:#內(nèi)容非0即1 print("只能改變成0和1,",end="")#提示 raise(ValueError())#報錯 if gai_hang>=guige or gai_lie>=guige:#行列不能超出矩陣規(guī)格 print("輸入超出規(guī)格,",end="")#提示 raise(ValueError())#報錯 break#如果沒有異常就退出循環(huán) except:#如果異常 print("請正確輸入")#提示 try_numpy[gai_hang][gai_lie]=gai_neirong#賦值 print("標注成功")#提示 continue#從頭開始,節(jié)約時間
這部分比較難,建議好好理解理解,消化消化。
七、第四步:查看標注矩陣功能
接下來是查看標注矩陣的功能。
我們把問題轉(zhuǎn)換一下,不就是輸出try_numpy嘛?
if caozuo==2:#如果要查看標注矩陣 print(try_numpy)#直接輸出 continue#從頭開始,節(jié)約時間
是不是簡簡單單?
八、第五步:勝利偵測
為了節(jié)省運行時間,我們換成當(dāng)輸入3之后才進行勝利偵測。
我們不能直接比較兩個矩陣是否相等,這時候就要用上numpy里面的函數(shù)——all()了。放上兩個矩陣,兩個等號連接就可以比較兩個矩陣是否相等。返回True或者False。
if caozuo==3:#如果要檢測是否勝利 if np.all(yes_numpy==try_numpy):#如果兩個矩陣全部相等 print("你勝利了!")#提示 zhuangtai="win"#改變變量 break#退出循環(huán) else:#否則 print("還不對哦!")#提示 continue#從頭開始
這些程序都是在那個while True的循環(huán)里,所以我們可以用break退出,再回到while win<5那個循環(huán)里。這里建議結(jié)合下面的完整代碼理解。
這里新建變量zhuangtai是因為后面還有重新開始功能,我們要知道是因為獲勝還是重新開始退出的大循環(huán)。
九、第六步:查看行列信息(難)
接下來,完成查看行列信息的程序。
由于矩陣全隨機,我們也只能自己去偵測行列信息。
我們設(shè)置一個計數(shù)變量:shu。
思路如下:如果偵測到1,則shu自增。
如果偵測到0且前一項為1,則輸出shu+空格,之后shu清零。
如果偵測到0且前一項為0,則不輸出,可以不偵測。
如果結(jié)束之后shu不是0,輸出shu且換行。
一行一行,一類一列挨個偵測輸出。
具體程序如下,好好消化消化:
shu=0 if caozuo==4:#如果要查看行列信息 for i in range(guige):#每一行 print("第",i,"行:")#提示到底是第幾行 for j in range(guige):#每一列 if yes_numpy[i][j]==1:#如果矩陣的這一格為1 shu+=1#shu自增 if yes_numpy[i][j]==0:#如果矩陣的這一格為0 if shu!=0:#且前一格不是0(直接偵測shu的狀態(tài)效果一樣) print(shu,end="")#輸出shu shu=0#shu清零 if shu!=0:#如果結(jié)束之后shu不為0 print(shu)#輸出shu要換行 shu=0#shu清零 print()#輸出空行之后顯示列 shu=0#初始化變量 #以下程序是把遍歷行列進行交換,來達到不用改變主體偵測矩陣列的效果 for j in range(guige): print("第",j,"列:") for i in range(guige): if yes_numpy[i][j]==1: shu+=1 if yes_numpy[i][j]==0: if shu!=0: print(shu,end="") shu=0 if shu!=0: print(shu) shu=0 print()
十、第七步:重新開始功能
矩陣重新開始,直接break就行,但要改一下zhuangtai。
#內(nèi)層循環(huán)的程序 if caozuo==5:#如果操作是5 zhuangtai="0"#狀態(tài)區(qū)分 break#直接退出循環(huán) #這里是最外層循環(huán)的程序 if zhuangtai=="win":#如果是因為獲勝退出的循環(huán) win+=1#win自增
十一、得分與完善and完整代碼
我們還可以加上得分功能,再完善一下程序,用變量defen記錄得分,增加一下玩家的優(yōu)越感。
連接以上程序,完善各種bug,最終程序如下:
import numpy as np import random as r win=0 defen=500 shu=0 print("游戲開始。游戲規(guī)則:我會給出一個矩陣,并且給出每行每列有幾個1的個數(shù)信息,如果有兩個數(shù)字代表有兩個空,舉個例子:\n[[ 1,1,1]\n[0,0,1]\n[1,0,0]]\n在這個列表中,例如第0列為1,0,1,有兩個間斷的1那我就給出1 1,第1列有1 0 0,那我就給出1,第2列為1,1,0,有兩個不間斷的1那我就給出2。\p,請復(fù)原這個矩陣。\n另外還有分數(shù)系統(tǒng),標注錯一次-10分,標注對一次+10分,初始500分,獲勝了+規(guī)格x50分。\n勝5局即可勝利。\n") while win<=5: while True: try: guige=int(input("輸入規(guī)格,3x3輸入3,4x4輸入4,5x5輸入5,6x6輸入6")) if guige<3 or guige>6: raise(VauleError()) break except: print("請正確輸入") print("正在生成題目…") yes_numpy=np.zeros((guige,guige)) try_numpy=np.zeros((guige,guige)) for i in range(guige): for j in range(guige): try_numpy[i][j]=None print(try_numpy) for i in range(guige): for j in range(guige): yes_numpy[i][j]=r.choice((1,0)) print(yes_numpy) while True:#游戲開始 try: caozuo=int(input("輸入操作,標注矩陣填1,查看目前改變矩陣填2,勝利偵測填3,查看行列信息填4,重新開始填5。")) if caozuo<1 or caozuo>4: raise(ValueError()) except: print("請正確輸入") continue if caozuo==1: while True: try: gai_hang,gai_lie,gai_neirong=map(int,input("輸入標注位置的行、列(下標),以及改變成0還是1(用空格隔開三個值)\n").split()) if gai_neirong<0 or gai_neirong>1: print("只能改變成0和1,",end="") raise(ValueError()) if gai_hang>=guige or gai_lie>=guige: print("輸入超出規(guī)格,",end="") raise(ValueError()) break except: print("請正確輸入") try_numpy[gai_hang][gai_lie]=gai_neirong if try_numpy[gai_hang][gai_lie]==yes_numpy[gai_hang][gai_lie]: defen+=10 else: defen-=10 print("標注成功") continue if caozuo==2: print(try_numpy) continue if caozuo==3: if np.all(yes_numpy==try_numpy): print("你勝利了!") zhuangtai="win" defen+=200 break else: print("還不對哦!") continue if caozuo==4: for i in range(guige): print("第",i,"行:") for j in range(guige): if yes_numpy[i][j]==1: shu+=1 if yes_numpy[i][j]==0: if shu!=0: print(shu,end="") shu=0 if shu!=0: print(shu) shu=0 print() shu=0 for j in range(guige): print("第",j,"列:") for i in range(guige): if yes_numpy[i][j]==1: shu+=1 if yes_numpy[i][j]==0: if shu!=0: print(shu,end="") shu=0 if shu!=0: print(shu) shu=0 print() if caozuo==5: zhuangtai= "0 " break if zhuangtai=="win": win+=1 print("獲勝達到5局!你真厲害!目前的分:",defen)
注:代碼的第26和31行為了方便測試直接輸出了兩個矩陣,玩的之后刪了這兩行代碼就行。
到此這篇關(guān)于利用Python還原方陣游戲詳解的文章就介紹到這了,更多相關(guān)Python還原方陣游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決pytorch 損失函數(shù)中輸入輸出不匹配的問題
這篇文章主要介紹了解決pytorch 損失函數(shù)中輸入輸出不匹配的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Python利用socket實現(xiàn)多進程的端口掃描器
作為開發(fā)人員經(jīng)常需要查看服務(wù)的端口開啟狀態(tài)判斷服務(wù)是否宕機。特別是部署的服務(wù)比較多的情況下,可能存在幾個甚至幾十個服務(wù)端口的占用。所以本文將利用socket實現(xiàn)多進程的端口掃描器,需要的可以參考一下2022-12-12Python3+SQLAlchemy+Sqlite3實現(xiàn)ORM教程
這篇文章主要介紹了Python3+SQLAlchemy+Sqlite3實現(xiàn)ORM教程,需要的朋友可以參考下2021-02-02Python微醫(yī)掛號網(wǎng)醫(yī)生數(shù)據(jù)抓取
今天小編就為大家分享一篇關(guān)于Python微醫(yī)掛號網(wǎng)醫(yī)生數(shù)據(jù)抓取,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01python3.6之xlwt如何設(shè)置單元格對齊方式
這篇文章主要介紹了python3.6之xlwt如何設(shè)置單元格對齊方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06