AI,双人五子棋

来,上代码(pygame要下载,不多说了!)

# 先导入tkinter, sys, re库
from tkinter import *
from tkinter import messagebox as msgbox
import sys
import re
 
 
"""五子棋之人机对战"""

import sys
import tkinter as tk
import random
import pygame
from pygame.locals import *
import pygame.gfxdraw
from collections import namedtuple

Chessman = namedtuple('Chessman', 'Name Value Color')
Point = namedtuple('Point', 'X Y')

BLACK_CHESSMAN = Chessman('黑子', 1, (45, 45, 45))
WHITE_CHESSMAN = Chessman('白子', 2, (219, 219, 219))

offset = [(1, 0), (0, 1), (1, 1), (1, -1)]

class Checkerboard:
    def __init__(self, line_points):
        self._line_points = line_points
        self._checkerboard = [[0] * line_points for _ in range(line_points)]

    def _get_checkerboard(self):
        return self._checkerboard

    checkerboard = property(_get_checkerboard)

    # 判断是否可落子
    def can_drop(self, point):
        return self._checkerboard[point.Y][point.X] == 0

    def drop(self, chessman, point):
        """
        落子
        :param chessman:
        :param point:落子位置
        :return:若该子落下之后即可获胜,则返回获胜方,否则返回 None
        """
        print(f'{chessman.Name} ({point.X}, {point.Y})')
        self._checkerboard[point.Y][point.X] = chessman.Value

        if self._win(point):
            print(f'{chessman.Name}获胜')
            
            return chessman

    # 判断是否赢了
    def _win(self, point):
        cur_value = self._checkerboard[point.Y][point.X]
        for os in offset:
            if self._get_count_on_direction(point, cur_value, os[0], os[1]):
                return True

    def _get_count_on_direction(self, point, value, x_offset, y_offset):
        count = 1
        for step in range(1, 5):
            x = point.X + step * x_offset
            y = point.Y + step * y_offset
            if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:
                count += 1
            else:
                break
        for step in range(1, 5):
            x = point.X - step * x_offset
            y = point.Y - step * y_offset
            if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:
                count += 1
            else:
                break

        return count >= 5


SIZE = 30  # 棋盘每个点时间的间隔
Line_Points = 19  # 棋盘每行/每列点数
Outer_Width = 20  # 棋盘外宽度
Border_Width = 4  # 边框宽度
Inside_Width = 4  # 边框跟实际的棋盘之间的间隔
Border_Length = SIZE * (Line_Points - 1) + Inside_Width * 2 + Border_Width  # 边框线的长度
Start_X = Start_Y = Outer_Width + int(Border_Width / 2) + Inside_Width  # 网格线起点(左上角)坐标
SCREEN_HEIGHT = SIZE * (Line_Points - 1) + Outer_Width * 2 + Border_Width + Inside_Width * 2  # 游戏屏幕的高
SCREEN_WIDTH = SCREEN_HEIGHT + 200  # 游戏屏幕的宽

Stone_Radius = SIZE // 2 - 3  # 棋子半径
Stone_Radius2 = SIZE // 2 + 3
Checkerboard_Color = (0xE3, 0x92, 0x65)  # 棋盘颜色
BLACK_COLOR = (0, 0, 0)
WHITE_COLOR = (255, 255, 255)
RED_COLOR = (200, 30, 30)
BLUE_COLOR = (30, 30, 200)

RIGHT_INFO_POS_X = SCREEN_HEIGHT + Stone_Radius2 * 2 + 10


