文章目录

1、初始化棋盘2、初始化棋子3、开始游戏4、落子设置5、吃子判断6 悔棋和弃一子7 重新开始、推出与切换棋盘8 显示9 初始化

本文使用python中的pygame库设计制作了一个围棋游戏。

参考项目资料:

https://github.com/HapHac/weiqi

1、初始化棋盘

# 绘制棋盘

def draw_chessboard(self):

# 画棋盘,填充颜色

pygame.draw.rect(self.screen, (204, 85, 17), [0 * self.size, 0 * self.size, 400 * self.size, 400 * self.size])

pygame.draw.rect(self.screen, (51, 102, 153),

[400 * self.size, 0 * self.size, 200 * self.size, 400 * self.size])

# 画外框

outer_frame_color = (60, 20, 0)

pygame.draw.rect(self.screen, outer_frame_color,

[20 * self.size, 20 * self.size, 360 * self.size, 360 * self.size],

5)

# 棋盘上的九个定位点,以中点为模型,移动位置,以作出其余八个点

for m in [-1, 0, 1]:

for n in [-1, 0, 1]:

rect = pygame.Rect([200 * self.size - self.size * 2,

200 * self.size - self.size * 2,

self.size * 4, self.size * 4])

pygame.draw.ellipse(self.screen, (0, 0, 0), rect, width=0)

rect = rect.move(m * self.interval * (2 if self.mode_num == 9 else (3 if self.mode_num == 13 else 6)),

n * self.interval * (2 if self.mode_num == 9 else (3 if self.mode_num == 13 else 6)))

pygame.draw.ellipse(self.screen, (0, 0, 0), rect, width=0)

# 画中间的线条

for i in range(1, self.mode_num - 1):

pygame.draw.line(self.screen, (0, 0, 0), (20 * self.size, 20 * self.size + i * self.interval),

(380 * self.size, 20 * self.size + i * self.interval), width=2)

pygame.draw.line(self.screen, (0, 0, 0), (20 * self.size + i * self.interval, 20 * self.size),

(20 * self.size + i * self.interval, 380 * self.size), width=2)

# 放置右侧初始图片

if self.stop:

self.screen.blit(self.photoW, (480 * self.size, 65 * self.size))

self.screen.blit(self.photoB, (480 * self.size - 45, 65 * self.size))

elif self.present == 1:

self.screen.blit(self.photoB, (480 * self.size - 45, 65 * self.size))

else:

self.screen.blit(self.photoW, (480 * self.size, 65 * self.size))

# # 几个功能按钮

button_color = (255, 255, 255)

self.start_button = Button('开始游戏', button_color, 'msyh.ttc', 23)

self.start_button.draw(self.screen, 480 * self.size, 200 * self.size)

self.pass_me_button = Button('弃一子', button_color, 'msyh.ttc', 23)

self.pass_me_button.draw(self.screen, 480 * self.size, 225 * self.size)

self.regert_button = Button('悔棋', button_color, 'msyh.ttc', 23)

self.regert_button.draw(self.screen, 480 * self.size, 250 * self.size)

self.restsrt_button = Button('重新开始', button_color, 'msyh.ttc', 23)

self.restsrt_button.draw(self.screen, 480 * self.size, 275 * self.size)

self.thirteen_way_button = Button('十三路棋', button_color, 'msyh.ttc', 23)

self.thirteen_way_button.draw(self.screen, 480 * self.size, 300 * self.size)

self.nineteenth_way_button = Button('十九路棋', button_color, 'msyh.ttc', 23)

self.nineteenth_way_button.draw(self.screen, 480 * self.size, 325 * self.size)

self.exit_button = Button('退出游戏', button_color, 'msyh.ttc', 23)

self.exit_button.draw(self.screen, 480 * self.size, 350 * self.size)

在上述代码中,首先绘制棋盘的框架,使用pygame中的pygame.draw.rect,然后通过pygame.draw.line绘制线条,形成完整的棋盘。除此之外,在棋盘的一旁,添加了一个太极图用以表示当前的棋手,以及一些按钮用于控制游戏的进程(按钮使用自定义类完成)。

