I am participating in the nuggets Community game creative submission Contest. For details, please see: Game Creative Submission Contest

Gobang as a way of entertainment, I believe we have played, and many people should be good at this way. Do we programmers ever think about how it’s implemented? How to achieve man-machine? How to match and play online?

I spent a few days, and finally completed the first version of gobang small game, mainly contains the following small functions:

  • Log in to register
  • The man-machine against
  • Online play
  • Integral module

Online experience address: gobang battle

Open source code address: I stubborn but you: gobang

An overview,

This article focuses on the gameplay of this backgammon, the implementation of the use of technology, as well as the shortcomings of the current game and improvement plan.

At present, as a preliminary version, it can complete the functions I expected, and the overall amount of code of the project is small and the complexity is low. It is more suitable for students who want to learn related code technology to refer to, and it can also help me put forward a better improvement plan. Welcome to play, reference, comment.

It needs to be explained that my front-end is very general, the current interface is relatively simple, only to achieve basic functions, need to be gradually optimized in the future.

Ii. Introduction of gameplay

The game has four small features mentioned in the beginning, and the following is a step-by-step look at each feature with illustrations.

2.1 the home page

To visit gobang battle, go directly to the home page:

Modes can be selected:

  • The man-machine model
  • mode

Check out the leaderboard:

  • List of man-machine
  • List of ladder

2.2 Login and Registration

The login registration function here is mainly for recording the score of players. Therefore, the account can be directly used in Chinese, the account is a nickname, intuitive embodiment.

2.2.1 login

When we click man-machine mode or play mode, a prompt box will pop up, prompting us to log in:

2.2.2 registered

For the first time, you need to register by clicking the registration button in the lower left corner of the picture above:

We input our account and password, click Register, and log in the game directly.

2.3 Man-machine Battle

2.3.1 First hand, second hand

Complete the previous login and registration, click the man-machine battle button on the home page again, you can enter the game interface, the first step you need to choose the first or second hand:

2.3.2 timeout

We click first here to start the game. Note that you have 30 seconds to think, if you exceed the time, you will lose:

The computer will take a certain amount of time to think, depending on the performance of the current machine, basically no more than 4 to 5s, the computer will not timeout:

2.3.3 Winning and losing tips

When you win or lose this game, you will be given the following prompt:

  • Return to the home page to exit the current mode;
  • One more game, the game starts again, and the first or last hand is chosen again.

If you win, you get 100 points, and 10 points will be deducted if you lose.

In addition, the interface provides the button to return to the home page and restart the game, which does not deduct points.

2.4 Online Battle

Match against 2.4.1

Click the battle mode button, you will directly enter the matching interface:

During this process, click Cancel match to exit the mode and return to the home page.

When another player enters the matching process, the two players will make a match and start the game after success:

2.4.2 timeout

After entering the interface, you will see whether the current round is black or white, providing a countdown prompt

If not, the team will lose and 10 points will be deducted

Accordingly,The other party to winTo obtain100 points:

2.4.3 throw in the towel

Provide a defeat button:

10 points will be deducted for losing:

Accordingly, the other side gets 100 points:

2.4.4 Tips for winning and losing

In the current mode, regardless of whether you win or lose, click the “OK” prompt will return to the home page. If you want to continue, click the “Match” mode again to match.

2.5 Integration Module

This module is used to record the score of the player to increase the fun of the game.

The home page can be viewed with two hyperlinks:

2.5.1 man-machine list

Select man-machine list, the TOP20 list will pop up from the left:

2.5.2 ladder list

If you select the ladder, the TOP20 will pop up from the right:

Three, the main technology realization

The following mainly according to the functional module to talk about technology.

3.1 Project Architecture

The overall architecture of the project is very simple, with only three layers, all of which are single services:

  • Application layer: Deploy vue projects through Nginx
  • Service layer: springboot service
  • Data layer: mysql and Redis

3.2 Winning and losing judgment

As we all know, the board of backgammon is a 15 by 15 square, and as long as one side has five pieces in a row, the winner is counted. So how do you tell if there are five pieces of the same color in the current game?

Here I use a two-dimensional array in the front to simulate the whole checkerboard. The abscissa and ordinate of the checkerboard can fit perfectly into a two-dimensional array.

Suppose we have a two-dimensional array of size 15: ARr [15][15]

Then it would correspond to the checkerboard as follows:

The two-dimensional array, as shown above, represents each position on the board, and so on, up to ARR [15][15].

Since the pieces are primarily two colors, black and white, I’ve defined that when I assume that a spot has landed on the board, I’ll set the array at this point to 1, and again, the white spot can be set to 2; After doing this, all the points on the board are recorded by me in a two-dimensional array.

So how do you judge a winner?

Chessboard has four main directions: horizontal, vertical, oblique, oblique.

Let’s convert the array values in each direction to a string using the join method to see if there are consecutive strings like 11111,22222 on the board.

Horizontal and vertical traversal of the two-dimensional array is very simple, the difficulty lies in the oblique, oblique traversal, this paper does not do a detailed introduction, the relevant algorithm is on the force link.