def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
    imgText = font.render(text, True, fcolor)
    screen.blit(imgText, (x, y))


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption('单机练兵(困难模式)')

    font1 = pygame.font.SysFont('SimHei', 32)
    font2 = pygame.font.SysFont('SimHei', 72)
    fwidth, fheight = font2.size('黑方获胜')

    checkerboard = Checkerboard(Line_Points)
    cur_runner = BLACK_CHESSMAN
    winner = None
    computer = AI(Line_Points, WHITE_CHESSMAN)

    black_win_count = 0
    white_win_count = 0

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_RETURN:
                    if winner is not None:
                        winner = None
                        cur_runner = BLACK_CHESSMAN
                        checkerboard = Checkerboard(Line_Points)
                        computer = AI(Line_Points, WHITE_CHESSMAN)
            elif event.type == MOUSEBUTTONDOWN:
                if winner is None:
                    pressed_array = pygame.mouse.get_pressed()
                    if pressed_array[0]:
                        mouse_pos = pygame.mouse.get_pos()
                        click_point = _get_clickpoint(mouse_pos)
                        if click_point is not None:
                            if checkerboard.can_drop(click_point):
                                winner = checkerboard.drop(cur_runner, click_point)
                                if winner is None:
                                    cur_runner = _get_next(cur_runner)
                                    computer.get_opponent_drop(click_point)
                                    AI_point = computer.AI_drop()
                                    winner = checkerboard.drop(cur_runner, AI_point)
                                    if winner is not None:
                                        white_win_count += 1
                                    cur_runner = _get_next(cur_runner)
                                else:
                                    black_win_count += 1
                        else:
                            print('超出棋盘区域')

        # 画棋盘
        _draw_checkerboard(screen)

        # 画棋盘上已有的棋子
        for i, row in enumerate(checkerboard.checkerboard):
            for j, cell in enumerate(row):
                if cell == BLACK_CHESSMAN.Value:
                    _draw_chessman(screen, Point(j, i), BLACK_CHESSMAN.Color)
                elif cell == WHITE_CHESSMAN.Value:
                    _draw_chessman(screen, Point(j, i), WHITE_CHESSMAN.Color)

        _draw_left_info(screen, font1, cur_runner, black_win_count, white_win_count)

        if winner:
            print_text(screen, font2, (SCREEN_WIDTH - fwidth)//2, (SCREEN_HEIGHT - fheight)//2, winner.Name + '获胜', RED_COLOR)

        pygame.display.flip()


def _get_next(cur_runner):
    if cur_runner == BLACK_CHESSMAN:
        return WHITE_CHESSMAN
    else:
        return BLACK_CHESSMAN


# 画棋盘
def _draw_checkerboard(screen):
    # 填充棋盘背景色
    screen.fill(Checkerboard_Color)
    # 画棋盘网格线外的边框
    pygame.draw.rect(screen, BLACK_COLOR, (Outer_Width, Outer_Width, Border_Length, Border_Length), Border_Width)
    # 画网格线
    for i in range(Line_Points):
        pygame.draw.line(screen, BLACK_COLOR,
                         (Start_Y, Start_Y + SIZE * i),
                         (Start_Y + SIZE * (Line_Points - 1), Start_Y + SIZE * i),
                         1)
    for j in range(Line_Points):
        pygame.draw.line(screen, BLACK_COLOR,
                         (Start_X + SIZE * j, Start_X),
                         (Start_X + SIZE * j, Start_X + SIZE * (Line_Points - 1)),
                         1)
    # 画星位和天元
    for i in (3, 9, 15):
        for j in (3, 9, 15):
            if i == j == 9:
                radius = 5
            else:
                radius = 3
            # pygame.draw.circle(screen, BLACK, (Start_X + SIZE * i, Start_Y + SIZE * j), radius)
            pygame.gfxdraw.aacircle(screen, Start_X + SIZE * i, Start_Y + SIZE * j, radius, BLACK_COLOR)
            pygame.gfxdraw.filled_circle(screen, Start_X + SIZE * i, Start_Y + SIZE * j, radius, BLACK_COLOR)


# 画棋子
def _draw_chessman(screen, point, stone_color):
    # pygame.draw.circle(screen, stone_color, (Start_X + SIZE * point.X, Start_Y + SIZE * point.Y), Stone_Radius)
    pygame.gfxdraw.aacircle(screen, Start_X + SIZE * point.X, Start_Y + SIZE * point.Y, Stone_Radius, stone_color)
    pygame.gfxdraw.filled_circle(screen, Start_X + SIZE * point.X, Start_Y + SIZE * point.Y, Stone_Radius, stone_color)


# 画左侧信息显示
def _draw_left_info(screen, font, cur_runner, black_win_count, white_win_count):
    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2), BLACK_CHESSMAN.Color)
    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2 * 4), WHITE_CHESSMAN.Color)

    print_text(screen, font, RIGHT_INFO_POS_X, Start_X + 3, '玩家', BLUE_COLOR)
    print_text(screen, font, RIGHT_INFO_POS_X, Start_X + Stone_Radius2 * 3 + 3, '电脑', BLUE_COLOR)

    print_text(screen, font, SCREEN_HEIGHT, SCREEN_HEIGHT - Stone_Radius2 * 8, '战况:', BLUE_COLOR)
    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, SCREEN_HEIGHT - int(Stone_Radius2 * 4.5)), BLACK_CHESSMAN.Color)
    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, SCREEN_HEIGHT - Stone_Radius2 * 2), WHITE_CHESSMAN.Color)
    print_text(screen, font, RIGHT_INFO_POS_X, SCREEN_HEIGHT - int(Stone_Radius2 * 5.5) + 3, f'{black_win_count} 胜', BLUE_COLOR)
    print_text(screen, font, RIGHT_INFO_POS_X, SCREEN_HEIGHT - Stone_Radius2 * 3 + 3, f'{white_win_count} 胜', BLUE_COLOR)


def _draw_chessman_pos(screen, pos, stone_color):
    pygame.gfxdraw.aacircle(screen, pos[0], pos[1], Stone_Radius2, stone_color)
    pygame.gfxdraw.filled_circle(screen, pos[0], pos[1], Stone_Radius2, stone_color)


# 根据鼠标点击位置,返回游戏区坐标
def _get_clickpoint(click_pos):
    pos_x = click_pos[0] - Start_X
    pos_y = click_pos[1] - Start_Y
    if pos_x < -Inside_Width or pos_y < -Inside_Width:
        return None
    x = pos_x // SIZE
    y = pos_y // SIZE
    if pos_x % SIZE > Stone_Radius:
        x += 1
    if pos_y % SIZE > Stone_Radius:
        y += 1
    if x >= Line_Points or y >= Line_Points:
        return None

    return Point(x, y)


