主模块代码:
# -*- coding:utf-8 -*-
import sys
from tkinter import messagebox
import tkinter
import pygame
import button
SCREEN_SIDE = (400, 500) # 屏幕大小
black_color = (0, 0, 0)
white_color = (255, 255, 255)
yellow_color = (237, 145, 33)
COUNTER = 1 # 记录每一步
EMPTY = 0 # 标记空白
BLACK = 1 # 标记黑棋
WHITE = -1 # 标记白棋
class five_chess:
def __init__(self):
self.color_list = [[]] * 15 # 记录棋盘每一格的状态
self.point_coord = [[]] * 15 # 记录每一步棋的坐标
self.point_color = {} # 记录每一步棋的位置
self.reset()
self.resset2()
def reset(self):
"""初始化列表"""
for i in range(len(self.color_list)):
self.color_list[i] = [EMPTY] * 15 # 设置初始每格的状态都是空
def resset2(self):
"""初始化列表"""
for i in range(len(self.point_coord)):
self.point_coord[i] = [EMPTY] * 15
def draw_piece(self, screen, x, y, row, col):
"""绘制棋子"""
global COUNTER
# 当计数器为奇数时,绘制黑子,并设置该子的状态为黑棋,保存该子的坐标,位置
if COUNTER % 2 == 1:
pygame.draw.circle(screen, black_color, [x, y], 10, 0)
self.color_list[row - 1][col - 1] = BLACK
self.point_coord[row - 1][col - 1] = [x, y]
self.point_color[COUNTER + 1] = [row - 1, col - 1]
COUNTER += 1
else:
pygame.draw.circle(screen, white_color, [x, y], 10, 0)
self.color_list[row - 1][col - 1] = WHITE
self.point_coord[row - 1][col - 1] = [x, y]
self.point_color[COUNTER + 1] = [row - 1, col - 1]
COUNTER += 1
def remv_piece(self, screen):
"""撤销方法"""
global COUNTER
# 先将上一步计数器保存的棋子状态设置为空,重新绘制空棋盘,遍历每一格的状态,将黑棋和白棋的状态绘制出来
r = self.point_color[COUNTER][0]
c = self.point_color[COUNTER][1]
self.color_list[r][c] = EMPTY
self.draw_chessboard(screen)
for i in range(15):
for index, row in enumerate(self.color_list):
if row[i] == BLACK:
pygame.draw.circle(screen, black_color, self.point_coord[index][i], 10, 0)
elif row[i] == WHITE:
pygame.draw.circle(screen, white_color, self.point_coord[index][i], 10, 0)
COUNTER -= 1 # 将计数器回溯到上一步的数值
def draw_chessboard(self, screen):
"""绘制棋盘"""
pygame.draw.rect(screen, yellow_color, [60, 60, 280, 280], 0)
for i in range(1, 16):
# 绘制棋盘的线
pygame.draw.line(screen, black_color, [60, 40 + 20 * i], [340, 40 + 20 * i], 1)
pygame.draw.line(screen, black_color, [40 + 20 * i, 60], [40 + 20 * i, 340], 1)
# 绘制五个小黑点点
pygame.draw.circle(screen, black_color, [120, 120], 3, 0)
pygame.draw.circle(screen, black_color, [280, 120], 3, 0)
pygame.draw.circle(screen, black_color, [200, 200], 3, 0)
pygame.draw.circle(screen, black_color, [120, 280], 3, 0)
pygame.draw.circle(screen, black_color, [280, 280], 3, 0)
def is_win(self):
"""判断五子胜利条件"""
# 判断竖直方向的胜利条件
for col in range(15):
flag = 0
for row in self.color_list:
if row[col] == BLACK:
flag += 1
if flag == 5:
print("黑棋胜利!")
return 1
else:
flag = 0
for row in self.color_list:
if row[col] == WHITE:
flag += 1
if flag == 5:
print("白棋胜利")
return -1
else:
flag = 0
# 判断水平方向上的胜利条件
for row in self.color_list:
flag = 0
for col in range(15):
if row[col] == BLACK:
flag += 1
if flag == 5:
print("黑棋获胜")
return 1
else:
flag = 0
for col in range(15):
if row[col] == WHITE:
flag += 1
if flag == 5:
print("白棋获胜")
return -1
else:
flag = 0
# 判断反斜方向胜利条件
for col in range(-14, 15):
for index, row in enumerate(self.color_list):
if 0 <= index - col <= 14 and row[index - col] == BLACK:
flag += 1
if flag == 5:
print("黑棋获胜")
return 1
else:
flag = 0
for index, row in enumerate(self.color_list):
if 0 <= index - col <= 14 and row[index - col] == WHITE:
flag += 1
if flag == 5:
print("白棋获胜")
return -1
else:
flag = 0
# 判断正斜方向胜利条件
for col in range(28, 0, -1):
for index, row in enumerate(self.color_list):
if 0 <= col - index <= 14 and row[col - index] == BLACK:
flag += 1
if flag == 5:
print("黑棋获胜")
return 1
else:
flag = 0
for index, row in enumerate(self.color_list):
if 0 <= col - index <= 14 and row[col - index] == WHITE:
flag += 1
if flag == 5:
print("白棋获胜")
return -1
else:
flag = 0
def main():
global COUNTER
root = tkinter.Tk()
root.withdraw() # 将创建的窗体进行影藏
pygame.init()
pygame.display.set_caption('五子棋')
screen = pygame.display.set_mode(SCREEN_SIDE)
screen.fill(white_color) # 设置白色背景
wuziqi = five_chess()
wuziqi.draw_chessboard(screen)
button1 = button.Button(screen, "重新开始", 50, 370, 150, 50) # 绘制按钮,设置坐标和大小
button2 = button.Button(screen, "悔棋", 240, 370, 150, 50)
button1.draw_button()
button2.draw_button()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 监听点击退出事件时
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # 当鼠标点击后,并且点的是鼠标左键时
x, y = event.pos # 拿到鼠标在当前窗口上的位置坐标
if button1.rect.collidepoint(x, y):
# 当鼠标点击了该按钮的窗口位置时
COUNTER = 1
screen.fill(white_color)
button1.draw_button()
button2.draw_button()
wuziqi.draw_chessboard(screen)
wuziqi.reset()
wuziqi.resset2()
elif button2.rect.collidepoint(x, y):
if COUNTER != 1:
screen.fill(white_color)
button1.draw_button()
button2.draw_button()
wuziqi.remv_piece(screen)
for row in range(16):
for col in range(16):
if 37 + 20 * col <= x <= 43 + 20 * col and 37 + 20 * row <= y <= 43 + 20 * row:
x = 40 + 20 * col
y = 40 + 20 * row
if wuziqi.color_list[row - 1][col - 1] == EMPTY:
wuziqi.draw_piece(screen, x, y, row, col)
if wuziqi.is_win() == 1:
m = messagebox.askokcancel("恭喜", "黑子胜利\n是否再来一局?")
if m:
COUNTER = 1
wuziqi.draw_chessboard(screen)
wuziqi.reset()
else:
print("退出程序")
sys.exit()
elif wuziqi.is_win() == -1:
m = messagebox.askokcancel("恭喜", "白子胜利\n是否再来一局?")
if m:
COUNTER = 1
screen.fill(white_color)
button1.draw_button()
button2.draw_button()
wuziqi.draw_chessboard(screen)
wuziqi.reset()
wuziqi.resset2()
else:
sys.exit()
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
`
按钮模块代码:
import pygame
class Button:
def __init__(self, screen, msg, x, y, width, height): # msg为要在按钮中显示的文本
"""初始化按钮的属性"""
self.screen = screen
self.screen_rect = screen.get_rect()
self.button_color = (72, 61, 139) # 设置按钮的rect对象颜色为深蓝
self.text_color = (255, 255, 255) # 设置文本的颜色为白色
self.font = pygame.font.SysFont("华文宋体", 16) # 设置文本为华文宋体,字号为16
self.rect = pygame.Rect(x, y, width, height)
# self.rect.center = self.screen_rect.center # 创建按钮的rect对象,并使其居中
self.deal_msg(msg) # 渲染图像
def deal_msg(self, msg):
"""将msg渲染为图像,并将其在按钮上居中"""
self.msg_img = self.font.render(msg, True, self.text_color, self.button_color) # render将存储在msg的文本转换为图像
self.msg_img_rect = self.msg_img.get_rect() # 根据文本图像创建一个rect
self.msg_img_rect.center = self.rect.center # 将该rect的center属性设置为按钮的center属性
def draw_button(self):
self.screen.fill(self.button_color, self.rect) # 填充颜色
self.screen.blit(self.msg_img, self.msg_img_rect) # 将该图像绘制到屏幕