[Deep Learning] Implementing a game-based AI, starting with wuziqi (1)

Source: Internet
Author: User

[Deep Learning] Implementing a game-based AI, starting with wuziqi (1)

I haven't written a blog for a long time. How long has it taken, about 8 years ??? I recently picked up writing again ...... Recently, I 've been tossing AI and writing an AI-related question to my team's friends.

 

After so many years of machine learning, from classification to clustering, from Naive Bayes to SVM, from neural networks to deep learning, various mysterious projects have been used for countless times, however, I feel that all kinds of things are too far away from our lives. Recently, with the release of AlphaGo Zero, deep learning has become increasingly popular, and our friends can't resist the inner agitation. We need to build a game AI. Okay, let's start with wuziqi, which has simple rules and is suitable for all ages.

 

Okay, so much nonsense. Let's go to the first lecture to implement a Wuzi game.

 

Little friend: I don't want to talk about deep learning. I want to talk about deep learning. How can I start to implement a five-game program ......

Me: to do good deeds, you must first sharpen your skills. You must implement the AI of wuziqi. You don't even have a chess game. You can use AI as a hammer!

Old Luo: What?

......

 

Wuziqi is divided into two types: banned and unbanned. We first implement a normal version of The unbanned version as an example, because this does not affect our implementation of an AI. It is worth noting that no banned player is required to win the game. After the competition and various studies, people gradually begin to find a way to limit the advantages of the black player. As a result, there was a rule for banned players, which stipulated that black games could not be connected to three, three, four, and four. However, as the results of the competition continue to be studied, it is found that, even if there is a ban on black games, it still cannot prevent the fact that black games will win the first game, such as pointing to the start of a month, a mountain month, or a cloud month, xiyue, Han Xing, etc., refer to the famous month, Pu Yue, Xingxing, Xia Yue, and lanyue in the first phase. As a result, the Japanese continued to put forward the idea of switching and playing, and later developed into three-hand exchange and five-hand two-playing rules in the international competition, to prevent black players from winning the start or winning the fifth hand. Therefore, the conclusion is that, in the absence of formal rules or no banned players, black games will win.

 

(1) logical implementation of playing chess

Python is used here, because the later Machine Learning Library is also Python, which is more convenient.

There is no doubt that the interface and logic should be separated and decoupled, and AI should be trained later. Separation is required. So let's first implement the logic of a five-game.

Let's first consider that Wuzi is a 15*15 checker. Each intersection (or grid) on the checker has three states: blank, black, and white. Therefore, we should first create a file consts. py

Make the following definition:

from enum import EnumN = 15class ChessboardState(Enum):    EMPTY = 0    BLACK = 1    WHITE = 2

 

 

The status of the board. We first use a 15*15 two-dimensional array chessMap to represent the status of the board, and create a class gobang. py

CurrentI, currentJ, and currentState indicate the coordinates and colors of the current game. Then define a get and set functions. The most basic framework is displayed. The Code is as follows:

from enum import Enumfrom consts import *class GoBang(object):    def __init__(self):        self.__chessMap = [[ChessboardState.EMPTY for j in range(N)] for i in range(N)]        self.__currentI = -1        self.__currentJ = -1        self.__currentState = ChessboardState.EMPTY    def get_chessMap(self):        return self.__chessMap    def get_chessboard_state(self, i, j):        return self.__chessMap[i][j]    def set_chessboard_state(self, i, j, state):        self.__chessMap[i][j] = state        self.__currentI = i        self.__currentJ = j        self.__currentState = state

 

 

In this way, the interface can call the get function to obtain the status of each grid to determine whether to draw the pawns and what kind of pawns to draw. Each time you play the game, on the corresponding grid, coordinates are used to set the status of the checker Map.

Therefore, the above logic is enough for the most basic display and playing games. What should we do next? After each game, we have to consider the status of the corresponding grid. Do we need to determine whether the current game has won or not. So we need to add two more functions to do this. The idea is to take the current position from the east, south, west, north, southeast, Southwest, northwest, Northeast eight directions, four axes, check whether more than five pawns of the same color appear consecutively. Assume that we are currently in the middle of the board, and the position to be determined is shown in the meter shape.