class AI:
    def __init__(self, line_points, chessman):
        self._line_points = line_points
        self._my = chessman
        self._opponent = BLACK_CHESSMAN if chessman == WHITE_CHESSMAN else WHITE_CHESSMAN
        self._checkerboard = [[0] * line_points for _ in range(line_points)]

    def get_opponent_drop(self, point):
        self._checkerboard[point.Y][point.X] = self._opponent.Value

    def AI_drop(self):
        point = None
        score = 0
        for i in range(self._line_points):
            for j in range(self._line_points):
                if self._checkerboard[j][i] == 0:
                    _score = self._get_point_score(Point(i, j))
                    if _score > score:
                        score = _score
                        point = Point(i, j)
                    elif _score == score and _score > 0:
                        r = random.randint(0, 100)
                        if r % 2 == 0:
                            point = Point(i, j)
        self._checkerboard[point.Y][point.X] = self._my.Value
        return point

    def _get_point_score(self, point):
        score = 0
        for os in offset:
            score += self._get_direction_score(point, os[0], os[1])
        return score

    def _get_direction_score(self, point, x_offset, y_offset):
        count = 0   # 落子处我方连续子数
        _count = 0  # 落子处对方连续子数
        space = None   # 我方连续子中有无空格
        _space = None  # 对方连续子中有无空格
        both = 0    # 我方连续子两端有无阻挡
        _both = 0   # 对方连续子两端有无阻挡

        # 如果是 1 表示是边上是我方子,2 表示敌方子
        flag = self._get_stone_color(point, x_offset, y_offset, True)
        if flag != 0:
            for step in range(1, 6):
                x = point.X + step * x_offset
                y = point.Y + step * y_offset
                if 0 <= x < self._line_points and 0 <= y < self._line_points:
                    if flag == 1:
                        if self._checkerboard[y][x] == self._my.Value:
                            count += 1
                            if space is False:
                                space = True
                        elif self._checkerboard[y][x] == self._opponent.Value:
                            _both += 1
                            break
                        else:
                            if space is None:
                                space = False
                            else:
                                break   # 遇到第二个空格退出
                    elif flag == 2:
                        if self._checkerboard[y][x] == self._my.Value:
                            _both += 1
                            break
                        elif self._checkerboard[y][x] == self._opponent.Value:
                            _count += 1
                            if _space is False:
                                _space = True
                        else:
                            if _space is None:
                                _space = False
                            else:
                                break
                else:
                    # 遇到边也就是阻挡
                    if flag == 1:
                        both += 1
                    elif flag == 2:
                        _both += 1

        if space is False:
            space = None
        if _space is False:
            _space = None

        _flag = self._get_stone_color(point, -x_offset, -y_offset, True)
        if _flag != 0:
            for step in range(1, 6):
                x = point.X - step * x_offset
                y = point.Y - step * y_offset
                if 0 <= x < self._line_points and 0 <= y < self._line_points:
                    if _flag == 1:
                        if self._checkerboard[y][x] == self._my.Value:
                            count += 1
                            if space is False:
                                space = True
                        elif self._checkerboard[y][x] == self._opponent.Value:
                            _both += 1
                            break
                        else:
                            if space is None:
                                space = False
                            else:
                                break   # 遇到第二个空格退出
                    elif _flag == 2:
                        if self._checkerboard[y][x] == self._my.Value:
                            _both += 1
                            break
                        elif self._checkerboard[y][x] == self._opponent.Value:
                            _count += 1
                            if _space is False:
                                _space = True
                        else:
                            if _space is None:
                                _space = False
                            else:
                                break
                else:
                    # 遇到边也就是阻挡
                    if _flag == 1:
                        both += 1
                    elif _flag == 2:
                        _both += 1

        score = 0
        if count == 4:
            score = 10000
        elif _count == 4:
            score = 9000
        elif count == 3:
            if both == 0:
                score = 1000
            elif both == 1:
                score = 100
            else:
                score = 0
        elif _count == 3:
            if _both == 0:
                score = 900
            elif _both == 1:
                score = 90
            else:
                score = 0
        elif count == 2:
            if both == 0:
                score = 100
            elif both == 1:
                score = 10
            else:
                score = 0
        elif _count == 2:
            if _both == 0:
                score = 90
            elif _both == 1:
                score = 9
            else:
                score = 0
        elif count == 1:
            score = 10
        elif _count == 1:
            score = 9
        else:
            score = 0

        if space or _space:
            score /= 2

        return score

    # 判断指定位置处在指定方向上是我方子、对方子、空
    def _get_stone_color(self, point, x_offset, y_offset, next):
        x = point.X + x_offset
        y = point.Y + y_offset
        if 0 <= x < self._line_points and 0 <= y < self._line_points:
            if self._checkerboard[y][x] == self._my.Value:
                return 1
            elif self._checkerboard[y][x] == self._opponent.Value:
                return 2
            else:
                if next:
                    return self._get_stone_color(Point(x, y), x_offset, y_offset, False)
                else:
                    return 0
        else:
            return 0




import random
import sys
import pygame

import numpy as np

# 0表示空棋
# 1表示黑棋
# 2表示白棋
# 3表示下棋的位置

