2020-3-24 利用python实现五子棋

利用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值