利用python实现五子棋
部分源码来自github python-100-days,我在其中加上了实现连成五子的判断以及游戏结束弹出提醒框,其中提醒框这一部分是使用tkinter中messagebox实现的,所以会有弹出另外一个TK的界面,这个算是一个bug吧,因为五子棋整体是使用pygame实现的,由于设定是判断完胜负就退出,所以如果使用pygame中文字模块的话文字可能刚加载完就退出了,也看不清文字,我也懒得折腾了,所以就使用了tkinter实现了。
下面直接给出代码:
import pygame
from tkinter import messagebox
EMPTY = 0
BLACK = 1
WHITE = 2
black_color = [0, 0, 0]
white_color = [255, 255, 255]
class Point(object):
def __init__(self,x,y):
self._x=x
self._y=y
def __add__(self,other):
return Point(self._x+other._x,self._y+other._y)
class RenjuBoard(object):
def __init__(self):
self._board = [[]] * 15
self.reset()
def check(self,y,x,flag):
# 搜索的区域范围,是以当前的点为中心的9*9的点阵范围
leftEdge = x - 5
rightEdge = x +5
topEdge = y - 5
bottomEdge = y + 5
# 棋盘边界优化处理,缩小搜索范围
if leftEdge<0:
leftEdge = 0
if rightEdge>14:
rightEdge=14
if topEdge<0:
topEdge=0
if bottomEdge>14:
bottomEdge=14
dirs = [
Point(0,1),
Point(1,1),
Point(1,0),
Point(1,-1),
Point(0,-1),
Point(-1,-1),
Point(-1,0),
Point(-1,1)
]
length=[0]*8
for i in range(8):
l=0
pos = Point(x,y)
while self._board[pos._y][pos._x]==flag:
pos += dirs[i]
l+=1
if pos._x<leftEdge or pos._x >rightEdge or pos._y<topEdge or pos._y > bottomEdge:
break
length[i]=l
for i in range(4):
total = length[i] + length[i+4]-1
if total>=5:
return True
return False
def reset(self):
for row in range(len(self._board)):
self._board[row] = [EMPTY] * 15
def move(self, row, col, is_black):
if self._board[row][col] == EMPTY:
self._board[row][col] = BLACK if is_black else WHITE
return True
return False
def draw(self, screen):
for index in range(1, 16):
pygame.draw.line(screen, black_color,
[40, 40 * index], [600, 40 * index], 1)
pygame.draw.line(screen, black_color,
[40 * index, 40], [40 * index, 600], 1)
pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)
pygame.draw.circle(screen, black_color, [320, 320], 5, 0)
pygame.draw.circle(screen, black_color, [160, 160], 5, 0)
pygame.draw.circle(screen, black_color, [480, 480], 5, 0)
pygame.draw.circle(screen, black_color, [480, 160], 5, 0)
pygame.draw.circle(screen, black_color, [160, 480], 5, 0)
for row in range(len(self._board)):
for col in range(len(self._board[row])):
if self._board[row][col] != EMPTY:
ccolor = black_color \
if self._board[row][col] == BLACK else white_color
pos = [40 * (col + 1), 40 * (row + 1)]
pygame.draw.circle(screen, ccolor, pos, 20, 0)
def main():
board = RenjuBoard()
is_black = True
pygame.init()
pygame.display.set_caption('五子棋')
screen = pygame.display.set_mode([640, 640])
screen.fill([255, 255, 0])
board.draw(screen)
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYUP:
pass
elif event.type == pygame.MOUSEBUTTONDOWN\
and event.button == 1:
x, y = event.pos
row = round((y - 40) / 40)
col = round((x - 40) / 40)
if board.move(row, col, is_black):
is_black = not is_black
screen.fill([255, 255, 0])
board.draw(screen)
pygame.display.flip()
if board.check(row,col,board._board[row][col]):
if board._board[row][col]==BLACK:
messagebox.showinfo("提示","黑色方胜利!")
pygame.quit()
else:
messagebox.showinfo("提示","白色方胜利!")
pygame.quit()
pygame.quit()
if __name__ == '__main__':
main()
下面我会对五子棋判断胜负的部分进行解释,毕竟其他的都很简单
check(self,y,x,flag)
判断胜负的函数
leftEdge = x - 5
rightEdge = x +5
topEdge = y - 5
bottomEdge = y + 5
if leftEdge<0:
leftEdge = 0
if rightEdge>14:
rightEdge=14
if topEdge<0:
topEdge=0
if bottomEdge>14:
bottomEdge=14
首先确定搜索的区域范围,是以当前的点为中心的9*9的点阵范围,但是棋盘会有边界,所以又对棋盘边界进行了优化处理,缩小搜索范围。
dirs = [
Point(0,1),
Point(1,1),
Point(1,0),
Point(1,-1),
Point(0,-1),
Point(-1,-1),
Point(-1,0),
Point(-1,1)
]
dirs代表8个方向,依次是从Y轴正方向顺时针旋转的8个方向,即上、右上、右…
length=[0]*8
用来存储每个方向的长度
for i in range(8):
l=0
pos = Point(x,y)
while self._board[pos._y][pos._x]==flag:
pos += dirs[i]
l+=1
if pos._x<leftEdge or pos._x >rightEdge or/
pos._y<topEdge or pos._y > bottomEdge:
break
length[i]=l
用来计算8个方向的的长度,包括了自身
for i in range(4):
total = length[i] + length[i+4]-1
if total>=5:
return True
return False
用来计算8个方向的的长度,包括了自身
for i in range(4):
total = length[i] + length[i+4]-1
if total>=5:
return True
return False
计算横竖左斜右斜四个方向的总长度,因为包括了自身,所以total最后还需要-1