cdata = [
    # 一颗棋子的情况

    [1, 3, 0, 0, 0], [0, 1, 3, 0, 0], [0, 0, 1, 3, 0], [0, 0, 0, 1, 3], [0, 0, 0, 3, 1],
    [2, 3, 0, 0, 0], [0, 2, 3, 0, 0], [0, 0, 2, 3, 0], [0, 0, 0, 2, 3], [0, 0, 0, 3, 2],
    # 二颗棋子的情况
    [0, 1, 3, 1, 0], [1, 1, 3, 0, 0], [0, 0, 3, 1, 1],
    [2, 2, 3, 0, 0], [0, 0, 3, 2, 2], [0, 2, 3, 2, 0],
    # 三颗棋子的情况
    [1, 1, 1, 3, 0], [0, 3, 1, 1, 1], [1, 1, 3, 1, 0], [1, 3, 1, 1, 0],
    [2, 2, 0, 3, 2], [2, 3, 0, 2, 2], [0, 3, 2, 2, 2], [2, 2, 3, 2, 0],
    [2, 3, 2, 2, 0], [0, 2, 3, 2, 2], [0, 2, 2, 3, 2], [2, 2, 2, 3, 0], [3, 2, 2, 2, 0],
    # 四颗棋子情况
    [1, 1, 1, 1, 3], [3, 1, 1, 1, 1], [1, 1, 1, 3, 1], [1, 3, 1, 1, 1], [1, 1, 3, 1, 1],
    [2, 2, 2, 2, 3], [3, 2, 2, 2, 2], [2, 2, 3, 2, 2], [2, 3, 2, 2, 2], [2, 2, 2, 3, 2]
]


def auto_mach(row, col, level, dx, dy):
    global ai_col, ai_row, max_level
    col_sel = -1  # 暂存棋子列号
    row_sel = -1  # 暂存棋子行号
    isfind = True  # 匹配成功的标记

    for j in range(5):
        cs = alist[row + j * dx][col + j * dy]
        if cs == 0:
            if cdata[level][j] == 3:
                row_sel = row + j * dx
                col_sel = col + j * dy
            elif cdata[level][j] == 1:
                isfind = False
                break
            elif cdata[level][j] == 2:
                isfind = False
                break
        elif cs != cdata[level][j]:
            isfind = False
            break
    if isfind:
        ai_row = row_sel
        ai_col = col_sel
        max_level = level
        return True
    return False


def ai_play():
    global ai_col, ai_row, max_level
    ai_col = -1
    ai_row = -1
    max_level = -1
    # 搜素棋盘每个位置
    for i in range(19):
        for j in range(19):
            # 从高到低搜索
            for level in range(len(cdata) - 1, -1, -1):
                if level > max_level:
                    if i + 4 < 19:
                        if auto_mach(i, j, level, 1, 0):
                            break
                    if j + 4 < 19:
                        if auto_mach(i, j, level, 0, 1):
                            break

                    if i + 4 < 19 and j + 4 < 19:
                        if auto_mach(i, j, level, 1, 1):
                            break

                    if j + 4 < 19 and i - 4 > 0:
                        if auto_mach(i, j, level, -1, 1):
                            break
    if ai_row!=-1 and ai_row!=-1:
        alist[ai_row][ai_col]=2
        return True
    while True:
        col = random.randint(0,18)
        row = random.randint(0, 18)
        if alist[row][col]==0:
            alist[row][col]=2
            ai_row=row
            ai_col=col

            return True
    return False


def init():
    pygame.init()
    # 创建窗口,背景为棕色
    global screen
    screen = pygame.display.set_mode((615, 615))
    pygame.display.set_caption('单机练兵(简单模式)')
    screen.fill("#DD954F")
    # 创建外边框

    a = pygame.Surface((603, 603), flags=pygame.HWSURFACE)
    a.fill(color='#121010')
    b = pygame.Surface((585, 585), flags=pygame.HWSURFACE)
    b.fill(color="#DD954F")
    c = pygame.Surface((579, 579), flags=pygame.HWSURFACE)
    c.fill(color='#121010')

    e = pygame.Surface((31, 31), flags=pygame.HWSURFACE)
    e.fill(color="#DD954F")
    screen.blit(a, (6.5, 6.5))
    screen.blit(b, (15, 15))
    screen.blit(c, (18, 18))
    # 棋盘格子
    for j in range(18):
        for i in range(18):
            # 起点是20,间隔是32,每个格子大小31,所以格子间距1
            screen.blit(e, (20 + 32 * i, 20 + 32 * j))
    # 存储棋盘状态
    global alist
    alist = np.zeros((19, 19))
    # 星位
    pygame.draw.circle(screen, '#121010', [307.5, 307.5], 5)
    pygame.draw.circle(screen, '#121010', [115.5, 307.5], 5)
    pygame.draw.circle(screen, '#121010', [499.5, 307.5], 5)
    pygame.draw.circle(screen, '#121010', [115.5, 499.5], 5)
    pygame.draw.circle(screen, '#121010', [499.5, 499.5], 5)
    pygame.draw.circle(screen, '#121010', [115.5, 115.5], 5)
    pygame.draw.circle(screen, '#121010', [499.5, 115.5], 5)
    pygame.draw.circle(screen, '#121010', [307.5, 499.5], 5)
    pygame.draw.circle(screen, '#121010', [307.5, 115.5], 5)
    # 刷新窗口
    pygame.display.flip()


# 绘制棋子
def black(x, y):
    a = 20
    b = 20
    c = 20
    d = 0.01
    # 循环50次,每次绘制50个半径颜色不同的同心圆
    for i in range(50):
        pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))
        a += 1
        b += 1
        c += 1
        d += 0.08
    pygame.display.update()


