pygame開發(fā)-馬賽邏輯小游戲的代碼實(shí)現(xiàn)_第1頁(yè)
pygame開發(fā)-馬賽邏輯小游戲的代碼實(shí)現(xiàn)_第2頁(yè)
pygame開發(fā)-馬賽邏輯小游戲的代碼實(shí)現(xiàn)_第3頁(yè)
pygame開發(fā)-馬賽邏輯小游戲的代碼實(shí)現(xiàn)_第4頁(yè)
pygame開發(fā)-馬賽邏輯小游戲的代碼實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩7頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第pygame開發(fā):馬賽邏輯小游戲的代碼實(shí)現(xiàn)目錄一、游戲簡(jiǎn)介二、核心代碼解析三、pygame開發(fā)流程1、從創(chuàng)建窗口到棋盤繪制2、點(diǎn)擊方格改變顏色2.1、點(diǎn)擊事件2.2、碰撞檢測(cè)2.3、方格變色2.4、陣列轉(zhuǎn)換2.5、效果初見3、顯示提示信息四、游戲演示視頻

一、游戲簡(jiǎn)介

馬賽邏輯,是一個(gè)類似數(shù)獨(dú)和掃雷的邏輯小游戲,根據(jù)棋盤周圍的數(shù)據(jù)提示點(diǎn)亮方格,因外形像馬賽克而得名。在手機(jī)游戲中有多款A(yù)PP可以體驗(yàn)該游戲,如Peak、Nonogram、Crossme等。但在PC端,筆者暫時(shí)還未發(fā)現(xiàn)復(fù)刻版,于是打算自己動(dòng)手實(shí)現(xiàn)一番。

馬賽邏輯的基本玩法如下圖所示,上側(cè)橫向的各組數(shù)字為:對(duì)每一列中存在的目標(biāo)方格的標(biāo)注,如2表示該列有2個(gè)連續(xù)的目標(biāo),12表示該列有1個(gè)獨(dú)立的目標(biāo)+2個(gè)連續(xù)的目標(biāo)。左側(cè)縱向的各組數(shù)據(jù)為對(duì)每一行的標(biāo)注。通過上、左兩側(cè)的提示,將所有目標(biāo)方格點(diǎn)亮即為通關(guān)。

二、核心代碼解析

在正式開始游戲開發(fā)之前,我們可以先想想實(shí)現(xiàn)這個(gè)項(xiàng)目的關(guān)鍵點(diǎn)在哪。首先,方格有選中和未選中兩種狀態(tài),那可以用1表示選中、0表示未選中。要判斷玩家點(diǎn)亮的方格是否正確,只需將方塊矩陣映射成01矩陣,再與答案矩陣對(duì)比即可。如此一來,出題也很容易,隨機(jī)生成一串01組合即可。

而最重要的地方在于,如何生成提示數(shù)值?我們需要分別對(duì)每行每列進(jìn)行遍歷,找出單獨(dú)的1和連續(xù)的1。下面以棋盤的一行為例進(jìn)行說明。

首先,準(zhǔn)備一個(gè)列表類型的變量remind用于儲(chǔ)存多個(gè)提示數(shù)值,并準(zhǔn)備一個(gè)位移標(biāo)記flag用于記錄當(dāng)前是在答案陣列的哪一位進(jìn)行判斷,以及一個(gè)數(shù)值記錄num,再將答案陣列[0,1,1,0,1,0,0,1]傳入計(jì)數(shù)器。

當(dāng)傳入陣列長(zhǎng)度大于1時(shí)有四種情況,分別是:①當(dāng)前位0,次位1;②當(dāng)前位1,次位0;③連續(xù)多位1;④連續(xù)多位0。根據(jù)不同情況進(jìn)行位移,將新的陣列傳入計(jì)數(shù)器,并在1換0的時(shí)候記錄數(shù)值。

當(dāng)傳入陣列等于1時(shí)有兩種情況,分別是:①上位0;②上位1。根據(jù)不同的情況記錄數(shù)值。

按照這個(gè)思路,我們可以用一個(gè)簡(jiǎn)單的遞歸來實(shí)現(xiàn)這個(gè)提示算法,代碼如下:

defget_line_remind(_line):#輸出一行或一列的提示

remind=[]#一行或一列的提示記錄

num=0#提示值

deffun(line):

nonlocalremind,num

flag=0#位移

iflen(line)1:

ifline[0]==0andline[1]==1:

flag+=1

elifline[0]==line[1]==0:

flag+=2

elifline[0]==1andline[1]==0:

num+=1

remind.append(num)

num=0

flag+=2

elifline[0]==line[1]==1:

num+=1

flag+=1

fun(line[flag:])

eliflen(line)andline[0]:

ifnum:

remind.append(num+1)

else:

remind.append(1)

fun(_line)

returnremind

三、pygame開發(fā)流程

1、從創(chuàng)建窗口到棋盤繪制

