Gobang based on human experience

Posted by afterburner on Fri, 11 Feb 2022 16:06:00 +0100

Gobang based on human experience (2)

Based on the previously established rules, a primary Gobang computer is established. We use the rules to score each position on the chessboard, and then find the position with the highest score to choose; Despite a good start, this still cannot simulate a "visual" data for it.

Before proceeding to the next step, I have to provide an event that contains an experience that is all in the current state of Gobang.

I provided these in the previous post:

  1. Advantage calculation of wall [- 5000]
  2. Whether there are enemies (5 squares) in the current position in one row is calculated [- 1]
  3. Advantage calculation with my sub temporary lattice (5 lattice) [+ 2]
  4. The current position is associated with my child (i.e. temporary grid 1) [+ 3]
  5. If there is sub block on the other side and it can be divided into three sub [+ 3], otherwise [+ 5];
  6. If there is sub block on the other side and it can be divided into 4 sub [+ 13], otherwise [+ 20];
  7. Cheng Wuzi [+ 10000]

At that time, I didn't deal with "there is a blockage on the other side". That means I only deal with the situation of 3 / 4 children and ignore the judgment of being blocked. However, this effect is really caused by the entry potential of Gobang, which is easy to ignore these. After making the program and analyzing it, these functions are added.

Therefore, before the project, we should try to contact with the things related to the project, so as to fully realize the behavior details in the project as much as possible.

Well, then continue from here. The next question is how to quickly add this implementation.

void nodefraction(strplay**, int, int, short);//Calculate the advantage. short is the number of times to guess the other party's next steps

This is my function of computing advantage. There are two members in strplay structure (or class, but constructed with struct instead of class), which record player advantage score and computer advantage score respectively.

Internal implementation related to the current topic:

//Here [CSDN] is slightly changed and optimized from code reading
/*
static bool negative(strplay**node, int x, int y, int a, int b, int need, bool mode, bool how);
//Check whether the other end of the assembly is blocked. need is the direction to see: 1 is right left; 3 is up-down; 5 is upper right lower left; 7 is left upper right lower return true, indicating that this position is blocked. If it is blocked, it will be marked (see Step 5 only); If mode is false, blocking is not recorded; If how is true, it is the player
*/

				//right
				linebool = false;//[bool] whether the tag is blocked. true is yes and false is No
				int CommputerPtr = UserPtr = 0;//[int]UserPtr is the sub count of players; CommputerPtr is the counter of the enemy
				CommputerUint = UserUint = false;//[true / false] Yes / no
				for (int i = 1, linea = a; linea < x && i < 5; ++i)
				{
					linea = a + i;//[int]
					if (node[linea][b].mode == 0) //There are no children here
						break;//Exit this and look at the for on the right. Next, look at the left
					else 
					{
						if (node[linea][b].mode == 1)//This is the player's child
						{
							if (UserPtr < 4 && !CommputerUint)
								++UserPtr;
							else
								break;

							UserUint = true;
						}
						else //Here is the computer subsystem
						{
							if (CommputerPtr < 4 && !UserUint)
								++CommputerPtr;
							else
								break;

							CommputerUint = true;
						}
					}
				}

				//left
				CommputerUint = UserUint = false;//Mark whether there has been a computer / player, true yes, false No
				for (int i = 1, linea = a; linea >= 0 && i < 5; ++i)
				{
					linea = a - i;
					if (linea < 0)
						break;
					else if (node[linea][b].mode == 0)//There are no children here
						break;//Exit this, look at the for on the left, and then go in other directions, but the next code is not given in [CSDN]
					else 
					{
						if (node[linea][b].mode == 1)//This is the player's child
						{
							if (UserPtr < 4 && !CommputerUint)
								++UserPtr;
							else
								break;

							UserUint = true;
						}
						else//Here is the computer subsystem
						{
							if (CommputerPtr < 4 && !UserUint)
								++CommputerPtr;
							else
								break;

							CommputerUint = true;
						}

					}
				}

				linebool = negative(node, x, y, a, b, 1, true, true);//Player records blocked position
					
				//Bonus points for players
				switch (UserPtr) {//The child in the current position is the player's child
				case 2://Cheng 3 Zi
					if (linebool)//Check whether it will be blocked. If yes, it is true
						node[a][b].pinguser += 3;
					else
						node[a][b].pinguser += 7;
					break;
				case 3://Cheng 4 Zi
					if (linebool)
						node[a][b].pinguser += 11;
					else
						node[a][b].pinguser += 500;
					break;
				case 4:node[a][b].pinguser += 10000;//5 sub + 10000
					break;
				}

				linebool = false;
				linebool = negative(node, x, y, a, b, 1, true, false);//Record where the computer is blocked

				//Extra points for the number of computers
				switch (CommputerPtr) {//The child in the current position is the computer child
				case 2://Cheng 3 Zi
					if (linebool)
						node[a][b].pingcommputer += 3;//3 sub + 3
					else
						node[a][b].pingcommputer += 7;
					break;
				case 3://Cheng 4 Zi
					if (linebool)
						node[a][b].pingcommputer += 11;//4 sub + 11
					else
						node[a][b].pingcommputer += 500;
					break;
				case 4:node[a][b].pingcommputer += 10000;//5 sub + 10000
					break;
				}

I removed the parts irrelevant to this topic and changed some. Later, I found that some optimized places were also optimized, but I didn't move the source code [too lazy to move].

This is a right left judgment. Each judgment cycle is carried out for each position on the chessboard. The function added here is negative: it determines whether all the two ends of the sub are empty. If so, it returns false; otherwise, it returns true to indicate that they are blocked. If they are blocked, it records them to the blocked position of the player / computer.

Based on the above negative function implementation, some problems will be found:

  1. The method of checking the empty space at both ends to judge whether it is blocked is not always effective. For example, a child becomes three, but its two ends + 1 are enemy children or walls;
  2. There is a potential irreversible risk of recording the blocked position. Because the record is not necessarily deleted - if a function associated with this is added later, for example, if the user wants to customize the chessboard and pieces during the game, the information of the blocked position of the player / computer still exists, and because the current goal is to reach the existing goal in the most convenient way, the user will finish what he wants to do, The computer always ignores some chess pieces. The solution to this problem is to record it in the software development document.

Now the calculation advantage score function has completed the required change. Despite this, the man-machine still can't "correctly" play chess. Some obvious positions are ignored by the man-machine. Therefore, in the eyes of users, they can't understand these behaviors. They can only point out various errors of the man-machine to express that the man-machine is not intelligent. (fortunately, I didn't promote it at this time)

It can be seen that the simple Digitization Based on Nasheng equilibrium is too clumsy, and some "visual" rules should be added to correct it.

Topics: C++