def white(x, y):
    a = 170
    b = 170
    c = 170
    d = 0.02
    for i in range(50):
        pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))
        a += 1
        b += 1
        c += 1
        d += 0.08
    pygame.display.update()


pygame.font.init()
font1 = pygame.font.Font(None, 250)


# 主要操作
def do(wb):
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                x, y = pygame.mouse.get_pos()
                # 棋盘边界线的中点是19.5, 通过计算得到当前坐标在棋盘的行号和列号(x,y)
                x = round((x - 19.5) / 32)
                y = round((y - 19.5) / 32)
                if x < 0:
                    x = 0
                if x > 18:
                    x = 18
                if y < 0:
                    y = 0
                if y > 18:
                    y = 18
                if alist[x][y] == 0:
                    black(x, y)
                    alist[x][y] = 1
                    wb1 = "You"
                    wb = "white"
                    check(x, y, wb1)
                    pygame.time.wait(100)
                    if ai_play():
                        white(ai_row, ai_col)
                        wb1 = "AI"
                        wb = "black"
                        check(ai_row, ai_col, wb1)

def check(x, y, wb1):
    xx = x
    yy = y
    while True:
        # 从最上边的棋子开始检查,记录颜色相同得棋子数量
        # 先找到最同一条线上最上边的同色棋子
        if xx == 0:
            if alist[xx][yy] != alist[x][y]:
                xx += 1
            break
        elif alist[xx][yy] != alist[x][y]:
            xx += 1
            break
        else:
            xx -= 1
    num = 0
    while True:
        if xx == 18:
            if alist[xx][yy] == alist[x][y]:
                num += 1
            break
        elif alist[xx][yy] != alist[x][y]:
            break
        else:
            xx += 1
            num += 1
    if num >= 5:
        win(wb1)
    # 从最边的棋子开始检查,记录颜色相同得棋子数量
    # 先找到最同一条线上最左边的同色棋子
    xx = x
    yy = y
    while True:
        if yy == 0:
            if alist[xx][yy] != alist[x][y]:
                yy += 1

            break
        elif alist[xx][yy] != alist[x][y]:
            yy += 1
            break
        else:
            yy -= 1
    num = 0
    while True:
        if yy == 18:
            if alist[xx][yy] == alist[x][y]:
                num += 1
            break
        elif alist[xx][yy] != alist[x][y]:
            break
        else:
            yy += 1
            num += 1
    if num >= 5:
        win(wb1)

    # 从左上方的棋子开始检查,记录颜色相同得棋子数量

    # 先找到最同一条线上左上方的同色棋子
    xx = x
    yy = y
    while True:
        if xx == 0:
            if alist[xx][yy] != alist[x][y]:
                xx += 1
                yy += 1
            break
        elif yy == 0:
            if alist[xx][yy] != alist[x][y]:
                xx += 1
                yy += 1
            break
        elif alist[xx][yy] != alist[x][y]:
            xx += 1
            yy += 1
            break
        else:
            xx -= 1
            yy -= 1
    num = 0
    while True:
        if xx == 18:
            if alist[xx][yy] == alist[x][y]:
                num += 1

            break
        elif yy == 18:
            if alist[xx][yy] == alist[x][y]:
                num += 1
            break
        elif alist[xx][yy] != alist[x][y]:
            break
        else:
            xx += 1
            yy += 1
            num += 1
    if num >= 5:
        win(wb1)

    # 从右上方的棋子开始检查,记录颜色相同得棋子数量

    # 先找到最同一条线上右上方的同色棋子
    xx = x
    yy = y
    while True:
        if xx == 0:
            if alist[xx][yy] != alist[x][y]:
                xx += 1
                yy -= 1
            break
        elif yy == 18:
            if alist[xx][yy] != alist[x][y]:
                xx += 1
                yy -= 1
            break
        elif alist[xx][yy] != alist[x][y]:
            xx += 1
            yy -= 1
            break
        else:
            xx -= 1
            yy += 1
    num = 0
    while True:
        if xx == 18:
            if alist[xx][yy] == alist[x][y]:
                num += 1
            break
        elif yy == 0:
            if alist[xx][yy] == alist[x][y]:
                num += 1
            break
        elif alist[xx][yy] != alist[x][y]:
            break
        else:
            xx += 1
            yy -= 1
            num += 1
    if num >= 5:
        win(wb1)


def win(wb1):
    pygame.font.init()
    font = pygame.font.Font(None, 70)

    text = font.render(f"{wb1}  win", True, (255, 255, 255))
    screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))
    pygame.display.update()

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                init()
                text = font.render("Start the game", True, (255, 255, 255))
                screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))
                pygame.display.update()
                pygame.time.wait(500)
                init()
                do("black")

'''
@Auther : gaoxin
@Date : 2024.01.20
@Version : 1.0

'''

from tkinter import *
from tkinter import messagebox
import math


# 0表示空棋
# 1表示黑棋
# 2表示白棋
# 3表示下棋的位置