棋盤的設(shè)計(jì)及玩法已經(jīng)初具雛形了,可以正式開始制作游戲了啦!~筆者采用了有超過20年歷史的游戲制作庫(kù)pygame,該游戲庫(kù)包含了用于制作簡(jiǎn)單2D游戲的基本套件,python及游戲愛好者們已經(jīng)用它制作了成千上萬(wàn)的小游戲,使用pip安裝即可使用。

第一步,對(duì)各類游戲元素的顏色、位置、尺寸等必要參數(shù)做一些設(shè)置。接著,初始化pygame,繪制一個(gè)指定大小的窗口,使用pygame.font.Font()加載指定的字體文件,以防游戲打包后運(yùn)行出錯(cuò)。

需要注意的是,pygame的所有視覺元素都建立在不斷地重新繪制上,利用pygame.display.flip()進(jìn)行整體更新。因?yàn)楹笃谛枰诎咨尘爸刑砑觿?dòng)態(tài)元素,所以將背景繪制放入主循環(huán)的首位。

在主循環(huán)中,通過遍歷事件來獲取玩家的操作,當(dāng)前僅追蹤了一個(gè)退出事件。

importpygame

importsys

#參數(shù)設(shè)置----------------------------------

blue=(159,197,232)#被選中方格的顏色

gray=(217,217,217)#棋盤網(wǎng)格線顏色

gold=(255,215,0)#游戲記錄文字顏色

black=(0,0,0)

white=(255,255,255)

start_x=240#棋盤左上角位置

start_y=150

size=2#一行/列的方塊個(gè)數(shù)

square=320#棋盤邊長(zhǎng)

length=int(square/size)#每個(gè)方塊的邊長(zhǎng)

#游戲初始化----------------------------------

pygame.init()

screen=pygame.display.set_mode((780,520))#創(chuàng)建窗口

font=pygame.font.Font(r'./data/msyh.ttf',20)#提示字體

#主循環(huán)----------------------------------

whileTrue:

screen.fill(white)#背景填充

foreventinpygame.event.get():

ifevent.type==pygame.QUIT:

pygame.quit()#退出pygame

sys.exit()#安全退出系統(tǒng)

pygame.display.flip()#更新全部顯示

運(yùn)行以上代碼可以得到一片空白(霧)。

下一步,我們來想想怎么繪制棋盤。首先,棋盤本身的尺寸是固定的,我們只需修改棋盤中的方格數(shù)量和大小,來改變棋局。因此,在第一步的參數(shù)設(shè)置中,使用start_x、start_y來確定棋盤的位置,并設(shè)置棋盤的邊長(zhǎng)square=320,以及一行中方塊的個(gè)數(shù)size和方塊邊長(zhǎng)length。

因?yàn)榉綁K是可以被點(diǎn)擊而改變顏色的,所以我們要先自定義一個(gè)方塊類。機(jī)制比較簡(jiǎn)單,初始化即傳入坐標(biāo)和邊長(zhǎng),調(diào)用pygame.draw.rect()來繪制矩形。

classItem:#自定義方塊類

def__init__(self,pos_x,pos_y,leng):

self.rect=pygame.draw.rect(screen,gray,[pos_x,pos_y,leng,leng],0)

self.state=False

再定義一個(gè)繪制棋盤的方法,從棋盤左上角開始,橫豎各畫size個(gè)方塊,返回方塊對(duì)象列表。

defcreate_chessboard():#創(chuàng)建棋盤

item_lst=[]

forvinrange(size):

forhinrange(size):

rect=Item(start_x+h*length,start_y+v*length,length)

item_lst.append(rect)

returnitem_lst

由于方塊初始顏色和背景色一樣是白色,還需要加上網(wǎng)格線,橫豎各畫size+1條線,調(diào)用pygame.draw.line()繪制線條。

defdraw_line():#繪制網(wǎng)格線

forninrange(size+1):

start=(start_x,start_y+n*length)

end=(start_x+square,start_y+n*length)

pygame.draw.line(screen,gray,start,end,2)

forninrange(size+1):

start=(start_x+n*length,start_y)

end=(start_x+n*length,start_y+square)

pygame.draw.line(screen,gray,start,end,2)

將主循環(huán)代碼修改如下,注意:網(wǎng)格線是繪制在整個(gè)圖層組的最上層,才不會(huì)被方格和背景覆蓋掉。運(yùn)行即可繪制出初始棋盤,如圖為4X4的規(guī)格。

##前文參數(shù)、初始化略

......

items=create_chessboard()#創(chuàng)建棋盤

whileTrue:

screen.fill(white)#背景填充

foreventinpygame.event.get():

ifevent.type==pygame.QUIT:

pygame.quit()#退出pygame

sys.exit()#安全退出系統(tǒng)

draw_line()#繪制棋盤網(wǎng)格線

pygame.display.flip()#更新全部顯示

2、點(diǎn)擊方格改變顏色

2.1、點(diǎn)擊事件

