pygame實(shí)現(xiàn)五子棋游戲
本文實(shí)例為大家分享了pygame五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
1.設(shè)置棋盤(pán)
五子棋標(biāo)準(zhǔn)棋盤(pán)是15x15的,如果我們每個(gè)格子的大小是40x40的話,棋盤(pán)應(yīng)該是40x(15-1)=560的寬度,我們?cè)谒拿娓鞅A?0的邊距,那么窗口的長(zhǎng)寬各是40x(15-1)+60x2
# -*- coding=utf-8 -*-
import random
import pygame
pygame.init()
space = 60 # 四周留下的邊距
cell_size = 40 # 每個(gè)格子大小
cell_num = 15
grid_size = cell_size * (cell_num - 1) + space * 2 # 棋盤(pán)的大小
screencaption = pygame.display.set_caption('FIR')
screen = pygame.display.set_mode((grid_size,grid_size)) #設(shè)置窗口長(zhǎng)寬
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.fill((0,0,150)) # 將界面設(shè)置為藍(lán)色
for x in range(0,cell_size*cell_num,cell_size):
pygame.draw.line(screen,(200,200,200),(x+space,0+space),(x+space,cell_size*(cell_num-1)+space),1)
for y in range(0,cell_size*cell_num,cell_size):
pygame.draw.line(screen,(200,200,200),(0+space,y+space),(cell_size*(cell_num-1)+space,y+space),1)
pygame.display.update() # 必須調(diào)用update才能看到繪圖顯示

2.落子
首先我們定義一個(gè)chess_arr數(shù)組用于存儲(chǔ)落到棋盤(pán)上的棋子
chess_arr = []
然后在游戲主循環(huán)監(jiān)聽(tīng)下鼠標(biāo)彈起事件,然后在捕捉到鼠標(biāo)彈起事件時(shí)獲取鼠標(biāo)位置并把位置添加進(jìn)chess_arr
for event in pygame.event.get(): …… if event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)彈起 x, y = pygame.mouse.get_pos() # 獲取鼠標(biāo)位置 chess_arr.append((x,y))
最后我們?cè)趐ygame.display.update()前將棋子繪制出來(lái)看看效果

可以看到,現(xiàn)在已經(jīng)能點(diǎn)出棋子了,但是棋子的位置不是縱橫線的交叉點(diǎn),所以我們必須對(duì)鼠標(biāo)位置進(jìn)行取整,不能把x,y這個(gè)位置加的這么隨意,處理下x,y位置的代碼如下
for event in pygame.event.get(): …… if event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)彈起 x, y = pygame.mouse.get_pos() # 獲取鼠標(biāo)位置 xi = int(round((x - space)*1.0/cell_size)) # 獲取到x方向上取整的序號(hào) yi = int(round((y - space)*1.0/cell_size)) # 獲取到y(tǒng)方向上取整的序號(hào) if xi>=0 and xi<cell_num and yi>=0 and yi<cell_num: chess_arr.append((xi*cell_size+space,yi*cell_size+space))
現(xiàn)在發(fā)現(xiàn)落子位置靠譜多了

