Make computers smarter - use python to implement the backgammon game

As a classic chess game, backgammon is deeply loved by the public. However, if it is only a game between people, the program is very simple. If it is to realize a human-machine battle and teach the computer how to defeat humans, it is not very easy. In this article, we will start with simplicity and complete the basic operations of the backgammon game, and then try to introduce some programming methods and techniques to realize artificial intelligence to realize human-machine games.

1. Create the chessboard and chess pieces

For chess games, the scene of the game is the board on which chess is played, and the main characters of the game are the chess pieces. Next we start creating the chessboard and chess pieces.

1.1 Draw the chessboard

The backgammon board can be seen as an 1818 grid. It is composed of 19 vertical lines and 19 horizontal lines (including borders). The intersection of the straight lines is The position of the chess piece. Here, we use 1818 brown grids to fill the chessboard. The spacing between each grid is the vertical and horizontal length of the chessboard. Interlaced lines, python libraries that can implement this function include pgzero and tkinter. Here we usepygame


    # 创建窗口,背景为棕色
 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')

 #
 # d = pygame.Surface((576, 576), flags=pygame.HWSURFACE)
 # d.fill(color="#DD954F")
 #棋盘格子
 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))
 #存储棋盘状态
 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()

1.2 Create chess pieces

I originally planned to post the picture directly, but then I referred to other bloggers’ methods. In fact, you can draw smooth chess pieces by superimposing multiple concentric circles with different radii and colors.

    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()

Insert image description here

2. Complete the chess move operation

The chessboard and chess pieces are ready. Now let’s implement the chess playing function and see how to place the chess pieces on the chess board.

五子棋的规则如下

1. Each side of the game holds chess pieces of one color. Start with an empty chessboard. Black starts first, then white, and alternates the moves. Only one move can be made each time.
2. The chess piece is placed on a blank spot on the chessboard. After the chess piece is placed, it may not move to other points, or be removed from the chessboard or picked up and placed elsewhere.
3. The side that connects five consecutive chess pieces of the same color first in a line wins.

People can use their eyes to judge which position can be played and when to win or lose, but how can a computer judge these things? Computing does not have a smart brain like humans. If you want a computer to make these judgments, you must convert these operations into data that the computer can understand.

How to let the computer know the situation of the chessboard? We use a two-dimensional array to simulate the chessboard. Each position on the chessboard has three states (no stones, black stones, white stones). Then we use (0, 1, 2) to represent these three situations. Use wb to represent the current chess piece. If the position is 0, update the value of the position and the value of wb, and then call the painting function to update the window.

    #存储棋盘状态
    alist  = np.zeros((19, 19))
    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
               z = False
               if alist[x][y] == 0:
               #这步相当于black(x,y)或者是white(x,y)取决于wb
                   eval(wb + "({},{})".format(x, y))

3.Judge winning or losing

How to judge whether you have won? We play chess pieces through the left screen of the mouse. Pygame also provides us with a function to obtain the mouse coordinates. After each mouse click, the check() operation is performed
to check whether it is in the four directions. If there are consecutive pieces, first find the first piece in that direction and then count the number of the same color backwards to determine the winner or loser.


def check(x,y):
        xx = x
        yy = y
        while True:
            #从最上边的棋子开始检查,记录颜色相同得棋子数量

            #先找到最同一条线上最上边的同色棋子
            if xx == 0:
                break
            elif alist[xx][yy] != alist[x][y]:
                xx += 1
                break
            else:
                xx -= 1
        num = 0
        while True:
            if xx == 18:
                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:
                break
            elif alist[xx][yy] != alist[x][y]:
                yy += 1
                break
            else:
                yy -= 1
        num = 0
        while True:
            if yy == 18:
                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:
                break
            elif yy == 0:
                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:
                break
            elif yy == 18:
                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:
                break
            elif yy == 18:
                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:
                break
            elif yy == 0:
                break
            elif alist[xx][yy] != alist[x][y]:
                break
            else:
                xx += 1
                yy -= 1
                num += 1
        if num >= 5:
            pygame.font.init()
            win(wb1)
     


