python實(shí)現(xiàn)五子棋游戲(pygame版)
本文實(shí)例為大家分享了python五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
目錄
- 簡(jiǎn)介
- 實(shí)現(xiàn)過(guò)程
- 結(jié)語(yǔ)
簡(jiǎn)介
使用python實(shí)現(xiàn)pygame版的五子棋游戲;
環(huán)境:Windows系統(tǒng)+python3.8.0
游戲規(guī)則:
1.分兩位棋手對(duì)戰(zhàn),默認(rèn)黑棋先下;當(dāng)在棋盤點(diǎn)擊左鍵,即在該位置繪制黑棋;
2.自動(dòng)切換到白棋,當(dāng)在棋盤點(diǎn)擊左鍵,即在該位置繪制白棋;
3.輪流切換棋手下棋,當(dāng)那方先形成5子連線者獲勝(橫、豎、斜、反斜四個(gè)方向都可以)。
游戲運(yùn)行效果如下:

實(shí)現(xiàn)過(guò)程
1.新建文件settings.py,用來(lái)定義一些必須的基本屬性和初始值;
class Settings(): def __init__(self): """初始化的游戲配置""" # 屏幕寬高 self.width = 700 self.height = 554 # 文字顏色和大小 self.fontsize = 14 self.fonttype = 'simsunnsimsun' # 棋盤格數(shù) self.number = 15 # 棋盤左邊距、上邊距和間隔 self.bd_left = 30 self.bd_top = 30 self.bd_space = 36 # 判斷游戲是否結(jié)束(默認(rèn)開(kāi)始) self.game_active = True # 判斷哪方下棋(默認(rèn)黑子先寫) self.chess_player = 1 self.prompt_info = '當(dāng)前棋手:黑棋' # 開(kāi)始校驗(yàn)輸贏(兩邊合計(jì)9,因?yàn)橐呀?jīng)有一邊5步) self.win_number = 0 # 設(shè)置背景圖、黑棋圖片、白棋圖片路徑 self.checkerboard_bg = 'images/checkerboard_bg.png' self.black_chess = 'images/black_chess.png' self.white_chess = 'images/white_chess.png' # 存儲(chǔ)落子數(shù)據(jù) self.move_chess = []
2.新建文件checkerboard.py,主要用來(lái)繪制背景圖和棋格線;
import sys
import pygame
class Checkerboard():
def __init__(self, ck_settings, screen, position):
self.ck_settings = ck_settings
self.screen = screen
self.position = position
# 顏色和坐標(biāo)大小
self.text_color = (0, 0, 0)
self.font = pygame.font.SysFont(ck_settings.fonttype, ck_settings.fontsize)
# 存儲(chǔ)棋子坐標(biāo)
self.checkerboard = []
# 加載背景圖、黑棋和白棋(當(dāng)有圖片不存在時(shí),打印錯(cuò)誤并退出游戲)
try:
self.bg_image = pygame.image.load(ck_settings.checkerboard_bg)
self.black_image = pygame.image.load(ck_settings.black_chess).convert_alpha() # convert_alpha背景透明
self.white_image = pygame.image.load(ck_settings.white_chess).convert_alpha()
self.chess_rect = self.black_image.get_rect()
except Exception as e:
print('error:', e)
sys.exit()
def draw_board(self):
# 存儲(chǔ)棋子坐標(biāo)
for i in range(self.ck_settings.number):
self.checkerboard.append([])
for j in range(self.ck_settings.number):
self.checkerboard[i].append(self.position(self.ck_settings.bd_left + i * self.ck_settings.bd_space, self.ck_settings.bd_top + j * self.ck_settings.bd_space))
# 繪制棋盤坐標(biāo)
for i in range(0, self.ck_settings.number):
# ord返回字符的ASCII數(shù)值,chr再返回字符
x_text = self.font.render(chr(ord('A') + i), True, self.text_color) # A-O
y_text = self.font.render(str(i + 1), True, self.text_color) # 1-15
# 繪制xy軸坐標(biāo)(在棋盤背景圖繪制)
self.bg_image.blit(x_text, (self.checkerboard[i][0].x - x_text.get_width() / 2, self.checkerboard[i][0].y - 20))
self.bg_image.blit(y_text, (self.checkerboard[0][i].x - 20, self.checkerboard[0][i].y - y_text.get_height() / 2))
# 繪制橫豎線(在棋盤背景圖繪制)
pygame.draw.line(self.bg_image, self.text_color, self.checkerboard[0][i], self.checkerboard[self.ck_settings.number-1][i])
pygame.draw.line(self.bg_image, self.text_color, self.checkerboard[i][0], self.checkerboard[i][self.ck_settings.number-1])
# 繪制棋盤背景圖
self.screen.blit(self.bg_image, (0, 0))
3.新建文件infopanel.py,主要用來(lái)繪制棋盤右邊提示信息(暫時(shí)只有顯示下棋方和獲勝信息);
import pygame.font class Infopanel(): def __init__(self, ck_settings, screen): """初始化屬性""" self.settings = ck_settings self.screen = screen self.screen_rect = screen.get_rect() # 設(shè)置文字顏色和字體大小 self.info_color = (217, 8, 10) self.font = pygame.font.SysFont(ck_settings.fonttype, 16) def draw_info(self, info): """將文字渲染為圖像,并定位到右邊水平居中""" self.info_image = self.font.render(info, True, self.info_color) self.info_image_rect = self.info_image.get_rect() self.info_image_rect.right = self.screen_rect.right - (self.screen_rect.width - 536 - self.info_image_rect.width) / 2 self.info_image_rect.top = 50 # 繪制到屏幕 self.screen.blit(self.info_image, self.info_image_rect)
4.新建文件“game_functions.py”,存放跟游戲有關(guān)的所有業(yè)務(wù)邏輯函數(shù);
import sys
import pygame
# 棋
def update_board(ck_settings, cb, index_coordinates, position):
"""更新棋盤信息"""
# 判斷棋手(黑棋或白棋)
if ck_settings.chess_player == 1:
ck_settings.prompt_info = '當(dāng)前棋手:白棋'
img = cb.black_image
chess_type = 'black'
else:
ck_settings.prompt_info = '當(dāng)前棋手:黑棋'
img = cb.white_image
chess_type = 'white'
"""落棋"""
dropState = check_at(ck_settings, index_coordinates)
if dropState:
i, j = index_coordinates
chess_x = cb.checkerboard[j][i].x - cb.chess_rect.width / 2
chess_y = cb.checkerboard[j][i].y - cb.chess_rect.height / 2
# 累計(jì)步數(shù)(兩邊合計(jì))
ck_settings.win_number += 1
# 落子并轉(zhuǎn)換棋手
ck_settings.move_chess.append({'type': chess_type, 'coord': position(i, j)})
cb.bg_image.blit(img, (chess_x, chess_y))
ck_settings.chess_player *= -1
# 合計(jì)9步開(kāi)始校驗(yàn)輸贏
if ck_settings.win_number >= 9:
check_stats(ck_settings, (i, j))
else:
ck_settings.prompt_info = '已經(jīng)有其他棋子'
# 檢查(i,j)位置是否已占用
def check_at(ck_settings, index_coordinates):
for item in ck_settings.move_chess:
if index_coordinates == item['coord']:
return False
return True
def check_stats(ck_settings, pos):
"""校驗(yàn)四個(gè)方向,是否有了輸贏"""
pos_i, pos_j = pos
directs = [(1, 0), (0, 1), (1, 1), (1, -1)] # 橫、豎、斜、反斜 四個(gè)方向檢查
for direct in directs:
line_checkerboard = []
d_x, d_y = direct
last = ck_settings.move_chess[-1]
line_ball = [] # 存放在一條線上的棋子
for ball in ck_settings.move_chess:
# 跟最后落子判斷
if ball['type'] == last['type']:
x = ball['coord'].x - last['coord'].x
y = ball['coord'].y - last['coord'].y
if d_x == 0:
if x == 0:
line_ball.append(ball['coord'])
if d_y == 0:
if y == 0:
line_ball.append(ball['coord'])
if x * d_y == y * d_x:
line_ball.append(ball['coord'])
if len(line_ball) >= 5: # 只有5子及以上才繼續(xù)判斷
sorted_line = sorted(line_ball)
for i, item in enumerate(sorted_line):
index = i + 4
if index < len(sorted_line):
if d_x == 0:
y1 = item.y
y2 = sorted_line[index].y
# 此點(diǎn)和第5個(gè)點(diǎn)比較y值,如相差為4則連成5子
if abs(y1 - y2) == 4:
ck_settings.prompt_info = '黑棋獲勝' if last['type'] == 'black' else '白棋獲勝'
else:
x1 = item.x
x2 = sorted_line[index].x
# 此點(diǎn)和第5個(gè)點(diǎn)比較x值,如相差為4則連成5子
if abs(x1 - x2) == 4:
ck_settings.prompt_info = '黑棋獲勝' if last['type'] == 'black' else '白棋獲勝'
else:
break
# 事件
def check_events(ck_settings, cb, position):
"""監(jiān)聽(tīng)事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
# 點(diǎn)擊左鍵
if event.button == 1:
pos = pygame.mouse.get_pos() # 獲取點(diǎn)擊實(shí)際坐標(biāo)
# 判斷是否溢出
x_first = cb.checkerboard[0][0].x
x_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].x
y_first = cb.checkerboard[0][0].y
y_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].y
if pos[0] < x_first or pos[0] > x_last or pos[1] < y_first or pos[1] > y_last:
ck_settings.prompt_info = '落子位置不正確!'
else:
index_coordinates = to_index(ck_settings, pos)
update_board(ck_settings, cb, index_coordinates, position)
def to_index(ck_settings, pos):
"""實(shí)際坐標(biāo)轉(zhuǎn)換為棋盤下標(biāo)"""
i = round((pos[1] - ck_settings.bd_top) / ck_settings.bd_space)
j = round((pos[0] - ck_settings.bd_left) / ck_settings.bd_space)
return (i, j)
5.新建文件gobang.py,主函數(shù)用來(lái)初始化程序,并同步更新程序的信息;
import pygame
from settings import Settings
from checkerboard import Checkerboard
from collections import namedtuple
import game_functions as gf
from infopanel import Infopanel
def run_game():
"""運(yùn)行游戲"""
# 初始化游戲屏幕
pygame.init()
# 創(chuàng)建時(shí)鐘對(duì)象 (可以控制游戲循環(huán)頻率)
clock = pygame.time.Clock()
# 配置實(shí)例化
ck_settings = Settings()
screen = pygame.display.set_mode((ck_settings.width, ck_settings.height))
pygame.display.set_caption('五子棋游戲')
# namedtuple創(chuàng)建類似于元組的數(shù)據(jù)類型,除了可以用索引訪問(wèn),能夠迭代,還能用屬性名訪問(wèn)數(shù)據(jù)
position = namedtuple('Position', ['x', 'y'])
# 創(chuàng)建實(shí)例
cb = Checkerboard(ck_settings, screen, position)
# 實(shí)例化面板信息
infopanel = Infopanel(ck_settings, screen)
while ck_settings.game_active:
# 繪制棋盤
cb.draw_board()
# 繪制面板信息
infopanel.draw_info(ck_settings.prompt_info)
# 檢查玩家事件并更新棋盤
gf.check_events(ck_settings, cb, position)
# 讓最近繪制的屏幕可見(jiàn)
pygame.display.flip()
# 通過(guò)時(shí)鐘對(duì)象指定循環(huán)頻率
clock.tick(60) # 每秒循環(huán)60次
run_game()
6.在文件gobang.py目錄路徑下,執(zhí)行命令“python gobang.py”彈出窗口,即可對(duì)其操作游玩。
結(jié)語(yǔ)
該游戲只是實(shí)現(xiàn)了基礎(chǔ)功能,還有很多可優(yōu)化的功能:
1.根據(jù)實(shí)際情況加上更詳細(xì)的面板信息(比如倒計(jì)時(shí)等);
2.加上開(kāi)始游戲按鈕,可參考前面python實(shí)例;
3.勝負(fù)榜單等,可參考前面python實(shí)例。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Keras官方中文文檔:性能評(píng)估Metrices詳解
這篇文章主要介紹了Keras官方中文文檔:性能評(píng)估Metrices詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
python3中編碼獲取網(wǎng)頁(yè)的實(shí)例方法
在本篇文章里小編給大家整理了一篇關(guān)于python3中編碼獲取網(wǎng)頁(yè)的實(shí)例方法,有興趣的朋友們可以學(xué)習(xí)下。2020-11-11
深入理解python對(duì)json的操作總結(jié)
Json最廣泛的應(yīng)用是作為AJAX中web服務(wù)器和客戶端的通訊的數(shù)據(jù)格式,本篇文章主要介紹了python對(duì)json的操作總結(jié),具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
keras 解決加載lstm+crf模型出錯(cuò)的問(wèn)題
這篇文章主要介紹了keras 解決加載lstm+crf模型出錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
python實(shí)現(xiàn)圖片彩色轉(zhuǎn)化為素描
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)圖片彩色轉(zhuǎn)化為素描,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
基于Python編寫一個(gè)監(jiān)控CPU的應(yīng)用系統(tǒng)
在使用電腦辦公時(shí),有時(shí)候不知道哪些軟件或進(jìn)程會(huì)占用大量的資源,導(dǎo)致進(jìn)行其他任務(wù)時(shí)出現(xiàn)變慢、卡頓等現(xiàn)象。因此,實(shí)時(shí)監(jiān)控系統(tǒng)的資源就變得非常重要。本文用Python編寫了一款超治愈的RunCat監(jiān)控應(yīng)用系統(tǒng),需要的可以參考一下2022-06-06
Python機(jī)器學(xué)習(xí)之隨機(jī)梯度下降法的實(shí)現(xiàn)
如果當(dāng)我們數(shù)據(jù)量和樣本量非常大時(shí),每一項(xiàng)都要參與到梯度下降,那么它的計(jì)算量時(shí)非常大的,所以我們需要采用隨機(jī)梯度下降法。本文介紹了Python實(shí)現(xiàn)隨機(jī)梯度下降法的方法,希望對(duì)大家有所幫助2023-02-02
Python統(tǒng)計(jì)某列不同值的個(gè)數(shù)的示例代碼
在數(shù)據(jù)分析和數(shù)據(jù)處理中,統(tǒng)計(jì)數(shù)據(jù)往往集中在特定列中不同值的出現(xiàn)次數(shù),本文主要介紹了Python統(tǒng)計(jì)某列不同值的個(gè)數(shù)的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03