cdata = [
    # 一颗棋子的情况

    [1, 3, 0, 0, 0], [0, 1, 3, 0, 0], [0, 0, 1, 3, 0], [0, 0, 0, 1, 3], [0, 0, 0, 3, 1],
    [2, 3, 0, 0, 0], [0, 2, 3, 0, 0], [0, 0, 2, 3, 0], [0, 0, 0, 2, 3], [0, 0, 0, 3, 2],
    # 二颗棋子的情况
    [0, 1, 3, 1, 0], [1, 1, 3, 0, 0], [0, 0, 3, 1, 1],
    [2, 2, 3, 0, 0], [0, 0, 3, 2, 2], [0, 2, 3, 2, 0],
    # 三颗棋子的情况
    [1, 1, 1, 3, 0], [0, 3, 1, 1, 1], [1, 1, 3, 1, 0], [1, 3, 1, 1, 0],
    [2, 2, 0, 3, 2], [2, 3, 0, 2, 2], [0, 3, 2, 2, 2], [2, 2, 3, 2, 0],
    [2, 3, 2, 2, 0], [0, 2, 3, 2, 2], [0, 2, 2, 3, 2], [2, 2, 2, 3, 0], [3, 2, 2, 2, 0],
    # 四颗棋子情况
    [1, 1, 1, 1, 3], [3, 1, 1, 1, 1], [1, 1, 1, 3, 1], [1, 3, 1, 1, 1], [1, 1, 3, 1, 1],
    [2, 2, 2, 2, 3], [3, 2, 2, 2, 2], [2, 2, 3, 2, 2], [2, 3, 2, 2, 2], [2, 2, 2, 3, 2]
]

def auto_mach(row, col, level, dx, dy):
    global ai_col, ai_row, max_level
    col_sel = -1  # 暂存棋子列号
    row_sel = -1  # 暂存棋子行号
    isfind = True  # 匹配成功的标记

    for j in range(5):
        cs = alist[row + j * dx][col + j * dy]
        if cs == 0:
            if cdata[level][j] == 3:
                row_sel = row + j * dx
                col_sel = col + j * dy
            elif cdata[level][j] == 1:
                isfind = False
                break
            elif cdata[level][j] == 2:
                isfind = False
                break
        elif cs != cdata[level][j]:
            isfind = False
            break
    if isfind:
        ai_row = row_sel
        ai_col = col_sel
        max_level = level
        return True
    return False

#定义棋盘类
class chessBoard() :
 def __init__(self) :
  self.window = Tk()
  self.window.title("双人对战")
  self.window.geometry("660x470")
  self.window.resizable(0,0)
  self.canvas=Canvas(self.window , bg="#EEE8AC" , width=470, height=470)
  self.paint_board()
  self.canvas.grid(row = 0 , column = 0)
 def paint_board(self) :
  for row in range(0,15) :
   if row == 0 or row == 14 :
    self.canvas.create_line(25 , 25+row*30 , 25+14*30 , 25+row*30 , width = 2)
   else :
    self.canvas.create_line(25 , 25+row*30 , 25+14*30 , 25+row*30 , width = 1)
  for column in range(0,15) :
   if column == 0 or column == 14 :
    self.canvas.create_line(25+column*30 ,25, 25+column*30 , 25+14*30 ,width = 2)
   else :
    self.canvas.create_line(25+column*30 ,25, 25+column*30 , 25+14*30 , width = 1)
   
  self.canvas.create_oval(112, 112, 118, 118, fill="black")
  self.canvas.create_oval(352, 112, 358, 118, fill="black")
  self.canvas.create_oval(112, 352, 118, 358, fill="black")
  self.canvas.create_oval(232, 232, 238, 238, fill="black")
  self.canvas.create_oval(352, 352, 358, 358, fill="black")


