pygame實現井字棋之第三步邏輯優化
一、前言
先說一下本期的目標。
首先我們在判斷出輸贏、平局的時候,隻有一個控制臺輸出,很明顯不符合我們遊戲的排面(doge
另外,之前的邏輯有一個漏洞,就是玩傢一定是先手(就是第一個下棋的人,這個也需要修改)。
還有,有一個短暫的彈窗顯示到誰瞭,遊戲的可玩性就會有提高。
最後一個就是,如果點擊位置有問題,我們需要顯示。
二、渲染問題
翻車瞭,之前的邏輯是將九宮格和背景顏色寫死,而且之前都是直接在之前的基礎上渲染,但是我們的彈窗需要在結束後及時撤下來,所以需要我們不斷的重新渲染界面。
得,改吧。
首先,我們就不需要使用draw.rect方法創建矩形瞭,而是使用另外一個pygame.Rect函數。
同時,為瞭省去九行基本相同的代碼,我創建瞭一個元組來存儲。
格子創建最新版:
# 表示九個格子 rect = [0]*9 rect_wh = [ (1,1), (single+3,1), (single*2+5,1), (1,single+3), (single+3,single+3), (single*2+5,single+3), (1,single*2+5), (single+3,single*2+5), (single*2+5,single*2+5) ] for i in range(len(rect)): rect[i] = pygame.Rect(*rect_wh[i],single,single) rect[i] = Lattice(rect[i],screen)
Rect函數:
傳入x、y坐標以及高度寬度,就能創建一個rect對象。
這裡需要解釋的是*rect_wh[i],後面的部分就是在元組列表中找到一個指定的元素,而星號的作用是將元組進行解封裝。
三、封裝和解封裝
a, b = 1, 2
首先,我們將後面的兩個變量封裝成一個元組,從而賦值給等號前面的部分;
而前面為兩個變量,所以我們還需要進行解封裝,也就是將一個元組拆分成一個個的變量。
當時記錄的筆記:
回到之前的格子問題,還有一個細節就是我們應該怎麼顯示格子周圍的分割線,之前采用的是繪制矩形時自帶的,現在因為刷新的問題,不能再使用瞭(不然每刷新一次創建9個矩形並繪制,這誰頂得住)。
我的辦法是:減小瞭single的大小:
single = width/3 - 1
應該會註意到的,元組列表中我修改瞭(x,y)的值,這樣我們就能繪制出這樣的一個圖形:
(原創不易,整這個眼睛都快要瞎瞭,還是沒有很完美 -_-||)
bg_color = (0, 0, 0), 黑色。
我們還有個draw.rect方法,傳入screen,(255, 255, 255),rect對象,我們就可以顯示一個白色的矩形瞭。
因為寬高小瞭一點,所以我們就能看到很棒的邊界(比我自己畫的好多瞭)
(啊,為什麼是黃色的啊,因為我把bg_color改瞭……,問題不大)
當前的update方法:
def update(): screen.fill((255,228,181)) for i in rect: pygame.draw.rect(screen,(255, 255, 255),i.rect) i.draw()
四、彈窗顯示
添加的彈窗:
輸贏、平局彈窗,3s後退出程序;
哪方下棋、下棋的位置有問題,0.3s後自己退出。
看過我大戰外星人系列應該知道,有一個很大的遺憾就是給定的button類有一點專用,導致我後來隻能自己添加按鈕類。
這次,我自己寫的彈窗類的適用性會更高一些。
popup.py
"""在遊戲過程中,添加各種彈窗""" import pygame class Popup(): def __init__(self, screen,msg): self.msg = msg self.screen = screen self.bg_color = (0, 0, 0) self.text_color = (230, 230, 230) self.font = pygame.font.SysFont(None,48) self.msg_image = self.font.render(msg,True,self.text_color,self.bg_color) self.msg_rect = self.msg_image.get_rect() self.screen_rect = self.screen.get_rect() self.msg_rect.center = self.screen_rect.center self.screen.blit(self.msg_image,self.msg_rect)
傳入一個要顯示的信息,然後就可以渲染到屏幕上瞭。
方法都是之前的,看這篇博客。
(所以適用性高是不是因為基本上沒什麼內容……)
第一種情況(以平局為例):
Popup(screen,"draw") pygame.display.flip() time.sleep(3) exit()
調用類(調用一次就完瞭,不需要再使用實例)
顯示屏幕
掛起三秒
退出程序
第二種情況下,我選擇”computer choice”作為案例,也就是輪到電腦操作:
Popup(srceeen,"computer choice”) pygame.display.filp() time.sleep(0.3)
但這樣,彈窗是不會自己消失的,所以我們還需要在後面跟一個update方法。
哦對瞭,還有一個沒有講怎麼實現
五、實現判斷點擊是否有效
elif event.type == pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y = pygame.mouse.get_pos() # 判斷玩傢是否點擊成功 success = 0 for i in rect: if not i.stats and i.rect.collidepoint(mouse_x,mouse_y): # 如果點擊有效,將變量置為1 if not success: update(0.3,"you can't choose here!")
六、update優化
看瞭一下,基本上隻有兩種情況,一個是正常的update,另一個是需要跟彈窗和延時。
def update(time_sleep=0,msg=""): screen.fill((255,228,181)) for i in rect: pygame.draw.rect(screen,(255, 255, 255),i.rect) i.draw() if msg: Popup(screen,msg) pygame.display.flip() if time_sleep: time.sleep(time_sleep)
對於正常的刷新,隻需要調用update(),如果是需要彈窗和延時的,就自己加變量來處理。
主循環部分:
while not judge: update() for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y = pygame.mouse.get_pos() # 判斷玩傢是否點擊成功 success = 0 for i in rect: # 確定玩傢下瞭一步 if not i.stats and i.rect.collidepoint(mouse_x,mouse_y): success = 1 # 玩傢下棋 i.stats = -1 update() win_or_lose() # 電腦下棋 update(0.3,"Computer choice!") computer() update() win_or_lose() update(0.3,"your choice!") if not success: update(0.3,"you can't choose here!")
computer函數部分:
def computer(): """電腦的回合,隨機生成一個位置""" global judge random_num = [i for i in range(len(rect)) if not rect[i].stats] # 沒位子下瞭,平局 if not random_num: update(3,"draw") exit() rect[random.choice(random_num)].stats = 1
判斷輸贏部分:
def win_or_lose(): global judge stats1 = [i for i in range(len(rect)) if rect[i].stats == 1] stats2 = [i for i in range(len(rect)) if rect[i].stats == -1] win_list = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ] for i in win_list: if i == [j for j in i if j in stats1]: update(3,"Computer win!") exit() elif i == [j for j in i if j in stats2]: update(3,"You win!") exit()
七、先手問題
這個,還是交給隨機數。
使用random.randint(0,1)產生一個0/1,來判斷先手,
如果先手是電腦,使用(0,8)選擇一個將其stats置為1
代碼:
def first_hand(): """判斷先手,如果隨機數為1,則電腦先手""" x = random.randint(0,1) if x: x = random.randint(0,8) rect[x].stats = 1
循環開始前調用一下就行瞭。
八、結語
整體的遊戲就實現瞭,很簡單的一個,卻能加深對pygame模塊的使用。
往期博客:
pygame實現井字棋——1.繪制九宮格
pygame實現井字棋——2.邏輯實現
到此這篇關於pygame實現井字棋之第三步邏輯優化的文章就介紹到這瞭,更多相關pygame井字棋遊戲內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- pygame實現井字棋之第二步邏輯實現
- pygame實現井字棋之第一步繪制九宮格
- python實戰之利用pygame實現貪吃蛇遊戲(二)
- Python Pygame實現落球遊戲詳解
- pygame實現滑塊接小球遊戲