class Text:

def __init__(self, text: str, text_color, font_type: str, font_size: int):

"""

text: 文本内容,注意是字符串形式

text_color: 字体颜色

font_type: 字体文件

font_size: 字体大小

"""

self.text = text

self.text_color = text_color

self.font_type = font_type

self.font_size = font_size

font = pygame.font.Font(os.path.join('font', (self.font_type)), self.font_size)

self.text_image = font.render(self.text, True, self.text_color).convert_alpha()

self.text_width = self.text_image.get_width()

self.text_height = self.text_image.get_height()

def draw(self, surface: pygame.Surface, center_x, center_y):

"""

surface: 文本放置的表面

center_x, center_y: 文本放置在表面的<中心坐标>

"""

upperleft_x = center_x - self.text_width / 2

upperleft_y = center_y - self.text_height / 2

surface.blit(self.text_image, (upperleft_x, upperleft_y))

class Button(Text):

def __init__(self, text: str, text_color, font_type: str, font_size: int):

super().__init__(text, text_color, font_type, font_size)

self.rect = self.text_image.get_rect()

self.enable = True

def draw(self, surface: pygame.Surface, center_x, center_y):

super().draw(surface, center_x, center_y)

self.rect.center = center_x, center_y

def handle_event(self, command):

self.hovered = self.rect.collidepoint(pygame.mouse.get_pos())

if self.hovered:

if self.enable:

command()

else:

pass

2、初始化棋子

# 绘制棋子

def draw_chess(self):

# 遍历棋盘二维数组,绘制出棋盘中所有已下子

for i in range(self.mode_num):

for j in range(self.mode_num):

pos = i * self.interval + 20 * self.size - 30 * self.p, j * self.interval + 20 * self.size - 30 * self.p

if self.positions[i][j] == 0:

continue

elif self.positions[i][j] == 1:

self.screen.blit(self.photoBD, pos)

elif self.positions[i][j] == -1:

self.screen.blit(self.photoWD, pos)

定义一个数组:self.positions用以存储棋盘中棋子的状态。

3、开始游戏

点击开始游戏按钮,正式开始游戏,删除白色太极图,表示黑棋先行。

# 开始游戏函数,点击“开始游戏”时调用

def start(self):

# 删除右侧太极图

self.screen.blit(self.bg_rect, (400 * self.size, 65 * self.size))

# 利用右侧图案提示开始时谁先落子

if self.present == 1:

self.screen.blit(self.photoB, (480 * self.size - 45, 65 * self.size))

else:

self.screen.blit(self.photoW, (480 * self.size, 65 * self.size))

# 开始标志,解除stop

self.stop = None

4、落子设置

首先定义一个函数,用以获取当前鼠标的位置。

# 获取鼠标当前位置

def get_mouse_current_position(self, x, y):

self.mouse_x = x

self.mouse_y = y

然后设置棋子跟随鼠标移动。

# 棋子跟随鼠标移动

def chess_follow(self):

if 20 * self.size < self.mouse_x < 380 * self.size and 20 * self.size < self.mouse_y < 380 * self.size:

pos = self.mouse_x - 30 * self.p, self.mouse_y - 35 * self.p

if self.present == 1:

self.screen.blit(self.photoBD, pos)

else:

self.screen.blit(self.photoWD, pos)

最后定义一个函数,在鼠标左键点击时,落下棋子。

# 落子,并驱动玩家的轮流下棋行为

def getDown(self):

# 拷贝三份棋盘“快照”,悔棋和判断“打劫”时需要作参考

self.last_3_positions = copy.deepcopy(self.last_2_positions)

self.last_2_positions = copy.deepcopy(self.last_1_positions)

self.last_1_positions = copy.deepcopy(self.positions)

dx = (self.mouse_x - 20 * self.size) % self.interval

dy = (self.mouse_y - 20 * self.size) % self.interval

if not self.stop:

row = int((self.mouse_x - 20 * self.size) / self.interval) + round(dx / self.interval)