So far, each time we go to determine whether the number of times the group has a matching string to determine whether to win or lose.

3.3 Extending the design concept based on gobang

True renju masters, both for the placement of the board has his own ideas, then fall where and how to fall, is to have cultured, anyone interested in this address, see the very detailed introduction: game.onegreen.net/wzq/HTML/14…

The above article highlights several different chess positions, as follows:

  • Even the five
  • Live four
  • At four
  • three
  • Sleep three
  • Live two
  • Sleep two

After reading the above content, it seems that the degree of danger is gradually reduced from top to bottom, so I make an enumeration of points according to different chess positions, which can also be called the score model:

LIAN_5("LIAN_5".1000000),
HUO_4("HUO_4".30000),
CHONG_4("CHONG_4".25000),
HUO_3("HUO_3".6000),
HUO_2("HUO_2".1000),
MIAN_3("MIAN_3".500),
MIAN_2("MIAN_2".300),
ONE_CHESS("ONE_CHESS".10);
Copy the code

Now that we have the concept of score, I’m sure you can think of the next move. I’m going to score the players and the computer for the current game.

3.3 implementation scheme of man-machine Mode

According to the above description, my man-machine mode is based on such a set of score model to play chess automatically. The whole man-machine versus mode, is the most difficult project, to achieve automatic computer defense and attack.

3.3.1 Ideological design

So how does the computer know where the best place is?

The easiest way, when you don’t know if it’s appropriate, is to give it a try?

Difficult our way is the same, let the computer to try, under where will get the highest score!! There must be the following process:

In the picture above, when it comes to the most difficult part, how do you weigh the player score versus the computer score?

My idea is to be defense-oriented, to be based on player scoring.

Imagine that the computer simulates playing chess at each point of the board. At this time, different chess positions are formed, and there must be different total scores. Finally, the computer will get the score list of each point. The computer itself, on the other hand, wants to score higher.

You can’t just take the lowest score, you’re going to make the computer just play defense. You can’t just let the computer get its highest score, it just attacks.

So in the end, I settled on the following solution:

What does the difference list mean?

Each score in this list is the difference between the computer’s score and the player’s score, so can I assume that the maximum value of this list is the most favorable point for the computer among all the points that the player scored.

In plain English, the computer uses the player’s score as a basis to find points that are not good for the player, but are also best for the computer.

What if the difference list has the same value?

If there are two identical points, how do you decide which is the best?

I’m going to use the same point here to simulate the next step of the user, and I’m going to take the point with the highest score as the optimal point under the computer.

3.3.2 Scoring design

After the previous thought design, it seems to work, so let’s design how to calculate score?

3.3.2.1 Refinement of chess

First of all, I refined the scoring model mentioned above. Imagine a scenario in which a match is made according to the form of a string. There might be 21111, or 11112, which is blocked by other colors. What if it’s on the border? I’m going to use 31111; And then there are gaps in between, and then there are blocks, or there are boundaries.

Thus, the following possible moves are formed, which are partial but not complete:

3.3.2.2 Score by direction

As with the winning method introduced earlier, we still need to traverse the entire board data, divided into: horizontal, vertical, oblique, and inverse. Abstract an abstract class for the calculation of scores in four different directions:

/** * Abstract class **@author weirx
 * @date 2022/04/01 18:41
 **/
public abstract class AbstractChessDirectionAnalysis {

    public abstract Map<String, Object> analysis(Integer[][] integers, boolean flag);

    public Map<String, Object> analysis(ChessScoreEnum chessScoreEnum, String join, boolean flag) {

        join = this.handleBorder(join);
        Map<String, Object> map = new HashMap<>();

        if (flag) {
            List<PlayerChessScoreChildEnum> playerChessScoreChildEnums = PlayerChessScoreChildEnum.getByChessScoreEnum(chessScoreEnum);
            for (PlayerChessScoreChildEnum c : playerChessScoreChildEnums) {
                String type = c.getType();
                if (join.contains(type)) {
                    map.put("score", chessScoreEnum.getScore());
                    map.put("type", chessScoreEnum.getCode());
                    map.put("str", c.getType()); }}}else {
            List<AIChessScoreChildEnum> aiChessScoreChildEnums = AIChessScoreChildEnum.getByChessScoreEnum(chessScoreEnum);
            for (AIChessScoreChildEnum c : aiChessScoreChildEnums) {
                String type = c.getType();
                if (join.contains(type)) {
                    // If the player hits 4, the score is given to a situation greater than the possible 4
                    map.put("score", chessScoreEnum.getCode().equals(ChessScoreEnum.CHONG_4) ? chessScoreEnum.getScore() * 2 : chessScoreEnum.getScore());
                    map.put("type", chessScoreEnum.getCode());
                    map.put("str", c.getType()); }}}return map;
    }

    public String handleBorder(String join) {
        if (join.indexOf("1") = =0) {
            join = "3" + join;
        }
        if (join.lastIndexOf("1") == join.length() - 1) {
            join = join + "3";
        }
        returnjoin; }}Copy the code

This abstract class contains the ability to match general moves and encapsulate scores. There is an if-ESle judgment to distinguish between the player score and the computer score, one of which is 1 and the other is 2.