Def have_five (self, current_ I, current_j): # Count vertical left oblique right oblique hcount = 1 temp = ChessboardState. EMPTY # H-left for j in range (current_j-1,-1,-1): # transverse to left from (current_j-1) to 0 temp = self. _ chessMap [current_ I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break hcount = hcount + 1
# H-right for j in range (current_j + 1, N): # from (current_j + 1) to N temp = self. _ chessMap [current_ I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break hcount = hcount + 1
# H-result if hcount> = 5: return True

 

 

Similarly, you can see the vertical axis, the left oblique, and the Right oblique. The have_five function becomes like this:

Def have_five (self, current_ I, current_j): # Count the vertical and vertical directions, the left oblique, and the Right oblique hcount = 1 vcount = 1 lbhcount = 1 rbhcount = 1 temp = ChessboardState. EMPTY # H-left for j in range (current_j-1,-1,-1): # transverse to left from (current_j-1) to 0 temp = self. _ chessMap [current_ I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break hcount = hcount + 1 # H-right for j in range (current_j + 1, N): # transverse to right from (current_j + 1) to N temp = self. _ chessMap [current_ I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break hcount = hcount + 1 # H-result if hcount> = 5: return True
# V-for I in range (current_ I-1,-1,-1): # from (current_ I-1) to 0 temp = self. _ chessMap [I] [current_j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break vcount = vcount + 1 # V-for I in range (current_ I + 1, N): # from (current_ I + 1) to N temp = self. _ chessMap [I] [current_j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break vcount = vcount + 1 # V-result if vcount> = 5: return True
# LB-for I, j in zip (range (current_ I-1,-1,-1), range (current_j-1,-1,-1 )): temp = self. _ chessMap [I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break lbhcount = lbhcount + 1 # LB-bottom for I, j in zip (range (current_ I + 1, N), range (current_j + 1, N )): temp = self. _ chessMap [I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break lbhcount = lbhcount + 1 # LB-result if lbhcount> = 5: return True
# RB-for I, j in zip (range (current_ I-1,-1,-1), range (current_j + 1, N): temp = self. _ chessMap [I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break rbhcount = rbhcount + 1 # RB-lower for I, j in zip (range (current_ I + 1, N), range (current_j-1,-1, -1): temp = self. _ chessMap [I] [j] if temp = ChessboardState. EMPTY or temp! = Self. _ currentState: break rbhcount = rbhcount + 1 # LB-result if rbhcount> = 5: return True

 

 

In this case, is it finished? All the logic of wuziqi is implemented ~

NO, don't be so happy too early. I want to say, I'm so disgusting. The code above is ugly. Let's take a look at it. I 've repeatedly written so many for, so many if, so many repeated code blocks, let me vomit ......

Okay, think about how to change it. There are at least four axes, which are repeated, right? Then, each axis is counted from both positive and negative directions. Finally, the two directions are added, it is also repeated, right.

So can we just write the code in one direction, tune it twice, and then tune it four times for four axes, 2*4 = 8, and try it with 8 lines of code in total.

Because of the existence of the 45 ° and 135 ° oblique axes, positive and negative axes should be controlled from the x and y axes respectively in the direction, so we can write a function first, statistics by direction:

Xdirection = 0, ydirection = 1 indicates the positive number from the Y axis;

Xdirection = 0, ydirection =-1 indicates the negative number from the Y axis;

Xdirection = 1, ydirection = 1 indicates the positive number from the 45 ° oblique axis;

......

I did not list them one by one, and added the boundary condition judgment, so I had the following functions:

Def count_on_direction (self, I, j, xdirection, ydirection, color): count = 0 for step in range (1, 5): # except the current position, look at Step 4 in the corresponding direction. if xdirection! = 0 and (j + xdirection * step <0 or j + xdirection * step> = N): break if ydirection! = 0 and (I + ydirection * step <0 or I + ydirection * step> = N): break if self. _ chessMap [I + ydirection * step] [j + xdirection * step] = color: count + = 1 else: break return count

 

 