為了代碼的可讀性更好點(diǎn),以后一些棋盤(pán)計(jì)算更方便,我們把放入chess_arr數(shù)組的絕對(duì)坐標(biāo)改成放入的是格子的序號(hào),也就是把
chess_arr.append((xi*cell_size+space,yi*cell_size+space))
改成
chess_arr.append((xi,yi))
然后在畫(huà)棋子的地方也稍作修改,把
pygame.draw.circle(screen,(205,205,205), [x, y], 16,16)
改成
pygame.draw.circle(screen,(205,205,205), [x*cell_size+space, y*cell_size+space], 16,16)
接下來(lái)還有個(gè)問(wèn)題,因?yàn)檫M(jìn)到chess_arr數(shù)組前并沒(méi)有判斷某一位置是否已經(jīng)有棋子,存在重復(fù)落子的情況,所以這邊還要多加個(gè)判斷,因?yàn)閜ython語(yǔ)言夠強(qiáng)大,可以直接判斷是否包含tuple或者數(shù)組,所以只要多加一個(gè)(xi,yi) not in chess_arr的判斷就好了,開(kāi)不開(kāi)森~
for event in pygame.event.get(): …… if event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)彈起 …… if xi>=0 and xi<cell_num and yi>=0 and yi<cell_num and (xi,yi) not in chess_arr: chess_arr.append((xi,yi))
為免代碼偏差,先更新下目前的完整代碼
# -*- coding=utf-8 -*-
import random
import pygame
from pygame.locals import MOUSEBUTTONUP
pygame.init()
space = 60 # 四周留下的邊距
cell_size = 40 # 每個(gè)格子大小
cell_num = 15
grid_size = cell_size * (cell_num - 1) + space * 2 # 棋盤(pán)的大小
screencaption = pygame.display.set_caption('FIR')
screen = pygame.display.set_mode((grid_size,grid_size)) #設(shè)置窗口長(zhǎng)寬
chess_arr = []
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)彈起
x, y = pygame.mouse.get_pos() # 獲取鼠標(biāo)位置
xi = int(round((x - space)*1.0/cell_size)) # 獲取到x方向上取整的序號(hào)
yi = int(round((y - space)*1.0/cell_size)) # 獲取到y(tǒng)方向上取整的序號(hào)
if xi>=0 and xi<cell_num and yi>=0 and yi<cell_num and (xi,yi) not in chess_arr:
chess_arr.append((xi,yi))
screen.fill((0,0,150)) # 將界面設(shè)置為藍(lán)色
for x in range(0,cell_size*cell_num,cell_size):
pygame.draw.line(screen,(200,200,200),(x+space,0+space),(x+space,cell_size*(cell_num-1)+space),1)
for y in range(0,cell_size*cell_num,cell_size):
pygame.draw.line(screen,(200,200,200),(0+space,y+space),(cell_size*(cell_num-1)+space,y+space),1)
for x, y in chess_arr:
pygame.draw.circle(screen,(205,205,205), [x*cell_size+space, y*cell_size+space], 16,16)
pygame.display.update() # 必須調(diào)用update才能看到繪圖顯示
3.區(qū)分黑白子
這里常規(guī)的想法可能有這么兩種:1.chess_arr理論應(yīng)該是黑白相間的,一個(gè)隔一個(gè)不同顏色畫(huà)就好了(這種在不考慮正規(guī)比賽五手兩打或者讓子的情況下是沒(méi)問(wèn)題的) 2.往chess_arr里填(x,y)時(shí)多填一個(gè)黑白標(biāo)記改成(x,y,flag) ,這里我們選擇第二種方案
首先,我們?nèi)侄x個(gè)flag變量
flag = 1 # 1黑 2白
我們把
if xi>=0 and xi<cell_num and yi>=0 and yi<cell_num and (xi,yi) not in chess_arr: chess_arr.append((xi,yi))
這里改成
if xi>=0 and xi<cell_num and yi>=0 and yi<cell_num and (xi,yi,1) not in chess_arr and (xi,yi,2) not in chess_arr: chess_arr.append((xi,yi,flag)) flag = 2 if flag == 1 else 2
再把畫(huà)棋的
改成
for x, y, c in chess_arr: chess_color = (30,30,30) if c == 1 else (225,225,225) pygame.draw.circle(screen, chess_color, [x*cell_size+space, y*cell_size+space], 16,16)