Another point to note: if the player has a strike four and the computer happens to have a live four in the next step, the score must be higher than the computer’s live four score, otherwise the computer will play its own live four and ignore the player’s strike four, causing the game to lose.

Int (Integer[][] integers, Boolean flag) and andleBorder(String Join)

Four directions of analysis, respectively to inherit this abstract class, the following horizontal analysis as an example. Implementation analysis method, this method is mainly used to traverse the horizontal chess game, the core is also abstract class method call, with the string of the current row to match the string defined in the chess enumeration, if the match, then the score.

/** * Horizontal analysis of chess games **@author weirx
 * @date2022/04/01 18:44 * * /
@Slf4j
@Service
public class ChessRowAnalysisService extends AbstractChessDirectionAnalysis {
    @Override
    public Map<String, Object> analysis(Integer[][] integers, boolean flag) {

        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < 15; i++) {
            Integer[][] col = new Integer[15] [15];
            for (int j = 0; j < 15; j++) {
                col[i][j] = integers[j][i];
            }
            Map<String, Object> row = this.analysis(col, i,flag);
            if(! row.isEmpty()) { map.put("ROW_"+ i, row); }}return map;
    }

    public Map<String, Object> analysis(Integer[][] integers, int index, boolean flag) {
        Map<String, Object> map = new HashMap<>();
        String join = StringUtils.join(integers[index], "");
        for (ChessScoreEnum chessScoreEnum : ChessScoreEnum.values()) {
            Map<String, Object> row = this.analysis(chessScoreEnum, join,flag);
            if(! row.isEmpty()){ map.put("ROW_"+chessScoreEnum.getCode(), row); }}returnmap; }}Copy the code

The above difficulty is the split and encapsulation of the format points. In particular, oblique, oblique analysis, is actually completely different process, need to focus on, limited to space, need to see the source code.

Each direction analysis will return a Map object, the next thing we need to do is to break it out and sum it up, relatively simple, not introduced here.

So much for the analysis of man-machine versus machine.

3.4 [Battle mode] implementation scheme

Compared with online battle, its logical analysis of algorithms and so on, is much weaker, the focus of online is how to realize the communication and data synchronization of two players.

The implementation scheme adopted in this paper is based on webSokcet.

3.4.1 Match players

Matching players was one of the first challenges I encountered in implementing this feature. How do YOU store users that are matching? How do you match players in a match? After the matching, delete the previously saved information about the matched user

I did it in a relatively simple way, as shown below:

Process analysis:

  • Players initiate matches and their information is stored in Redis

  • The scheduled task continuously pulls the key every five seconds

  • Determine whether at least two people are matching:

    • If no, continue the loop
    • If yes, delete the matching information and promote the WebSocket
  • The Websocket pushes successful matching messages based on the matching information

  • Two players establish a connection

3.4.2 Playing Online Chess

Each time both parties drop a target on their own client, they will push the message (mainly the information of the current location of the target and the user name of the opponent) to the server through websocket. The server will push topic according to the user name of the opponent, and the opponent client will get the message through listening topic (Redis issue and subscription). Push to the page through websocket, and finally complete the client chess rendering, to achieve the purpose of synchronization.

Here Redis is mainly to solve the problem of distributed session. Although this project is stand-alone, redis is used to transfer one step out of habit.

Four, deficiencies and improvement plan

  • The man-machine against

Inadequacy: at present man-machine war, to the complicated and changeable chess bureau, still can appear the score calculation is not accurate, bring about the computer to go wrong. In particular, pieces are blocked, involving boundaries, in the case of adding space, not covering all possibilities.

Artificial generalization is laborious, because there are so many kinds.

Improvements: Subsequent improvements mainly focus on AI, allowing computers to learn by themselves. Every failure is automatically recorded and persisted, which should cover the vast majority of possibilities after long-term training.

  • Online play

Disadvantages: at present, scheduled tasks are polling and matching players. Small concurrent projects have no problem, while large concurrent projects may have low distribution efficiency. In distributed deployment, idempotent processing is also required for scheduled tasks.

Improvements: The bottom layer will be changed to Netty later.

  • Page optimization

Shortcomings: As a back-end programmer, the current page writing is simple, and the code format is chaotic, not many good use of the essence of VUE, such as routing, so the page is not smooth, waiting for reconstruction.

Improvements: Refactoring the code style to separate components and pages by function. Add detail and color to the game.

Five, the summary

The whole game, using the usual spare time, probably used about 10 days, efficiency is not high, also encountered problems in the middle, stuck for a long time. In particular, the design of man-machine module took a lot of time, and several schemes were overturned in the process, which was finally completed in a stumbling way. There are still many problems, and I will optimize them later.

Summarize some shortcomings:

  • Not good at math
  • Algorithm in general
  • Front-end coding capability needs to be improved
  • Encountered problems, to learn to jump out of the cycle, sorting out ideas after analysis
  • Age problem, thinking is really not thorough

In fact, the most important point lies in the need to think before starting, no matter what development, or to do the design first, verify the feasibility, so as to avoid repeated.