col = int((self.mouse_y - 20 * self.size) / self.interval) + round(dy / self.interval)

if self.positions[row][col] == 0:

self.positions[row][col] = self.present

deadlist = self.get_deadlist()

self.kill(deadlist)

# 自杀判定

# 对方无“气”棋子全部提走后,对己方棋子进行有无“气”的判断,若己方仍存在无“气”棋子,则判定为自杀行为,自杀标志置1(因只需检测到一个无“气”子即说明是自杀,故无需继续检测,跳出循环)

for i in range(9):

for j in range(9):

if self.positions[i][j] == self.present:

if self.if_dead(i, j) == True:

win32api.MessageBox(0, "禁止自杀", "警告", win32con.MB_ICONWARNING)

self.positions[i][j] = 0

self.present = - self.present

else:

# 警告信息框

win32api.MessageBox(0, "此处以存在棋子", "警告", win32con.MB_ICONWARNING)

5、吃子判断

在每次落子之后,遍历整个棋盘,并返回死棋列表位置

# 落子后,依次判断四周是否有棋子被杀死,并返回死棋位置列表

def get_deadlist(self):

deadlist = []

for i in range(self.mode_num):

for j in range(self.mode_num):

if self.positions[i][j] == 0:

continue

elif self.positions[i][j] == -self.present and self.if_dead(i, j) == True:

# continue

self.visit_positions = [[0 for k in range(self.mode_num + 2)] for k in range(self.mode_num + 2)]

deadlist.append([i, j])

# print(deadlist)

return deadlist

判断棋子是否有气函数if_dead

# 判断棋子是否无气(死亡),有气则返回False,无气则返回无气棋子的列表

def if_dead(self, x, y):

# 为避免重复搜索,走过的位置记为1

self.visit_positions[x][y] = 1

directions = [[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]]

# 左,右,上,下四个方向

for dx, dy in directions:

# 左边是墙 或 右边是墙 或 上边是墙 或 下边是墙,即死路,则跳过此方向

if dx < 0 or dx > 8 or dy < 0 or dy > 8:

continue

# 若此方向没有搜索过,则开始搜索

elif self.visit_positions[dx][dy] == 0:

# 此方向没有棋子,可看做迷宫的出口,于是该棋子有“气”,停止搜索

if self.positions[dx][dy] == 0:

return False

# 此方向是对方棋子,是死路,跳过此方向

elif self.positions[dx][dy] == - self.positions[x][y]:

continue

# 此方向是己方棋子,即通路,继续递归执行DFS

elif self.positions[dx][dy] == self.positions[x][y]:

self.if_dead(dx, dy)

# 以上条件都不满足,即所有路径都为死路,该棋子无“气”,停止搜索

return True

杀死死棋

# 杀死位置列表killList中的棋子,即删除图片,位置值置0

def kill(self, killList):

if len(killList) > 0:

for i, j in killList:

self.positions[i][j] = 0

6 悔棋和弃一子

# 放弃一子

def passme(self):

self.present = -self.present

# 悔棋函数

def regret(self):

self.positions = self.last_2_positions

7 重新开始、推出与切换棋盘

# 重新开始游戏

def reload(self):

self.present = 1

self.draw_chessboard()

# 定义棋盘阵列,无子:0,黑棋:1,白棋:-1

self.positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.visit_positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.draw_chess()

# 退出游戏

def exit(self):

pygame.quit()

sys.exit()

# 更改游戏棋盘

def newgame1(self):

self.mode_num = 13

# 棋盘每格的边长

self.interval = 360 * self.size / (self.mode_num - 1)

# 相对九路棋盘的矫正比例

self.p = 1 if self.mode_num == 9 else (2 / 3 if self.mode_num == 13 else 4 / 9)

# 定义棋盘阵列,无子:0,黑棋:1,白棋:-1

self.positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.visit_positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.photoBD = pygame.image.load("./Pictures/" + "BD" + "-" + str(self.mode_num) + ".png") # .convert()

self.photoWD = pygame.image.load("./Pictures/" + "WD" + "-" + str(self.mode_num) + ".png") # .convert()

