本文實例為大家分享了python五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
目錄
- 簡介
- 實現(xiàn)過程
- 結(jié)語
簡介
使用python實現(xiàn)pygame版的五子棋游戲;
環(huán)境:Windows系統(tǒng)+python3.8.0
游戲規(guī)則:
1.分兩位棋手對戰(zhàn),默認黑棋先下;當在棋盤點擊左鍵,即在該位置繪制黑棋;
2.自動切換到白棋,當在棋盤點擊左鍵,即在該位置繪制白棋;
3.輪流切換棋手下棋,當那方先形成5子連線者獲勝(橫、豎、斜、反斜四個方向都可以)。
游戲運行效果如下:
實現(xiàn)過程
1.新建文件settings.py,用來定義一些必須的基本屬性和初始值;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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é)束(默認開始) self .game_active = True # 判斷哪方下棋(默認黑子先寫) self .chess_player = 1 self .prompt_info = '當前棋手:黑棋' # 開始校驗輸贏(兩邊合計9,因為已經(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' # 存儲落子數(shù)據(jù) self .move_chess = [] |
2.新建文件checkerboard.py,主要用來繪制背景圖和棋格線;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
import sys import pygame class Checkerboard(): def __init__( self , ck_settings, screen, position): self .ck_settings = ck_settings self .screen = screen self .position = position # 顏色和坐標大小 self .text_color = ( 0 , 0 , 0 ) self .font = pygame.font.SysFont(ck_settings.fonttype, ck_settings.fontsize) # 存儲棋子坐標 self .checkerboard = [] # 加載背景圖、黑棋和白棋(當有圖片不存在時,打印錯誤并退出游戲) 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 ): # 存儲棋子坐標 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)) # 繪制棋盤坐標 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軸坐標(在棋盤背景圖繪制) 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,主要用來繪制棋盤右邊提示信息(暫時只有顯示下棋方和獲勝信息);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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è)務邏輯函數(shù);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
import sys import pygame # 棋 def update_board(ck_settings, cb, index_coordinates, position): """更新棋盤信息""" # 判斷棋手(黑棋或白棋) if ck_settings.chess_player = = 1 : ck_settings.prompt_info = '當前棋手:白棋' img = cb.black_image chess_type = 'black' else : ck_settings.prompt_info = '當前棋手:黑棋' 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 # 累計步數(shù)(兩邊合計) 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 # 合計9步開始校驗輸贏 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): """校驗四個方向,是否有了輸贏""" pos_i, pos_j = pos directs = [( 1 , 0 ), ( 0 , 1 ), ( 1 , 1 ), ( 1 , - 1 )] # 橫、豎、斜、反斜 四個方向檢查 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 # 此點和第5個點比較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 # 此點和第5個點比較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)聽事件""" for event in pygame.event.get(): if event. type = = pygame.QUIT: sys.exit() elif event. type = = pygame.MOUSEBUTTONDOWN: # 點擊左鍵 if event.button = = 1 : pos = pygame.mouse.get_pos() # 獲取點擊實際坐標 # 判斷是否溢出 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): """實際坐標轉(zhuǎn)換為棋盤下標""" 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ù)用來初始化程序,并同步更新程序的信息;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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(): """運行游戲""" # 初始化游戲屏幕 pygame.init() # 創(chuàng)建時鐘對象 (可以控制游戲循環(huán)頻率) clock = pygame.time.Clock() # 配置實例化 ck_settings = Settings() screen = pygame.display.set_mode((ck_settings.width, ck_settings.height)) pygame.display.set_caption( '五子棋游戲' ) # namedtuple創(chuàng)建類似于元組的數(shù)據(jù)類型,除了可以用索引訪問,能夠迭代,還能用屬性名訪問數(shù)據(jù) position = namedtuple( 'Position' , [ 'x' , 'y' ]) # 創(chuàng)建實例 cb = Checkerboard(ck_settings, screen, position) # 實例化面板信息 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) # 讓最近繪制的屏幕可見 pygame.display.flip() # 通過時鐘對象指定循環(huán)頻率 clock.tick( 60 ) # 每秒循環(huán)60次 run_game() |
6.在文件gobang.py目錄路徑下,執(zhí)行命令“python gobang.py”彈出窗口,即可對其操作游玩。
結(jié)語
該游戲只是實現(xiàn)了基礎(chǔ)功能,還有很多可優(yōu)化的功能:
1.根據(jù)實際情況加上更詳細的面板信息(比如倒計時等);
2.加上開始游戲按鈕,可參考前面python實例;
3.勝負榜單等,可參考前面python實例。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/king0964/article/details/104015047