現(xiàn)在看起來(lái)有點(diǎn)像那么回事了
4.判斷輸贏
判斷輸贏的關(guān)鍵當(dāng)然還是使用chess_arr這個(gè)數(shù)組,這個(gè)數(shù)組用來(lái)判斷勝利并不太方便,我們把它轉(zhuǎn)一個(gè)15*15的二維數(shù)組來(lái)計(jì)算,轉(zhuǎn)換代碼如下
m = [[0]*15 for i in range(15)] # 先定義一個(gè)15*15的全0數(shù)組 for x, y, c in chess_arr: m[y][x] = 1 # 上面有棋則標(biāo)1
我們把這代碼一起放到一個(gè)check_win(chess_arr, flag)函數(shù)里,用于判斷某一方是否勝利,基本流程是分別判斷最后一顆落下的子的橫線、豎線、斜線上是不是有5個(gè)以上子,有則返回True,函數(shù)代碼如下:
def get_one_dire_num(lx, ly, dx, dy, m): tx = lx ty = ly s = 0 while True: tx += dx ty += dy if tx < 0 or tx >= cell_num or ty < 0 or ty >= cell_num or m[ty][tx] == 0: return s s+=1 def check_win(chess_arr, flag): m = [[0]*cell_num for i in range(cell_num)] # 先定義一個(gè)15*15的全0的數(shù)組,不能用[[0]*cell_num]*cell_num的方式去定義因?yàn)橐晃粩?shù)組會(huì)被重復(fù)引用 for x, y, c in chess_arr: if c == flag: m[y][x] = 1 # 上面有棋則標(biāo)1 lx = chess_arr[-1][0] # 最后一個(gè)子的x ly = chess_arr[-1][1] # 最后一個(gè)子的y dire_arr = [[(-1,0),(1,0)],[(0,-1),(0,1)],[(-1,-1),(1,1)],[(-1,1),(1,-1)]] # 4個(gè)方向數(shù)組,往左+往右、往上+往下、往左上+往右下、往左下+往右上,4組判斷方向 for dire1,dire2 in dire_arr: dx, dy = dire1 num1 = get_one_dire_num(lx, ly, dx, dy, m) dx, dy = dire2 num2 = get_one_dire_num(lx, ly, dx, dy, m) if num1 + num2 + 1 >= 5: return True return False
判斷函數(shù)完成了,我們?cè)俣ㄒ粋€(gè)全局變量用于保存游戲狀態(tài)
game_state = 1 # 游戲狀態(tài)1.表示正常進(jìn)行 2.表示黑勝 3.表示白勝
我們?cè)谑髽?biāo)添加棋子的代碼后面做下修改,調(diào)用判斷勝利的函數(shù)
if check_win(chess_arr, flag): game_state = 2 if flag == 1 else 3 else: flag = 2 if flag == 1 else 1
最后在pygame.display.update()前加個(gè)游戲狀態(tài)判斷,用于顯示獲勝文字
if game_state != 1:
myfont = pygame.font.Font(None,60)
white = 210,210,0
win_text = "%s win"%('black' if game_state == 2 else 'white')
textImage = myfont.render(win_text, True, white)
screen.blit(textImage, (260,320))
另外,鼠標(biāo)事件判斷處也要做下修改,判斷下游戲狀態(tài)是不是游戲中
if game_state == 1 and event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)彈起
至此主要的代碼都完整了,下面是效果圖
最后貼下完整程序,這邊沒(méi)有做禁手的判斷和判輸,后面有時(shí)間再處理
# -*- coding=utf-8 -*-
import random
import pygame
from pygame.locals import MOUSEBUTTONUP
pygame.init()
space = 60 # 四周留下的邊距
cell_size = 40 # 每個(gè)格子大小
cell_num = 15
grid_size = cell_size * (cell_num - 1) + space * 2 # 棋盤(pán)的大小
screencaption = pygame.display.set_caption('FIR')
screen = pygame.display.set_mode((grid_size,grid_size)) #設(shè)置窗口長(zhǎng)寬
chess_arr = []
flag = 1 # 1黑 2白
game_state = 1 # 游戲狀態(tài)1.表示正常進(jìn)行 2.表示黑勝 3.表示白勝
def get_one_dire_num(lx, ly, dx, dy, m):
tx = lx
ty = ly
s = 0
while True:
tx += dx
ty += dy
if tx < 0 or tx >= cell_num or ty < 0 or ty >= cell_num or m[ty][tx] == 0: return s
s+=1
def check_win(chess_arr, flag):
m = [[0]*cell_num for i in range(cell_num)] # 先定義一個(gè)15*15的全0的數(shù)組,不能用[[0]*cell_num]*cell_num的方式去定義因?yàn)橐晃粩?shù)組會(huì)被重復(fù)引用
for x, y, c in chess_arr:
if c == flag:
m[y][x] = 1 # 上面有棋則標(biāo)1
lx = chess_arr[-1][0] # 最后一個(gè)子的x
ly = chess_arr[-1][1] # 最后一個(gè)子的y
dire_arr = [[(-1,0),(1,0)],[(0,-1),(0,1)],[(-1,-1),(1,1)],[(-1,1),(1,-1)]] # 4個(gè)方向數(shù)組,往左+往右、往上+往下、往左上+往右下、往左下+往右上,4組判斷方向
for dire1,dire2 in dire_arr:
dx, dy = dire1
num1 = get_one_dire_num(lx, ly, dx, dy, m)
dx, dy = dire2
num2 = get_one_dire_num(lx, ly, dx, dy, m)
if num1 + num2 + 1 >= 5: return True
return False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_state == 1 and event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)彈起
x, y = pygame.mouse.get_pos() # 獲取鼠標(biāo)位置
xi = int(round((x - space)*1.0/cell_size)) # 獲取到x方向上取整的序號(hào)
yi = int(round((y - space)*1.0/cell_size)) # 獲取到y(tǒng)方向上取整的序號(hào)
if xi>=0 and xi<cell_num and yi>=0 and yi<cell_num and (xi,yi,1) not in chess_arr and (xi,yi,2) not in chess_arr:
chess_arr.append((xi,yi,flag))
if check_win(chess_arr, flag):
game_state = 2 if flag == 1 else 3
else:
flag = 2 if flag == 1 else 1
screen.fill((0,0,150)) # 將界面設(shè)置為藍(lán)色
for x in range(0,cell_size*cell_num,cell_size):
pygame.draw.line(screen,(200,200,200),(x+space,0+space),(x+space,cell_size*(cell_num-1)+space),1)
for y in range(0,cell_size*cell_num,cell_size):
pygame.draw.line(screen,(200,200,200),(0+space,y+space),(cell_size*(cell_num-1)+space,y+space),1)
for x, y, c in chess_arr:
chess_color = (30,30,30) if c == 1 else (225,225,225)
pygame.draw.circle(screen, chess_color, [x*cell_size+space, y*cell_size+space], 16,16)
if game_state != 1:
myfont = pygame.font.Font(None,60)
white = 210,210,0
win_text = "%s win"%('black' if game_state == 2 else 'white')
textImage = myfont.render(win_text, True, white)
screen.blit(textImage, (260,320))
pygame.display.update() # 必須調(diào)用update才能看到繪圖顯示
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
對(duì)numpy中的transpose和swapaxes函數(shù)詳解
今天小編就為大家分享一篇對(duì)numpy中的transpose和swapaxes函數(shù)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
python關(guān)于圖片和base64互轉(zhuǎn)的三種方式
無(wú)論使用cv2、PIL還是直接讀取圖片的方法進(jìn)行圖片與Base64的轉(zhuǎn)換,核心步驟都涉及到二進(jìn)制格式的轉(zhuǎn)換,每種方法的基本過(guò)程都是:Base64轉(zhuǎn)二進(jìn)制,然后二進(jìn)制轉(zhuǎn)圖片,或反向操作,這些方法均基于二進(jìn)制與圖片轉(zhuǎn)換的基本原理2024-09-09
Python函數(shù)裝飾器實(shí)現(xiàn)方法詳解
這篇文章主要介紹了Python函數(shù)裝飾器實(shí)現(xiàn)方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Python函數(shù)裝飾器的概念、功能、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2018-12-12
Pytorch搭建簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)(CNN)實(shí)現(xiàn)MNIST數(shù)據(jù)集分類(lèi)任務(wù)
這篇文章主要介紹了Pytorch搭建簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)(CNN)實(shí)現(xiàn)MNIST數(shù)據(jù)集分類(lèi)任務(wù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Python執(zhí)行時(shí)間的幾種計(jì)算方法
這篇文章主要介紹了Python執(zhí)行時(shí)間的幾種計(jì)算方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
python的scipy實(shí)現(xiàn)插值的示例代碼
這篇文章主要介紹了python的scipy實(shí)現(xiàn)插值的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