def win(wb1):
    font = pygame.font.Font(None, 36)
    text = font.render("{}赢了".format(wb1), True, (255, 255, 255))
    screen.blit(text, ((665 - 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:
                do()

After completing these steps, the basic rules of backgammon have been implemented. After typing dozens of lines of code, I can finally get some feedback.
The following is the complete code of the junior version


import random
import sys
import pygame

import numpy as np

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:
                    eval(wb + "({},{})".format(x, y))
                    if wb == "black":
                        alist[x][y] = 1
                        wb1 = "black"
                        wb = "white"
                    elif wb == "white":
                        alist[x][y] = 2
                        wb1 = "white"
                        wb = "black"
                    check(x, y, wb1)
def check(x, y, wb1):
    xx = x
    yy = y
    while True:
        # 从最上边的棋子开始检查,记录颜色相同得棋子数量
        # 先找到最同一条线上最上边的同色棋子
        if xx == 0:
            break
        elif alist[xx][yy] != alist[x][y]:
            xx += 1
            break
        else:
            xx -= 1
    num = 0
    while True:
        if xx == 18:
            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:
            break
        elif alist[xx][yy] != alist[x][y]:
            yy += 1
            break
        else:
            yy -= 1
    num = 0
    while True:
        if yy == 18:
            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:
            break
        elif yy == 0:
            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:
            break
        elif yy == 18:
            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:
            break
        elif yy == 18:
            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:
            break
        elif yy == 0:
            break
        elif alist[xx][yy] != alist[x][y]:
            break
        else:
            xx += 1
            yy -= 1
            num += 1
    if num >= 5:
        pygame.font.init()
        win(wb1)


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

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

    pygame.display.flip()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                init()
                do("black")


if __name__ == "__main__":
    init()
    do('black')

4. Realize human-computer chess game

Now the basic functions of backgammon have been realized, but this kind of chess game full of strategies and games, guessing and responding to the opponent's possible layout, and having fierce intellectual duels with each other are the most fun parts of the game. Playing alone It’s too boring. It would be great if computers could think like people. Just like the “Alpha Dog” that has been particularly popular in recent years, I am looking forward to being defeated by my own program. So how to realize human-machine game?

With the rapid development of artificial intelligence, it has been widely used in many fields, including game artificial intelligence. Game artificial intelligence is divided into two major categories,
one is called deterministic artificial intelligence, and the other is called non-deterministic artificial intelligence.
Deterministic artificial intelligence refers to computers making judgments and decisions according to certain rules. Nondeterministic artificial intelligence refers to computers learning new rules based on existing rules, such as neural networks, genetic algorithms, decision trees, and probabilistic methods.
Because the rules of backgammon are certain, we only need to let the computer remember the rules and make decisions and judgments according to the rules. In chess games, if each layout of chess pieces is regarded as a 状态, then the set of all possible positions in the game is called 状态空间, state space search is to find the most favorable situation among all situations according to certain rules, and use this to decide the next move. Since the rules of backgammon are simple and there are relatively few optimal solutions in different states, there is no need to use the space-consuming state space search method. Just let the computer remember all the optimal solutions.

4.1 List the optimal solutions

Thinking back on your own thinking process when playing chess, there are only a few basis for decision-making and judgment. After weighing, choose the most advantageous move. Imitating the human thinking process, we can tell the computer all the moves, and then sort these moves by level. Every time the computer makes a decision, it will search for elements in these move sets in order from high to low. There is no The optimal solution is found randomly.

In order for the computer to recognize the moves, we must first describe and store the various moves in the chess game. Here we use a cdata list to implement it. 0 represents the empty chess, 1 represents the black chess, 2 represents the white chess, and 3 represents the chess to be played. s position.


# 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]
]

4.2 Match the optimal solution

Now that the computer has mastered all kinds of moves and has the winning secrets in hand, how do you use the computer? Next we define three global variables to assist in the execution of the matching algorithm. Use ai_col to play chess position column number, ai_row to play chess position row number, max_level move level

  global ai_col, ai_row, max_level
    ai_col = -1
    ai_row = -1
    max_level = -1

Next we define the auto_match() function

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

The function requires 4 parameters: row and col are the positions of the chess pieces, level is the move level, dx, dy are the next step direction, row_sel, col_sel are used to store the position value of the chess pieces during the matching process, the chess pieces are according to dx, The direction of dy is matched once and backward.
If the chessboard layout and move list match successfully, True will be played. Otherwise, False will be returned.

4.3 Autonomous operation

After completing the matching operation, the computer has the ability to make judgments. Next, we will realize the autonomous operation of the computer. Define ai_play() below


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 i + 4 < 19 and j - 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

This function first resets the global variables max_level, ai_row, ai_col to -1, clears the impact of the last result, and then starts matching from the first position on the chessboard. max_level records the highest level, and any move with a lower level is not considered directly. , this can reduce unnecessary operations and speed up the program running speed. After the matching is completed, if the optimal solution is found, ai_row and ai_col will be updated. If not found, a position that meets the requirements will be randomly selected.

Complete code

At this point, all the programs have been written. Now run the game and play it to see who is better, you or the computer. If you are defeated, this will be the best feedback for the code you have been working on for a long time.


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}  won", 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")


if __name__ == "__main__":
    init()
    do('black')



Insert image description here

Reference material "Fun Learning Python Game Programming"

Guess you like

Origin blog.csdn.net/weixin_55939638/article/details/133175969