#定义五子棋游戏类
#0为黑子 , 1为白子 , 2为空位
class Gobang() :
 #初始化
 def __init__(self) :
  self.board = chessBoard()
  self.game_print = StringVar()
  self.game_print.set("")
  #16*16的二维列表,保证不会out of index
  self.db = [([2] * 16) for i in range(16)]
  #悔棋用的顺序列表
  self.order = []
  #棋子颜色
  self.color_count = 0 
  self.color = 'black'
  #清空与赢的初始化,已赢为1,已清空为1
  self.flag_win = 1
  self.flag_empty = 1
  self.options()
  
  
 #黑白互换
 def change_color(self) :
  self.color_count = (self.color_count + 1 ) % 2
  if self.color_count == 0 :
   self.color = "black"
  elif self.color_count ==1 :
   self.color = "white"
 
 
 #落子
 def chess_moving(self ,event) :
  #不点击“开始”与“清空”无法再次开始落子
  if self.flag_win ==1 or self.flag_empty ==0 :
   return
  #坐标转化为下标
  x,y = event.x-25 , event.y-25
  x = round(x/30)
  y = round(y/30)
  #点击位置没用落子,且没有在棋盘线外,可以落子
  while self.db[y][x] == 2 and self.limit_boarder(y,x):
   self.db[y][x] = self.color_count
   self.order.append(x+15*y) 
   self.board.canvas.create_oval(25+30*x-12 , 25+30*y-12 , 25+30*x+12 , 25+30*y+12 , fill = self.color,tags = "chessman")
   if self.game_win(y,x,self.color_count) :
    self.game_print.set(self.color+"获胜")
    messagebox.showinfo("game over",self.color+"获胜")
   else :
    self.change_color()
    self.game_print.set("请"+self.color+"落子")

 #保证棋子落在棋盘上
 def limit_boarder(self , y , x) :
  if x<0 or x>14 or y<0 or y>14 :
   return False
  else :
   return True


 #计算连子的数目,并返回最大连子数目
 def chessman_count(self , y , x , color_count ) :
  count1,count2,count3,count4 = 1,1,1,1
  #横计算
  for i in range(-1 , -5 , -1) :
   if self.db[y][x+i] == color_count :
    count1 += 1
   else:
    break 
  for i in range(1 , 5 ,1 ) :
   if self.db[y][x+i] == color_count :
    count1 += 1
   else:
    break 
  #竖计算
  for i in range(-1 , -5 , -1) :
   if self.db[y+i][x] == color_count :
    count2 += 1
   else:
    break 
  for i in range(1 , 5 ,1 ) :
   if self.db[y+i][x] == color_count :
    count2 += 1
   else:
    break 
  #/计算
  for i in range(-1 , -5 , -1) :
   if self.db[y+i][x+i] == color_count :
    count3 += 1
   else:
    break 
  for i in range(1 , 5 ,1 ) :
   if self.db[y+i][x+i] == color_count :
    count3 += 1
   else:
    break 
  #\计算
  for i in range(-1 , -5 , -1) :
   if self.db[y+i][x-i] == color_count :
    count4 += 1
   else:
    break 
  for i in range(1 , 5 ,1 ) :
   if self.db[y+i][x-i] == color_count :
    count4 += 1
   else:
    break 
   
  return max(count1 , count2 , count3 , count4)


 #判断输赢
 def game_win(self , y , x , color_count ) :
  if self.chessman_count(y,x,color_count) >= 5 :
   self.flag_win = 1
   self.flag_empty = 0
   return True
  else :
   return False
  

 #悔棋,清空棋盘,再画剩下的n-1个棋子
 def withdraw(self ) :
  if len(self.order)==0 or self.flag_win == 1:
   return
  self.board.canvas.delete("chessman")
  z = self.order.pop()
  x = z%15
  y = z//15
  self.db[y][x] = 2
  self.color_count = 1
  for i in self.order :
   ix = i%15
   iy = i//15
   self.change_color()
   self.board.canvas.create_oval(25+30*ix-12 , 25+30*iy-12 , 25+30*ix+12 , 25+30*iy+12 , fill = self.color,tags = "chessman")
  self.change_color()
  self.game_print.set("请"+self.color+"落子")
 

 #清空
 def empty_all(self) :
  self.board.canvas.delete("chessman")
  #还原初始化
  self.db = [([2] * 16) for i in range(16)]
  self.order = []
  self.color_count = 0 
  self.color = 'black'
  self.flag_win = 1
  self.flag_empty = 1
  self.game_print.set("")

 def rules_of_the_game(self):
  messagebox.showinfo("游戏规则","游戏规则:1.五子棋是两个人之间进行的竞技活动,由于对黑方白方规则不同,黑棋必须先行。2.五子棋专用盘为 15×15 ,五连子的方向为横、竖、斜。")
 def take_a_stop(self):
  self.color_count = self.color_count - 1
  self.color_count = (self.color_count + 1 ) % 2
  if self.color_count == 0 :
   self.color = "black"
   self.change_color()
   self.game_print.set("请"+self.color+"落子")
  elif self.color_count ==1 :
   self.color = "white"
   self.change_color()
   self.game_print.set("请"+self.color+"落子")
 #将self.flag_win置0才能在棋盘上落子
 def game_start(self) :
  #没有清空棋子不能置0开始
  if self.flag_empty == 0:
   return
  self.flag_win = 0
  self.game_print.set("请"+self.color+"落子")

 def ren_shu(self):
  if self.color == "black":
   self.game_print.set("white获胜")
   messagebox.showinfo("game over","white获胜")
   self.flag_win = 1
   self.flag_empty = 0
  else:
   self.game_print.set("black获胜")
   messagebox.showinfo("game over","black获胜")
   self.flag_win = 1
   self.flag_empty = 0
 def options(self) :
  self.board.canvas.bind("<Button-1>",self.chess_moving)
  Label(self.board.window , textvariable = self.game_print , font = ("Arial", 20) ).place(relx = 0, rely = 0 ,x = 495 , y = 200)
  Button(self.board.window , text= "开始游戏" ,command = self.game_start,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=15)
  Button(self.board.window , text= " 悔棋 " ,command = self.withdraw,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=60)
  Button(self.board.window , text= "停走一步" ,command = self.take_a_stop,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=105)
  Button(self.board.window , text= "清空棋局" ,command = self.empty_all,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=150)
  Button(self.board.window , text= "结束游戏" ,command = self.board.window.destroy,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=420)
  Button(self.board.window , text= "游戏规则" ,command = self.rules_of_the_game,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=375)
  Button(self.board.window , text= " 认输 " ,command = self.ren_shu,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=330)
  self.board.window.mainloop()