在事件遍歷中添加對(duì)鼠標(biāo)點(diǎn)擊事件的追蹤,并獲取點(diǎn)擊坐標(biāo),之后通過判斷點(diǎn)擊的位置是否在某個(gè)方格中,即可得知是哪個(gè)方格被點(diǎn)擊了,并作出顏色修改。

ifevent.type==pygame.MOUSEBUTTONDOWN:#鼠標(biāo)點(diǎn)擊事件

x,y=event.pos

2.2、碰撞檢測(cè)

那么來寫一個(gè)判斷方法,將之前創(chuàng)建棋盤時(shí)得到的方塊對(duì)象列表,和鼠標(biāo)坐標(biāo)傳入,遍歷方塊并通過矩形的collidepoint()方法進(jìn)行碰撞檢測(cè),若鼠標(biāo)碰撞到了矩形區(qū)域,就對(duì)方塊的狀態(tài)取反。

defcheck_click(item_lst,pos_x,pos_y):#更新每個(gè)方塊的點(diǎn)擊狀態(tài)

foriinitem_lst:

ifi.rect.collidepoint(pos_x,pos_y):

i.state=bool(1-i.state)

2.3、方格變色

defchange_color(item_lst):#根據(jù)狀態(tài)改變方塊顏色

foriinitem_lst:

ifi.state:

pygame.draw.rect(screen,blue,i.rect,0)

else:

pygame.draw.rect(screen,white,i.rect,0)

2.4、陣列轉(zhuǎn)換

再來寫一個(gè)獲取玩家操作陣列的方法,利用列表生成式將方塊狀態(tài)轉(zhuǎn)換為01列表。

defcreate_answer_array():#創(chuàng)建答案矩陣

lst=[1ifrandom()0.5else0for_inrange(size*size)]

iflist(set(lst))[0]==0:

lst[0]=1

returnlst

并通過隨機(jī)生成的方式來創(chuàng)建答案,之后通過比較兩個(gè)列表即可判斷游戲是否通關(guān)。別忘了,答案陣列中不能全都是0。

defcreate_answer_array():#創(chuàng)建答案矩陣

lst=[1ifrandom()0.5else0for_inrange(size*size)]

iflist(set(lst))[0]==0:

lst[0]=1

returnlst

2.5、效果初見

修改主循環(huán)代碼如下,運(yùn)行后嘗試點(diǎn)擊可見效果。

##前文參數(shù)、初始化略

......

answer=create_answer_array()#創(chuàng)建答案矩陣

#主循環(huán)----------------------------------

whileTrue:

screen.fill(white)#背景填充

foreventinpygame.event.get():

ifevent.type==pygame.QUIT:

pygame.quit()#退出pygame

sys.exit()#安全退出系統(tǒng)

ifevent.type==pygame.MOUSEBUTTONDOWN:#鼠標(biāo)點(diǎn)擊事件

x,y=event.pos

check_click(items,x,y)#檢查選中的方格,修改狀態(tài)

result=get_player_array(items)#獲取方格操作矩陣

print(result)

ifresult==answer:

print("YOUWIN!")

change_color(items)#根據(jù)方格狀態(tài)修改顏色

draw_line()#繪制棋盤網(wǎng)格線

pygame.display.flip()#更新全部顯示

3、顯示提示信息

沒有提示只能盲點(diǎn)怎么玩呀!趕緊把提示信息搞出來(ε(#)☆╰╮o(皿///)

前文我們已經(jīng)了解了提示算法,接下來就根據(jù)答案矩陣來整理兩側(cè)的提示信息。

defget_w_remind(answer_lst):#根據(jù)答案矩陣輸出提示列表

h_remind=[]

v_remind=[]

h_array=[answer_lst[i:i+size]foriinrange(0,len(answer_lst),size)]#橫向矩陣

forhinh_array:

h_remind.append(get_line_remind(h))

v_array=list(map(list,zip(*h_array)))#縱向矩陣

forvinv_array:

v_remind.append(get_line_remind(v))

returnh_remind,v_remind

由于筆者是直接使用一維列表來代替矩陣的,因此如果要獲取每一行的提示,則需要按照size將將答案陣列分割成多份。而要獲取每一列的提示時(shí),則需要對(duì)分割好的橫向矩陣進(jìn)行行列轉(zhuǎn)置。

之后,通過億點(diǎn)點(diǎn)數(shù)學(xué)計(jì)算得到兩側(cè)信息的顯示坐標(biāo),利用窗口對(duì)象的blit()方法將渲染好的文本對(duì)象貼上去。對(duì)橫/縱陣列逆序的目的是,將多個(gè)提示數(shù)值從外到內(nèi)顯示,以符合閱讀習(xí)慣。

defshow_remind(answer_lst):#在棋盤兩側(cè)對(duì)應(yīng)位置顯示每行/列的提示

h_remind,v_remind=get_w_remind(answer_lst)

fori,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論