您好,登錄后才能下訂單哦!
本文實例為大家分享了pygame五子棋游戲的具體代碼,供大家參考,具體內容如下
1.設置棋盤
五子棋標準棋盤是15x15的,如果我們每個格子的大小是40x40的話,棋盤應該是40x(15-1)=560的寬度,我們在四面各保留60的邊距,那么窗口的長寬各是40x(15-1)+60x2
# -*- coding=utf-8 -*- import random import pygame pygame.init() space = 60 # 四周留下的邊距 cell_size = 40 # 每個格子大小 cell_num = 15 grid_size = cell_size * (cell_num - 1) + space * 2 # 棋盤的大小 screencaption = pygame.display.set_caption('FIR') screen = pygame.display.set_mode((grid_size,grid_size)) #設置窗口長寬 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() screen.fill((0,0,150)) # 將界面設置為藍色 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() # 必須調用update才能看到繪圖顯示
2.落子
首先我們定義一個chess_arr數組用于存儲落到棋盤上的棋子
chess_arr = []
然后在游戲主循環監聽下鼠標彈起事件,然后在捕捉到鼠標彈起事件時獲取鼠標位置并把位置添加進chess_arr
for event in pygame.event.get(): …… if event.type == pygame.MOUSEBUTTONUP: # 鼠標彈起 x, y = pygame.mouse.get_pos() # 獲取鼠標位置 chess_arr.append((x,y))
最后我們在pygame.display.update()前將棋子繪制出來看看效果
可以看到,現在已經能點出棋子了,但是棋子的位置不是縱橫線的交叉點,所以我們必須對鼠標位置進行取整,不能把x,y這個位置加的這么隨意,處理下x,y位置的代碼如下
for event in pygame.event.get(): …… if event.type == pygame.MOUSEBUTTONUP: # 鼠標彈起 x, y = pygame.mouse.get_pos() # 獲取鼠標位置 xi = int(round((x - space)*1.0/cell_size)) # 獲取到x方向上取整的序號 yi = int(round((y - space)*1.0/cell_size)) # 獲取到y方向上取整的序號 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))
現在發現落子位置靠譜多了
為了代碼的可讀性更好點,以后一些棋盤計算更方便,我們把放入chess_arr數組的絕對坐標改成放入的是格子的序號,也就是把
chess_arr.append((xi*cell_size+space,yi*cell_size+space))
改成
chess_arr.append((xi,yi))
然后在畫棋子的地方也稍作修改,把
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)
接下來還有個問題,因為進到chess_arr數組前并沒有判斷某一位置是否已經有棋子,存在重復落子的情況,所以這邊還要多加個判斷,因為python語言夠強大,可以直接判斷是否包含tuple或者數組,所以只要多加一個(xi,yi) not in chess_arr的判斷就好了,開不開森~
for event in pygame.event.get(): …… if event.type == pygame.MOUSEBUTTONUP: # 鼠標彈起 …… 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 # 每個格子大小 cell_num = 15 grid_size = cell_size * (cell_num - 1) + space * 2 # 棋盤的大小 screencaption = pygame.display.set_caption('FIR') screen = pygame.display.set_mode((grid_size,grid_size)) #設置窗口長寬 chess_arr = [] while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONUP: # 鼠標彈起 x, y = pygame.mouse.get_pos() # 獲取鼠標位置 xi = int(round((x - space)*1.0/cell_size)) # 獲取到x方向上取整的序號 yi = int(round((y - space)*1.0/cell_size)) # 獲取到y方向上取整的序號 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)) # 將界面設置為藍色 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() # 必須調用update才能看到繪圖顯示
3.區分黑白子
這里常規的想法可能有這么兩種:1.chess_arr理論應該是黑白相間的,一個隔一個不同顏色畫就好了(這種在不考慮正規比賽五手兩打或者讓子的情況下是沒問題的) 2.往chess_arr里填(x,y)時多填一個黑白標記改成(x,y,flag) ,這里我們選擇第二種方案
首先,我們全局定義個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
再把畫棋的
for x, y in chess_arr: pygame.draw.circle(screen,(205,205,205), [x*cell_size+space, y*cell_size+space], 16,16)
改成
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)
現在看起來有點像那么回事了
4.判斷輸贏
判斷輸贏的關鍵當然還是使用chess_arr這個數組,這個數組用來判斷勝利并不太方便,我們把它轉一個15*15的二維數組來計算,轉換代碼如下
m = [[0]*15 for i in range(15)] # 先定義一個15*15的全0數組 for x, y, c in chess_arr: m[y][x] = 1 # 上面有棋則標1
我們把這代碼一起放到一個check_win(chess_arr, flag)函數里,用于判斷某一方是否勝利,基本流程是分別判斷最后一顆落下的子的橫線、豎線、斜線上是不是有5個以上子,有則返回True,函數代碼如下:
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)] # 先定義一個15*15的全0的數組,不能用[[0]*cell_num]*cell_num的方式去定義因為一位數組會被重復引用 for x, y, c in chess_arr: if c == flag: m[y][x] = 1 # 上面有棋則標1 lx = chess_arr[-1][0] # 最后一個子的x ly = chess_arr[-1][1] # 最后一個子的y dire_arr = [[(-1,0),(1,0)],[(0,-1),(0,1)],[(-1,-1),(1,1)],[(-1,1),(1,-1)]] # 4個方向數組,往左+往右、往上+往下、往左上+往右下、往左下+往右上,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
判斷函數完成了,我們再定一個全局變量用于保存游戲狀態
game_state = 1 # 游戲狀態1.表示正常進行 2.表示黑勝 3.表示白勝
我們在鼠標添加棋子的代碼后面做下修改,調用判斷勝利的函數
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()前加個游戲狀態判斷,用于顯示獲勝文字
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))
另外,鼠標事件判斷處也要做下修改,判斷下游戲狀態是不是游戲中
if game_state == 1 and event.type == pygame.MOUSEBUTTONUP: # 鼠標彈起
至此主要的代碼都完整了,下面是效果圖
最后貼下完整程序,這邊沒有做禁手的判斷和判輸,后面有時間再處理
# -*- coding=utf-8 -*- import random import pygame from pygame.locals import MOUSEBUTTONUP pygame.init() space = 60 # 四周留下的邊距 cell_size = 40 # 每個格子大小 cell_num = 15 grid_size = cell_size * (cell_num - 1) + space * 2 # 棋盤的大小 screencaption = pygame.display.set_caption('FIR') screen = pygame.display.set_mode((grid_size,grid_size)) #設置窗口長寬 chess_arr = [] flag = 1 # 1黑 2白 game_state = 1 # 游戲狀態1.表示正常進行 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)] # 先定義一個15*15的全0的數組,不能用[[0]*cell_num]*cell_num的方式去定義因為一位數組會被重復引用 for x, y, c in chess_arr: if c == flag: m[y][x] = 1 # 上面有棋則標1 lx = chess_arr[-1][0] # 最后一個子的x ly = chess_arr[-1][1] # 最后一個子的y dire_arr = [[(-1,0),(1,0)],[(0,-1),(0,1)],[(-1,-1),(1,1)],[(-1,1),(1,-1)]] # 4個方向數組,往左+往右、往上+往下、往左上+往右下、往左下+往右上,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: # 鼠標彈起 x, y = pygame.mouse.get_pos() # 獲取鼠標位置 xi = int(round((x - space)*1.0/cell_size)) # 獲取到x方向上取整的序號 yi = int(round((y - space)*1.0/cell_size)) # 獲取到y方向上取整的序號 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)) # 將界面設置為藍色 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() # 必須調用update才能看到繪圖顯示
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。