Python to realize the game of Gobang

Time:2019-12-2

The code in this article is based on Python 3.6 and pyGame 1.9.4.

Compared with several games I wrote before, gobang is much more difficult. If it’s people to people, then the computer just needs to judge whether it wins. If it’s a man-machine fight, you have to let the computer know how to get off.

Let’s start with a simple question.

Beginning

Chessboard

First of all, we must draw a chessboard. It’s not difficult to draw a 19 × 19 or 15 × 15 chessboard with pyGame. This has been used many times in the previous articles, so we won’t go into details.

Draw pieces

It needs to be said to draw chess pieces, because there is no suitable picture of chess pieces, so you only need to draw chess pieces yourself.
The circle we drew with pygame.draw.circle is as follows:

The zigzag shape is very obvious. Pygame.draw has the function aaline to draw anti zigzag lines, but there is no such function as aacircle to draw an anti zigzag circle.

We need pygame.gfxdraw here. Pygame.gfxdraw is only an experimental version at present, which means that the API may change or disappear in later versions of pyGame.

To draw antialiasing and fill shapes, first use the AA * version of the function, then the fill version. For example:


col = (255, 0, 0)
surf.fill((255, 255, 255))
pygame.gfxdraw.aacircle(surf, x, y, 30, col)
pygame.gfxdraw.filled_circle(surf, x, y, 30, col)

Let’s use this method to draw a piece on the board.

It can be seen that the effect has improved significantly.

Fallen son

To drop a piece, you need to judge the mouse event. When you click the left mouse button, you can get the position of the mouse click, and then calculate the position of the piece on the chessboard according to the position of the chessboard.

while True:
    for event in pygame.event.get():
      if event.type == QUIT:
        sys.exit()
      elif event.type == MOUSEBUTTONDOWN:
        pressed_array = pygame.mouse.get_pressed()
        If pressed? Array [0]:? Left click
          mouse_pos = pygame.mouse.get_pos()
          click_point = _get_clickpoint(mouse_pos)

Victory judgement

When a son falls, how to decide whether to win or not?

To be sure, when a certain child falls, if there is a five connection, then the fallen child must be on the five connection. Then this problem can be simplified. We don’t need a full scan. We just need to press the scan horizontally and vertically at the drop position to determine whether there are five connections.

We define a chessboard class, in which we instantiate a 19 × 19 two-dimensional array. The initial values are all 0, which means null, 1 for black, and 2 for white. This class provides a drop method to receive parameters drop side and drop coordinates. If the drop succeeds, the winner will be returned, otherwise none will be returned.

Chessman = namedtuple('Chessman', 'Name Value Color')
Point = namedtuple('Point', 'X Y')
 
Black_chessman = chessman ('sunspot ', 1, (45, 45, 45))
White_chess man = chess man ('white son ', 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)
 
  #Judge whether it can be settled
  def can_drop(self, point):
    return self._checkerboard[point.Y][point.X] == 0
 
  def drop(self, chessman, point):
    """
    Fallen son
    : param chessman: Black / white
    :param point:Fallen son位置
    : Return: if the child can win after falling, return to the winning party, otherwise return to 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} wins')
      return chessman
 
  #Decide if you win
  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

Here I have defined an offset. We need to calculate 4 lines in total. If any line appears 5 times in a row, we will win. The calculation method is actually the same, but the direction is different, so define an offset array, different offsets represent different directions, so you can use the loop to achieve, saving a lot of code.

Computer drop

This is the whole play. How to teach computer to play Gobang.
First of all, I use a relatively traditional way, not deep learning.

Gobang is to achieve five, so, at the beginning, my idea is: to save all lines in an array, when the longest line drop is selected. But there’s a problem that can’t be solved. How can computers recognize “three three”?

Later, I saw an article on the Internet, using the method of: traversing the empty space on the chessboard, calculating whether each position has its own child in eight directions, adding 10 points for one, and finally selecting the position with the highest score.

This is not very rigorous. The computer estimation level written out is very poor, but this idea is right. The goal of a settlement is to find the most worthy place. Then we simply make an evaluation of every place where a settlement can be made and choose the best solution.

Here we need to understand several basic chess forms of Gobang: five in a row, four in a row, four in a row, three in a row, three in a row, two in a row, and two in a row.

Even five

As the name suggests, five pieces of the same color are connected and win.

Live four

Four pieces of the same color are connected together, and there is no block from each other on the left and right sides. There are two pieces in five points.

Chong four

Four pieces of the same color are connected together, and one side is blocked by the other piece, or four pieces are not connected, and there is a gap in the middle. At this time, only one piece is connected for five points.

Live three, jump three

Live threeThree pieces of the same color are connected.

Jump alive three: live three separated by a space.

Sleep three

There are only two kinds of situations, one is blocked, the other is there are two spaces. (in fact, I only consider the first situation in the code. Even if there is a conflict, it is not a dangerous situation.)

Living two and sleeping two

Living two can form the two of living three; sleeping two can form the two of sleeping three. I will not put the picture here.

Scoring mechanism

Understanding these chess shapes, then according to our previous thinking, is how to score.

  • First of all, there must be no five in a row. If there are five in a row, there will be no five in a row as long as the game is still in progress. So, what’s the highest priority? Nature is living four.
  • Second is the other side’s “four”, the other side live four, you can’t defend the same lose, the other side rushed four, you have to defend.
  • Third, our live three or four, live three and four are actually one level, the other side must defend.
  • Third, the other side’s three or four.

And so on. We can sum up one rule:

  • We are superior to each other in the same chess form.
  • There are three levels of Chong four and Huo three and one level of sleep three and Huo two.
  • If there is a space in the middle, it must be a little lower than the one without space, but it will not be degraded.

That’s the basic logic. I can’t write this piece of code well. I’ve written more than 100 lines of the whole judgment, so I won’t post the code. You can directly read the source code.

In the code, the player is the first in charge of black and the computer is the second in charge of white. Therefore, a good player can win the computer, but a small mistake is likely to be turned over by the computer.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.