目錄
- 一、前言
- 二、渲染問題
- 三、封裝和解封裝
- 四、彈窗顯示
- 五、實(shí)現(xiàn)判斷點(diǎn)擊是否有效
- 六、update優(yōu)化
- 七、先手問題
- 八、結(jié)語
一、前言
先說一下本期的目標(biāo)。
首先我們在判斷出輸贏、平局的時(shí)候,只有一個(gè)控制臺(tái)輸出,很明顯不符合我們游戲的排面(doge
另外,之前的邏輯有一個(gè)漏洞,就是玩家一定是先手(就是第一個(gè)下棋的人,這個(gè)也需要修改)。
還有,有一個(gè)短暫的彈窗顯示到誰了,游戲的可玩性就會(huì)有提高。
最后一個(gè)就是,如果點(diǎn)擊位置有問題,我們需要顯示。
二、渲染問題
翻車了,之前的邏輯是將九宮格和背景顏色寫死,而且之前都是直接在之前的基礎(chǔ)上渲染,但是我們的彈窗需要在結(jié)束后及時(shí)撤下來,所以需要我們不斷的重新渲染界面。
得,改吧。
首先,我們就不需要使用draw.rect方法創(chuàng)建矩形了,而是使用另外一個(gè)pygame.Rect函數(shù)。
同時(shí),為了省去九行基本相同的代碼,我創(chuàng)建了一個(gè)元組來存儲(chǔ)。
格子創(chuàng)建最新版:
# 表示九個(gè)格子
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函數(shù):
傳入x、y坐標(biāo)以及高度寬度,就能創(chuàng)建一個(gè)rect對(duì)象。
這里需要解釋的是*rect_wh[i],后面的部分就是在元組列表中找到一個(gè)指定的元素,而星號(hào)的作用是將元組進(jìn)行解封裝。
三、封裝和解封裝
a, b = 1, 2
首先,我們將后面的兩個(gè)變量封裝成一個(gè)元組,從而賦值給等號(hào)前面的部分;
而前面為兩個(gè)變量,所以我們還需要進(jìn)行解封裝,也就是將一個(gè)元組拆分成一個(gè)個(gè)的變量。
當(dāng)時(shí)記錄的筆記:
回到之前的格子問題,還有一個(gè)細(xì)節(jié)就是我們應(yīng)該怎么顯示格子周圍的分割線,之前采用的是繪制矩形時(shí)自帶的,現(xiàn)在因?yàn)樗⑿碌膯栴},不能再使用了(不然每刷新一次創(chuàng)建9個(gè)矩形并繪制,這誰頂?shù)米。?br />
我的辦法是:減小了single的大?。?/p>
應(yīng)該會(huì)注意到的,元組列表中我修改了(x,y)的值,這樣我們就能繪制出這樣的一個(gè)圖形:
(原創(chuàng)不易,整這個(gè)眼睛都快要瞎了,還是沒有很完美 -_-||)
bg_color = (0, 0, 0), 黑色。
我們還有個(gè)draw.rect方法,傳入screen,(255, 255, 255),rect對(duì)象,我們就可以顯示一個(gè)白色的矩形了。
因?yàn)閷捀咝×艘稽c(diǎn),所以我們就能看到很棒的邊界(比我自己畫的好多了)
(啊,為什么是黃色的啊,因?yàn)槲野裝g_color改了……,問題不大)
當(dāng)前的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后自己退出。
看過我大戰(zhàn)外星人系列應(yīng)該知道,有一個(gè)很大的遺憾就是給定的button類有一點(diǎn)專用,導(dǎo)致我后來只能自己添加按鈕類。
這次,我自己寫的彈窗類的適用性會(huì)更高一些。
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)
傳入一個(gè)要顯示的信息,然后就可以渲染到屏幕上了。
方法都是之前的,看這篇博客。
(所以適用性高是不是因?yàn)榛旧蠜]什么內(nèi)容……)
第一種情況(以平局為例):
Popup(screen,"draw")
pygame.display.flip()
time.sleep(3)
exit()
調(diào)用類(調(diào)用一次就完了,不需要再使用實(shí)例)
顯示屏幕
掛起三秒
退出程序
第二種情況下,我選擇"computer choice”作為案例,也就是輪到電腦操作:
Popup(srceeen,"computer choice”)
pygame.display.filp()
time.sleep(0.3)
但這樣,彈窗是不會(huì)自己消失的,所以我們還需要在后面跟一個(gè)update方法。
哦對(duì)了,還有一個(gè)沒有講怎么實(shí)現(xiàn)
五、實(shí)現(xiàn)判斷點(diǎn)擊是否有效
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
# 判斷玩家是否點(diǎn)擊成功
success = 0
for i in rect:
if not i.stats and i.rect.collidepoint(mouse_x,mouse_y):
# 如果點(diǎn)擊有效,將變量置為1
if not success:
update(0.3,"you can't choose here!")
六、update優(yōu)化
看了一下,基本上只有兩種情況,一個(gè)是正常的update,另一個(gè)是需要跟彈窗和延時(shí)。
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)
對(duì)于正常的刷新,只需要調(diào)用update(),如果是需要彈窗和延時(shí)的,就自己加變量來處理。
主循環(huán)部分:
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()
# 判斷玩家是否點(diǎn)擊成功
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函數(shù)部分:
def computer():
"""電腦的回合,隨機(jī)生成一個(gè)位置"""
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()
七、先手問題
這個(gè),還是交給隨機(jī)數(shù)。
使用random.randint(0,1)產(chǎn)生一個(gè)0/1,來判斷先手,
如果先手是電腦,使用(0,8)選擇一個(gè)將其stats置為1
代碼:
def first_hand():
"""判斷先手,如果隨機(jī)數(shù)為1,則電腦先手"""
x = random.randint(0,1)
if x:
x = random.randint(0,8)
rect[x].stats = 1
循環(huán)開始前調(diào)用一下就行了。
八、結(jié)語
整體的游戲就實(shí)現(xiàn)了,很簡單的一個(gè),卻能加深對(duì)pygame模塊的使用。
往期博客:
pygame實(shí)現(xiàn)井字棋——1.繪制九宮格
pygame實(shí)現(xiàn)井字棋——2.邏輯實(shí)現(xiàn)
到此這篇關(guān)于pygame實(shí)現(xiàn)井字棋之第三步邏輯優(yōu)化的文章就介紹到這了,更多相關(guān)pygame井字棋游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- pygame實(shí)現(xiàn)井字棋之第二步邏輯實(shí)現(xiàn)
- pygame實(shí)現(xiàn)井字棋之第一步繪制九宮格
- pygame可視化幸運(yùn)大轉(zhuǎn)盤實(shí)現(xiàn)
- pygame多種方式實(shí)現(xiàn)屏保操作(自動(dòng)切換、鼠標(biāo)切換、鍵盤切換)
- 詳解pygame捕獲鍵盤事件的兩種方式
- python+pygame實(shí)現(xiàn)代碼雨(黑客帝國既視感)
- Pygame做一期吃豆子游戲的示例代碼
- Python3+Pygame實(shí)現(xiàn)射擊游戲完整代碼