As a result, have_five looks a little longer and can become like this:

Def have_five (self, I, j, color): # Count values in four directions: horizontal, vertical, left, and right. hcount = 1 vcount = 1 lbhcount = 1 rbhcount = 1 hcount + = self. count_on_direction (I, j,-1, 0, color) hcount + = self. count_on_direction (I, j, 1, 0, color) if hcount> = 5: return True vcount + = self. count_on_direction (I, j, 0,-1, color) vcount + = self. count_on_direction (I, j, 0, 1, color) if vcount> = 5: return True lbhcount + = self. count_on_direction (I, j,-1, 1, color) lbhcount + = self. count_on_direction (I, j, 1,-1, color) if lbhcount> = 5: return True rbhcount + = self. count_on_direction (I, j,-1,-1, color) rbhcount + = self. count_on_direction (I, j, 1, 1, color) if rbhcount> = 5: return True

 

 

I still think the code is ugly. I am not a Virgo, but this function is really ugly. Can you make it more handsome? Of course, yes, the four repeated blocks are then merged into a function, which is called four times in a loop. Is it okay? Well, just do it, So have_five is a little more beautiful:

Def have_five (self, I, j, color): # Count directions = [[(-1, 0), (1, 0)], \ [(0,-1), (0, 1)], \ [(-1, 1), (1,-1)], \ [(-1, -1), (1, 1)] for axis in ctions: axis_count = 1 for (xdirection, ydirection) in axis: axis_count + = self. count_on_direction (I, j, xdirection, ydirection, color) if axis_count> = 5: return True return False

 

 

Well, I feel much better. Now I can determine whether there are five chess pieces of the same color in logic. I will add a function to return results to the interface layer. The logic part of the code is almost the same:

    def get_chess_result(self):        if self.have_five(self.__currentI, self.__currentJ, self.__currentState):            return self.__currentState        else:            return ChessboardState.EMPTY

 

 

As a result, the logic code of wuziqi is finished. The complete code gobang. py is as follows:

# Coding: utf-8from enum import Enumfrom consts import * class GoBang (object): def _ init _ (self): self. _ chessMap = [[ChessboardState. EMPTY for j in range (N)] for I in range (N)] self. _ currentI =-1 self. _ currentJ =-1 self. _ currentState = ChessboardState. EMPTY def get_chessMap (self): return self. _ chessMap def get_chessboard_state (self, I, j): return self. _ chessMap [I] [j] def set_chessboard_state (Self, I, j, state): self. _ chessMap [I] [j] = state self. _ currentI = I self. _ currentJ = j self. _ currentState = state def get_chess_result (self): if self. have_five (self. _ currentI, self. _ currentJ, self. _ currentState): return self. _ currentState else: return ChessboardState. EMPTY def count_on_direction (self, I, j, xdirection, ydirection, color): count = 0 for step in range (1, 5): # except for the current position, look at 4 in the corresponding direction Step if xdirection! = 0 and (j + xdirection * step <0 or j + xdirection * step> = N): break if ydirection! = 0 and (I + ydirection * step <0 or I + ydirection * step> = N): break if self. _ chessMap [I + ydirection * step] [j + xdirection * step] = color: count + = 1 else: break return count def have_five (self, I, j, color): # counting in four directions: horizontal, vertical, left, right, ctions = [[(-1, 0), (1, 0)], \ [(0,-1 ), (0, 1)], \ [(-1, 1), (1,-1)], \ [(-1,-1), (1, 1)] for axis in directions: axis_count = 1 for (xdirection, ydirection) in axis: axis_count + = self. count_on_direction (I, j, xdirection, ydirection, color) if axis_count> = 5: return True return False

 

Little friend: Eldest Brother. After a long time, why is there less than 60 lines of code?

Me: there are not many codes, so implementation will work ......

 

Add a render for it tomorrow, and the front-end interface will be ready. It is a simple and complete game. Do not worry about AI.

Okay, that's it...

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.