继续介绍python游戏编程,仍然是基于pgzero。关于该软件包的基础使用技巧可参考本人专栏文章:
老娄:python游戏编程之pgzero使用介绍zhuanlan.zhihu.com
思考
- 绘制棋盘。五子棋的棋盘是15*15的表格,所以就是画交叉的直线即可。可以使用screen.draw.line来实现,它接受3个参数:起点坐标、终点坐标、线的颜色。
def
显示的效果如下图所示:
- 关于走棋。鼠标可以在任何位置单击,所以不是一个精准的事件,我们已经知道def
同时,在落棋时,还要判断是否本点上已经有其它棋子。这里想到可以用一个0,1的二维矩阵来刻画每个位置上是否有棋子。这里使用的逻辑是:
chess_black = []
chess_white = []
def on_mouse_down(pos):
# print("Mouse button clicked at", pos)
click_x, click_y = pos
#计算落在第几行、第几列的交叉点上
xs,zs = math.modf((click_x - 20) / SIZE) #获取小数、整数部分
if xs > 0.5:
x = int(zs + 1)
else:
x = int(zs)
xs_y,zs_y = math.modf((click_y - 20) / SIZE)
if xs_y > 0.5:
y = int(zs_y + 1)
else:
y = int(zs_y)
if matrix[y][x] != 1:
chess = Actor("gobang_black")
chess.x = x * SIZE + 20
chess.y = y * SIZE + 20
matrix[y][x] = 1
chess_black.append(chess)
事实上,我们需要轮流走黑、白两种颜色的棋子,可以通过一个全局变量来实现,当黑棋走过后,手工将该全局变量置为另一种颜色即可。
- 是否结束。当落一子的时候,就要判断一下是否游戏可以结束了:横、竖、斜有5个同色棋子。
完整代码
import pgzrun
import pgzero
import math
import numpy
SIZE = 40
WIDTH = 15 * SIZE
HEIGHT = 15 * SIZE
#初始化每个坐标位,0表示没有棋子
matrix = [[0]*15 for i in range(15)]
chess_black = []
chess_white = []
global turn
turn = "black"
global FINISH
FINISH = False
def draw():
screen.fill((210,180,140))
for i in range(15):
screen.draw.line((20,20+SIZE*i),(20+SIZE*14,20+SIZE*i),(0,0,0)) #周边稍有留白
for i in range(15):
screen.draw.line((20+SIZE*i, 20), (20+SIZE*i,20 + SIZE * 14), (0, 0, 0))
for b in chess_black:
b.draw()
for b in chess_white:
b.draw()
if FINISH:
screen.draw.text("GAME OVER", topleft=(20, 100), color="green", fontsize=80)
return
def on_mouse_down(pos):
global turn
# print("Mouse button clicked at", pos)
click_x, click_y = pos
#计算落在第几行、第几列的交叉点上
xs,zs = math.modf((click_x - 20) / SIZE) #获取小数、整数部分
if xs > 0.5:
x = int(zs + 1)
else:
x = int(zs)
xs_y,zs_y = math.modf((click_y - 20) / SIZE)
if xs_y > 0.5:
y = int(zs_y + 1)
else:
y = int(zs_y)
if matrix[y][x] == 0:
if turn == "black":
chess = Actor("gobang_black")
chess.x = x * SIZE + 20
chess.y = y * SIZE + 20
matrix[y][x] = 1
chess_black.append(chess)
turn = "white"
check_finish(y, x)
print(FINISH)
elif turn == "white":
chess = Actor("gobang_white")
chess.x = x * SIZE + 20
chess.y = y * SIZE + 20
matrix[y][x] = -1
chess_black.append(chess)
turn = "black"
check_finish(y, x)
# print(FINISH)
else:
pass
def check_finish(i,j):
# i,j 表示 matrix的第i行,第j列
global FINISH
#判断横向
if [1,1,1,1,1] in [matrix[i][j:j+5], matrix[i][j-1:j+4],matrix[i][j-2:j+3],matrix[i][j-3:j+2],matrix[i][j-4:j+1],matrix[i][j-5:j]] or [-1,-1,-1,-1,-1] in [matrix[i][j:j+5], matrix[i][j-1:j+4],matrix[i][j-2:j+3],matrix[i][j-3:j+2],matrix[i][j-4:j+1]]:
FINISH = True
return
#判断纵向
mat = numpy.mat(matrix)
for x in range(-5,1):
y = 5 - abs(x)
col = mat[i+x:i+y,j]
col_list = [i[0] for i in col.tolist()]
if col_list == [1,1,1,1,1] or col_list == [-1,-1,-1,-1,-1]:
FINISH = True
return
#判断斜向
col_list = []
for x in range(-4,5):
if i + x >= 0 and i + x < 15 and j + x >= 0 and j + x < 15:
col_list.append(mat[i+x,j+x])
if col_list == [1,1,1,1,1] or col_list == [-1,-1,-1,-1,-1]:
FINISH = True
return
col_list = []
for x in range(-4,5):
if i + x >= 0 and i+x < 15 and j - x >= 0 and j-x < 15:
col_list.append(mat[i+x,j-x])
if col_list == [1,1,1,1,1] or col_list == [-1,-1,-1,-1,-1]:
FINISH = True
return
pgzrun.go()
参考资料
《趣学python游戏编程》何青 著