# 这里定义一个Tking类
class Tking(object):
    def a(self):
        self.winb.destroy()
        init()
        do("black")
    def b(self):
        self.wina.destroy()
        game = Gobang()
    def c(self):
        self.winb.destroy()
        main()
    def d(self):
        self.wina.destroy()
        self.winb = Tk()
        self.winb.geometry("300x200")
        self.winb.title("难度选择")
        button3 = Button(self.winb, text="简单模式", font=('宋体', 10), width=15, command=self.a)
        button3.place(x=100, y=50)
        button4 = Button(self.winb, text="困难模式", font=('宋体', 10), width=15, command=self.c)
        button4.place(x=100, y=125)
    # 初始化
    def __init__(self):
        self.win = Tk()
        self.count = 3
 
 
    # 定义函数来获取数据内容
    def read1(self):
        with open('zhanghao.txt', 'r')as f:
            file = f.read()
            return file
 
 
    # 定义函数来实现“登录”按钮的功能
    def js(self):
        # 调用函数获取账号信息
        data = self.read1()
 
        # 获取用户输入的信息
        user = self.username.get()
        passwd = self.passwd.get()
 
        # 使用正则得到我们想要的数据
        user1 = re.findall(r'账号:(.*\d?)', data)
        passwd1 = re.findall(r'密码:(.*\w?)', data)
 
        # 这里判断输入错误的次数,等于次就结束程序
        if self.count == 0:
            msgbox.showinfo('警告!', '非法入侵!\n启动自动销毁模式!!!')
            self.win.quit()
            sys.exit(0)
 
        # 这里对用户的数据和账号数据进行对比
        for i in range(len(user1)):
            if user == user1[i] and passwd == passwd1[i]:
                msgbox.showinfo('登录', '登录成功!')
                self.wina = Tk()
                self.wina.geometry("300x200")
                self.wina.title("五子棋")
                buttona = Button(self.wina, text="单机练兵", font=('宋体', 10), width=15, command=self.d)
                buttona.place(x=100, y=50)
                button2 = Button(self.wina, text="双人对战", font=('宋体', 10), width=15, command=self.b)
                button2.place(x=100, y=125)
                self.win.destroy()
                break
        else:
            msgbox.showinfo('失败!', '你还可以登录%s次' % self.count)
            self.count -= 1
 
 
    # 定义返回函数,使用“返回”按钮的功能
    def fanhui(self):
        # 使登录窗口恢复颜色,并销毁掉注册窗口
        self.win.attributes('-alpha', 1)
        self.win1.destroy()
 
 
    # 定义函数,实现注册功能
    def register(self):
        # 获取用户输入的数据
        username = self.username1.get()
        passwd1 = self.passwd1.get()
        passwd2 = self.passwd2.get()
 
        if passwd1 == '' or passwd2 == '':
            return msgbox.showerror('失败!', '不能填空!!!')
 
        # 判断用户输入的数据
        if passwd1 != passwd2:
            msgbox.showerror('失败!', '注册失败,两次密码不一致!')
        else:
            msgbox.showinfo('成功', '恭喜你注册成功!')
            with open('zhanghao.txt', 'a')as file:
                file.write('账号:')
                file.write(username + '\n')
                file.write('密码:')
                file.write(passwd2 + '\n')
 
 
    # 定义函数实现“注册”按钮的功能
    def js1(self):
        # 使用登录界面变成透明色,让用户看不到
        self.win.attributes('-alpha', -1)
 
        # 定义窗口2,来实现注册窗口
        self.win1 = Tk()
        self.win1.geometry("300x200")
        self.win1.title("注册")
 
        # 定义输入框
        self.username1 = Entry(self.win1)
        self.passwd1 = Entry(self.win1, show="*")
        self.passwd2 = Entry(self.win1, show="*")
        self.username1.place(x=110, y=25)
        self.passwd1.place(x=110, y=75)
        self.passwd2.place(x=110, y=125)
 
        # 定义标签
        name4 = Label(self.win1, text="用户名:", font=('宋体', 15), width=10)
        name4.place(x=1, y=20)
        name5 = Label(self.win1, text="密码:", font=('宋体', 15), width=10)
        name5.place(x=1, y=70)
        name6 = Label(self.win1, text="确认密码:", font=('宋体', 15), width=10)
        name6.place(x=1, y=120)
 
        # 定义按钮
        button = Button(self.win1, text="返回", font=('宋体', 10), width=5, command=self.fanhui)
        button.place(x=250, y=170)
        button1 = Button(self.win1, text="注册", font=('宋体', 15), width=10, command=self.register)
        button1.place(x=100, y=160)
 
        # 窗口运行
        self.win1.mainloop()
 
 
    # 定义函数,创建窗口
    def windows(self):
        self.win.geometry("300x200")
        self.win.title("登录")
 
        # 设置按钮
        self.username = Entry(self.win)
        self.passwd = Entry(self.win, show="*")
        self.username.place(x=110, y=25)
        self.passwd.place(x=110, y=75)
 
        # 设置标签,实现在窗口上打印“用户名:”等
        name1 = Label(self.win, text="用户名:", font=('宋体', 15), width=10)
        name1.place(x=1, y=20)
        name2 = Label(self.win, text="密码:", font=('宋体', 15), width=10)
        name2.place(x=1, y=70)
 
        # 设置按钮
        button = Button(self.win, text="登录", font=('宋体', 15), width=10, command=self.js)
        button.place(x=20, y=110)
        button1 = Button(self.win, text="注册", font=('宋体', 15), width=10, command=self.js1)
        button1.place(x=140, y=110)
 
        # 窗口运行
        self.win.mainloop()
 
 
# 调用类
if __name__ == '__main__':
    tk = Tking()
    tk.windows()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值