# 更改游戏棋盘

def newgame2(self):

self.mode_num = 19

# 棋盘每格的边长

self.interval = 360 * self.size / (self.mode_num - 1)

# 相对九路棋盘的矫正比例

self.p = 1 if self.mode_num == 9 else (2 / 3 if self.mode_num == 13 else 4 / 9)

# 定义棋盘阵列,无子:0,黑棋:1,白棋:-1

self.positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.visit_positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.photoBD = pygame.image.load("./Pictures/" + "BD" + "-" + str(self.mode_num) + ".png") # .convert()

self.photoWD = pygame.image.load("./Pictures/" + "WD" + "-" + str(self.mode_num) + ".png") # .convert()

8 显示

def show(self):

while True:

pygame.display.flip()

self.clock = pygame.time.Clock()

# 绘制棋盘

self.draw_chessboard()

# 绘制棋子

self.draw_chess()

if not self.stop:

# 棋子跟随鼠标移动

self.chess_follow()

# 监听所有事件

for event in pygame.event.get():

# 点击x则关闭窗口

if event.type == pygame.QUIT:

pygame.quit()

sys.exit()

# 点击窗口里面类容则完成相应指令

elif event.type == MOUSEMOTION:

x, y = event.pos

self.get_mouse_current_position(x, y)

elif event.type == MOUSEBUTTONDOWN:

# 鼠标点击按钮函数

self.start_button.handle_event(self.start)

self.pass_me_button.handle_event(self.passme)

self.regert_button.handle_event(self.regret)

self.restsrt_button.handle_event(self.reload)

self.thirteen_way_button.handle_event(self.newgame1)

self.nineteenth_way_button.handle_event(self.newgame2)

self.exit_button.handle_event(self.exit)

# 如果鼠标左键在棋盘内按下

if 20 * self.size < self.mouse_x < 380 * self.size and 20 * self.size < self.mouse_y < 380 * self.size:

self.getDown()

self.present = - self.present

9 初始化

class weiqi():

def __init__(self):

# 模式,九路棋:9,十三路棋:13,十九路棋:19

self.mode_num = 9

# 窗口尺寸设置,默认:1.8

self.size = 1.8

# 棋盘每格的边长

self.interval = 360 * self.size / (self.mode_num - 1)

# 相对九路棋盘的矫正比例

self.p = 1 if self.mode_num == 9 else (2 / 3 if self.mode_num == 13 else 4 / 9)

# 定义棋盘阵列,无子:0,黑棋:1,白棋:-1

self.positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

self.visit_positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]

# 当前轮到的玩家,黑:1,白:-1,执黑先行

self.present = 1

# 初始停止运行,点击“开始游戏”运行游戏

self.stop = True

# 悔棋次数,次数大于0才可悔棋,初始置0(初始不能悔棋),悔棋后置0,下棋或弃手时恢复为1,以禁止连续悔棋

self.regretchance = 0

self.mouse_x = -100

self.mouse_y = -100

self.last_1_positions = copy.deepcopy(self.positions)

self.last_2_positions = copy.deepcopy(self.positions)

self.last_3_positions = copy.deepcopy(self.positions)

pygame.init()

# 创建一个窗口

self.screen = pygame.display.set_mode([600 * self.size, 400 * self.size])

# 设置窗口标题

pygame.display.set_caption("围棋")

self.photoW = pygame.image.load("./Pictures/W.png") # .convert()

self.photoB = pygame.image.load("./Pictures/B.png") # .convert()

self.photoBD = pygame.image.load("./Pictures/" + "BD" + "-" + str(self.mode_num) + ".png") # .convert()

self.photoWD = pygame.image.load("./Pictures/" + "WD" + "-" + str(self.mode_num) + ".png") # .convert()

self.bg_rect = pygame.Surface((200 * self.size, 100 * self.size), flags=pygame.HWSURFACE)

self.bg_rect.fill((51, 102, 153))

完整代码 https://download.csdn.net/download/m0_55818687/87698112

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: