C++ language design and implementation of gobang

  • 2020-06-07 04:59:22
  • OfStack

This paper shares the design idea and implementation of C++5 for your reference. The specific content is as follows

Algorithm idea:

After the end of the C++ learning, I will prepare myself to compile 1 simple exercise program. At present, the preliminary idea is to prepare a personal computer game simple 5 sub chess software. The following is the process of personal design thinking.

First, analyze and design the problem. The planned function is to select man-machine or two-man match at the beginning, and then the match will start. Initializes the board at the end of the game and asks whether to continue or exit. Can be added in the follow-up, repentance and other functions. In the whole process, two objects, chess pieces and chessboard, were involved, and the AI object in the man-machine game was added, that is, three objects were involved.

Design of the checkerboard class.

Data storage: A 15*15 grid structure for 5 child chess boards, namely 1 total 225 nodes, each node has 1 vertical and 1 horizontal coordinates, and each node has 3 states, black, white or empty. Consider using a 2-dimensional array for storage. Each node has three states, suitable for enumeration (enum) type.
1. The checkerboard object shall be responsible for updating the status of the checkerboard in real time and displaying it externally, so it needs to receive the input of the checkerboard object and need to output it at the same time. The checkerboard object does not need to send information to the checkerboard object, so the function of updating the checkerboard state in the checkerboard class can be designed to receive the checkerboard object as formal parameter. 2. At the same time, after each move, the checkerboard object should update the checkerboard information in time, that is, output the checkerboard state. 3. Moreover, before updating the output after each move, it is necessary to determine whether the chess moves conform to the rules and win or lose. If the rule decision is encapsulated as an object alone, it is inconvenient to call the checkerboard information. Therefore, the rule decision is designed as a member function of the checkerboard class, receiving two formal parameters, one is the current state of the checkerboard, and the other is the next step to be taken, namely, a checkerboard object.

Design pawn objects. The chessman object should contain two kinds of information. 1 is the color of the chess piece, 2 is the position coordinates of the chess piece to be moved, and retains the output interface.

Next, refine the rule decision function.

First of all, the rules of play are decided. After receiving the position information of the current chess piece, determine whether the position is out of bounds or empty, if not empty or out of bounds, then determine the violation, throw the exception, the superior call processing. And then make a decision to win or lose. In accordance with the order of 1, the adjacent elements at the current falling position are determined and counted. When more than 4 pieces of the same color are found on a line, the current player is judged to be the winner. It is also important to pay attention to whether the boundary is crossed. If they do not constitute a 5-star line, then enter a draw judgment. Judge the draw, traverse the board, and count the empty space. If the empty space is 0, the board is full, and judge it as a draw.

Next, design AI for chess. A function designed as a one-piece type that receives the current board state and the opponent's last play, returning the piece object type.

Game algorithm design.

First of all, hand decision: if the board is empty, then directly drop (8,8), the middle start. Then the defense decision: for the other side last play chess live chess detection, in horizontal, vertical, left slope, right slope four lines in turn on the detection. If 4 or live 3 is detected in any direction, the plugging operation can be carried out and all feasible plugging positions are given. If no 4 or 3 is detected, a 2 is counted and all possible plugging locations are given. Then, score all possible blocking positions and select the position with the highest score. If none of the above detection can find the defensive point, then turn to the offensive algorithm. Attack algorithm: enumeration, that is, the method of brute force cracking. Go through all the Spaces on the board and give a score for each one. Pick the highest score to drop. Live chess detection algorithm: given the reference pieces, in four directions are detected separately. Take the lateral detection as an example, set the coordinates of the chess pieces as (x,y), set the same-color counter count=1 (to calculate the number of same-color chess pieces), set the blockade statistics lock=0, set the determined direction statistics judge=0. For x-1, judge the node state. If the same color counter is added 1, continue to judge ES34en-2. If the color is different, then lock+1, judge+1, if judge=2, terminate the judgment, if judge < 2. Reverse judgment of x+1; If blank, judge+1, if judge=2, terminate judgment, if judge < 2. Reverse judgment. Finally, the number of blocked ports lock and isochromatic number count are obtained. If lock=0, count=3 or 2, the decision is live 3 or live 2. If lock=1 and count=4, the judgment is 4; if lock=1 and count=3, the judgment is half 3. But in this algorithm, there are some problems about the determination of whitespace. Zero for blank, plus for the same color, minus for different colors, and then when the following happens: -0++0-, -+++0-, is actually dead, and +0++0, +0++ -, is actually 3 or 4 halves alive. For this reason, it is necessary to carry out 1 step screening in the case of live 2 and half 3, that is, the blank end should ensure two consecutive blank. During live chess detection, if 3 or 4 halves are encountered, the detection is immediately terminated and the possible position of the drop is returned. If not, record 2 1/2 defensive positions and change direction for detection. Finally, an array of 1 chess piece is returned, containing all the suggested drop positions. If none, traverse the board, count all the blank positions, and return. Scoring algorithm of placement position: score each position in the return array of live chess detection, that is, take this point as its reference point to perform live chess detection. If there is count=5, directly return this placement position. You have live 3 or half 4, plus 20, you have live 2, plus 5, you have adjacent colors on the diagonal, plus 2, you have different colors, minus 2, you have the same color on both sides, plus 1, you have different colors, minus 1. The last sorting, take the highest score corresponding to the drop, return the drop.

Next comes the data structure and object design and the implementation of the main function call:

Class and its implementation


#define RENJU_H
#include <iostream>
#include <windows.h>
#include <string>
#define hor 7
#define ver 4
using namespace std;


// Used to record coordinates 
struct position
{
 int x;
 int y;
 position()
 {
 x = 0;
 y = 0;
 }
 position(int a,int b)
 {
 x = a;
 y = b;
 }
};


// Used to record chess pieces' colors and node states 
enum state
{
 blank=0,black=1,white=2


};


// Used to store game analysis information : Unplayed, foul, draw, black win, white win 
enum result
{
 go_on,error,draw,black_win,white_win
};


//  Set the cursor 
void setpos(COORD a) 
{
 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
 SetConsoleCursorPosition(out, a);
}


//  Set the cursor 
void setpos(int i, int j)
{
 COORD pos = { i, j };
 setpos(pos);
}


// A drawing function that prints the specified character at the specified coordinates 
inline void gps(int x,int y,char c)
{
 setpos(y,x);
 cout<<c;
}


// A drawing function that outputs an integer at specified coordinates 
inline void gps(int x,int y,int i)
{
 setpos(y,x);
 if(i>=10)
 cout<<i;
 else
 cout<<0<<i;
}


// A drawing function that outputs a string at specified coordinates 
inline void gps(int x,int y,string s)
{
 setpos(y,x);
 cout<<s;
}


// A drawing function used to print a checkerboard at a given coordinate 1 " 
void tab(int x,int y,state str)
{
 string s;
 switch (str)
 {
 case blank:
 s=" "; 
 break;
 case black:
 s=" black ";
 break;
 case white:
 s=" white ";
 break;
 default:
 break;
 }
 setpos(y,x);
 cout<<" ------ ";
 setpos(y,x+1);
 cout<<"|  |";
 setpos(y,x+2);
 cout<<"| "<<s<<" |";
 setpos(y,x+3);
 cout<<"|  |";
 setpos(y,x+4);
 cout<<" ------ ";
}


// Find the maximum 
int MAX(const int *a,int n)
{
 int max = a[0];
 for(int i =1; i < n ;i++)
 {
 if(a[i] > max)
 max = a[i];
 }
 return max;
}


// Check whether the victory conditions are met 


// Pawn class 
class chess
{
public:
 inline chess(int x=0,int y=0,state c=blank)
 { point.x=x,point.y=y;
 color=c;
 };
 inline chess(chess &ch) 
 { point=ch.drop_point();
 color=ch.get_color();
 }
 ~chess(){};
 struct position drop_point()const;// Used to provide chess position to the outside world 
 inline state get_color() const { return color;}// Provides chess piece color information 
 void set_point();// Used to retrieve the position of a chess piece from the outside 
 void set_point(int x,int y){ point.x=x,point.y=y;}
 void set_point(position p){ point.x=p.x,point.y=p.y;}
 void set_color(state c){ color=c;}// Set the chess piece color 
private:
 position point;
 enum state color;
 };


position chess::drop_point()const
{
 return point; 
}
 
void chess::set_point()
{
 if(color==black)
 {
 setpos(110,1);
 cout<<" Please enter the number of columns and rows in the black box: ";
 cin>>point.x>>point.y;
 while(point.x<1||point.x>15)
 {
 setpos(110,1);
 cout<<" The number of columns entered is out of range, please re-enter 1~15 Between the digital   ";
 cin>>point.x;
 }
 while(point.y<1||point.y>15)
 {
 setpos(110,2);
 cout<<" The number of lines entered is out of range, please re-enter 1~15 Between the digital  ";
 cin>>point.y;
 }
 }
 else if(color==white)
 {
 setpos(110,1);
 cout<<" Please enter the number of columns and rows in white space: ";
 cin>>point.x>>point.y;
 while(point.x<1||point.x>15)
 {
 setpos(110,1);
 cout<<" The number of columns entered is out of range, please re-enter 1~15 Between the digital   ";
 cin>>point.x;
 }
 while(point.y<1||point.y>15)
 {
 setpos(110,2);
 cout<<" The number of lines entered is out of range, please re-enter 1~15 Between the digital  ";
 cin>>point.y;
 }
 }
 point.x--;
 point.y--;
}


// A board 
class chessboard
{
public:
 chessboard()
 {
 for(int i=0;i<15;i++)
 for(int j=0;j<15;j++)
 {
 square[i][j]=blank;
 }
 }
 chessboard(chessboard *cb)
 {
 for(int i=0;i<15;i++)
 for(int j=0;j<15;j++)
 {
 square[i][j]=cb->viewboard(i,j);
 }
 }
 inline state viewboard(position p_c) const;// Receives coordinates and returns the status of that position 
 inline state viewboard(int x,int y) const;// Receives an integer coordinate, returning the status of that position 
 void update(chess ch);// Receive new pieces and update board status 
 void display()const;// Output the checkerboard state 
 result judge(chess ch)const;// Rule function to determine whether a move is illegal and win 
 void clear()// Empty board 
 {
 for(int i=0;i<15;i++)
 for(int j=0;j<15;j++)
 {
 square[i][j]=blank;
 }
 }
private:
 state square[15][15];
};
int check_five(chessboard bd,chess ch)
{
 position ori=ch.drop_point();
 int count=1;// Counter, count the number of the same color 
 int sum[4]={0};
 bool locked=0;// A logical marker to mark whether a non-homochromatic node has been encountered 
 // Horizontal detection 
 for(int i=0,locked=0;i<5&&((ori.x-i)>=0)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x-i,ori.y))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[0]=count-1;
 for(int i=0,locked=0;i<5&&((ori.x+i)<=14)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x+i,ori.y))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[1]=count-sum[0]-2;
 sum[0]=count;
 if(count>=5)
 return count;
 // Vertical detection 
 count=1;
 for(int i=0,locked=0;i<5&&((ori.y-i)>=0)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x,ori.y-i))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[2]=count-1;
 for(int i=0,locked=0;i<5&&((ori.y+i)<=14)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x,ori.y+i))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[3]=count-sum[2]-2;
 sum[1]=count;
 if(count>=5)
 return count;
 // Upper left to lower right oblique detection 
 count=1;
 for(int i=0,locked=0;i<5&&((ori.y-i)>=0)&&((ori.x-i)>=0)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x-i,ori.y-i))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[4]=count-1;
 for(int i=0,locked=0;i<5&&((ori.x+i)<=14)&&((ori.y+i)<=14)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x+i,ori.y+i))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[5]=count-sum[4]-2;
 sum[2]=count;
 if(count>=5)
 return count;
 // Lower left to upper right oblique detection 
 count=1;
 for(int i=0,locked=0;i<5&&((ori.y+i)<=14)&&((ori.x-i)>=0)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x-i,ori.y+i))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[6]=count-1;
 for(int i=0,locked=0;i<5&&((ori.x+i)<=14)&&((ori.y-i)>=0)&&(!locked);i++)// Termination cycle condition: Same-color over 4 Or touch the boundary of the board or encounter non-homochromatic nodes 
 if(ch.get_color()==bd.viewboard(ori.x+i,ori.y-i))
 count++;
 else
 if(i!=0)
 locked=1;
 //sum[7]=count-sum[6]-2;
 sum[3]=count;
 if(count>=5)
 return count;
 return MAX(sum,4);
}


state chessboard::viewboard(position p_c) const
{
 return square[p_c.x][p_c.y];
}
state chessboard::viewboard(int x,int y) const
{
 return square[x][y];
}
void chessboard::update(chess ch)
{
 position pos=ch.drop_point();
 square[pos.x][pos.y]=ch.get_color();
}


void chessboard::display()const
{
 system("cls");


 for(int i=0;i<15;i++)// Print column coordinates 
 {
 gps(0,6+i*hor,i+1);
 }
 for(int i=0;i<15;i++)// Print column coordinates 
 {
 gps(16*ver,6+i*hor,i+1);
 }
 for(int i=0;i<15;i++)// Print line coordinates 
 {
 gps(3+i*ver,1,i+1);
 }
 for(int i=0;i<15;i++)// Print line coordinates 
 {
 gps(3+i*ver,1+16*hor,i+1);
 }
 for(int i=0,j=0;i<15;i++)
 {
 for(j=0;j<15;j++)
 tab(1+i*ver,3+hor*j,square[j][i]);
 }
 cout<<endl;
}
result chessboard::judge(chess set)const
{
 bool full=1;
 if(viewboard(set.drop_point())!=blank)
 {
 return error;
 }


 if(check_five(*this,set)>=5&&(set.get_color()==black))
 return black_win;


 if(check_five(*this,set)>=5&&(set.get_color()==white))
 return white_win;


 for(int i=0;i<15;i++)
 for(int j=0;j<15;j++)
 {
 if(square[i][j]==blank) 
 full=0;
 }
 if(full==1)
 return draw;
 else
 return go_on;
}
#endif

The main function, game class should be defined to optimize, but the design is not considered, but according to the C thought.


#include "ai.h"
#include <stdlib.h>


int main()
{
 system("mode con cols=150 lines=150 ");
 system("color 27");
 chessboard bd;
 chess now;
 result final;
 int mode;
 gps(5,40,"============== Welcome easy to use 5 The child is! ==============");
 gps(10,50,">>>> The input 1 or 2 Make pattern selection <<<<");
 gps(11,50,"  <1>  Double against  ");
 gps(12,50,"  <2>  The man-machine against  ");
 do{
 cout<<endl<<"         input mode:";
 cin>>mode;
 }while(mode != 1 && mode != 2);
 
 // Double against 
 if (mode==1)
 {
loop1: now.set_color(black);// You play with black first 
 bd.clear();
 bd.display(); // Initializing checkerboard 
 setpos(110,0);
 cout<<" The game begins with the black flag ";
 // In cyclic judgment 1 Second drop results, collect the next 1 Time input, until the game results 
 do{ 
 now.set_point();// The input 
 final=bd.judge(now);
 // Judge if there is a violation 
 while(final==error)// Foul input is re-input 
 {
 system("cls");
 bd.display();
 setpos(110,10);
 cout<<" A foul ( Input coordinates already have chess pieces )!";
 now.set_point();
 final=bd.judge(now);
 }
 // Update the board after the correct placement 
 bd.update(now);
 bd.display();
 // Under the inversion 1 The color of the move 
 if(now.get_color()==black)
 now.set_color(white);
 else
 now.set_color(black);
 
 }while(final==go_on);
 switch (final)
 {
 case go_on:
 break;
 case error:
 break;
 case draw:
 setpos(110,10);
 cout<<" A draw : Game over ";
 break;
 case black_win:
 setpos(110,10);
 cout<<" The black flag victory : Game over ";
 break;
 case white_win:
 setpos(110,10);
 cout<<" A white flag to win : Game over ";
 break;
 default:
 break;
 }
 setpos(110,11);
 cout<<" Do you want to continue 1 Bureau? Y/N";
 char flag;
 cin>>flag;
 if(flag == 'Y')
 goto loop1;
 }
 if(mode == 2)
 {
 chess ai_ch;
 system("cls");
 gps(5,40,"============== Welcome easy to use 5 The child is! ==============");
 gps(10,50,">>>> The input 1 or 2 Make pattern selection <<<<");
 gps(11,50,"  <1>  You play with black first  ");
 gps(12,50,"  <2>  ZhiBai jump  ");
 do{
 cout<<endl<<"         input mode:";
 cin>>mode;
 }while(mode != 1 && mode != 2);
 if(mode == 1)
 {
loop2: now.set_color(black);// You play with black first 
 bd.clear();
 bd.display(); // Initializing checkerboard 
 Ai afago(bd,white);
 setpos(110,0);
 cout<<" The match starts, please settle down ";
 now.set_point();
 bd.update(now);
 ai_ch.set_color(white);
 ai_ch.set_point(left(now.drop_point(),false));
 bd.update(ai_ch);
 bd.display();
 // In cyclic judgment 1 Second drop results, collect the next 1 Time input, until the game results 
 do{ 
 now.set_point();// The input 
 final=bd.judge(now);
 // Judge if there is a violation 
 while(final==error)// Foul input is re-input 
 {
  system("cls");
  bd.display();
  setpos(110,10);
  cout<<" A foul ( Input coordinates already have chess pieces )!";
  now.set_point();
  final=bd.judge(now);
 }
 // Update the board after the correct placement 
 bd.update(now);
 if(final != black_win)
 {
  ai_ch=afago.set_chess();
  final=bd.judge(ai_ch);
  bd.update(ai_ch);
  bd.display();
 }else{bd.display();}
 }while(final==go_on);
 switch (final)
 {
 case go_on:
  break;
 case error:
  break;
 case draw:
  setpos(110,10);
  cout<<" A draw : Game over ";
  break;
 case black_win:
  setpos(110,10);
  cout<<" Congratulations on your excellent chess skills and victory AI: Game over ";
  break;
 case white_win:
  setpos(110,10);
  cout<<" The computer wins, please keep trying to improve yourself : Game over ";
  break;
 default:
  break;
 }
 setpos(110,11);
 cout<<" Do you want to continue 1 Bureau? Y/N";
 char flag;
 cin>>flag;
 if(flag=='Y')
 goto loop2;
 }
 if(mode == 2)
 {
loop3: ai_ch.set_color(black);//AI You play with black first 
 now.set_color(white);
 bd.clear(); // Initializing checkerboard 
 Ai afago(bd,black);
 ai_ch.set_point(7,7);
 bd.update(ai_ch);
 bd.display(); 
 setpos(110,0);
 cout<<" The match starts, please settle down ";
 // In cyclic judgment 1 Second drop results, collect the next 1 Time input, until the game results 
 do{ 
 now.set_point();// The input 
 final=bd.judge(now);
 // Judge if there is a violation 
 while(final==error)// Foul input is re-input 
 {
  system("cls");
  bd.display();
  setpos(110,10);
  cout<<" A foul ( Input coordinates already have chess pieces )!";
  now.set_point();
  final=bd.judge(now);
 }
 // Update the board after the correct placement 
 bd.update(now);
 if(final != white_win)
 {
 ai_ch=afago.set_chess();
 final=bd.judge(ai_ch);
 bd.update(ai_ch);
 bd.display();
 }else{bd.display();}
 }while(final==go_on);
 switch (final)
 {
 case go_on:
  break;
 case error:
  break;
 case draw:
  setpos(110,10);
  cout<<" A draw : Game over ";
  break;
 case white_win:
  setpos(110,10);
  cout<<" Congratulations on your excellent chess skills and victory AI: Game over ";
  break;
 case black_win:
  setpos(110,10);
  cout<<" The computer wins, please keep trying to improve yourself : Game over ";
  break;
 default:
  break;
 }
 setpos(110,11);
 cout<<" Do you want to continue 1 Bureau? Y/N";
 char flag;
 cin>>flag;
 if(flag=='Y')
 goto loop3;
 }
 }
 return 0;
 
}

More interesting classic games to realize the special topic, to share with you:

C++ classic game summary

python classic game summary

python Tetris game set

JavaScript classic games play non-stop

java classic game summary

javascript classic game summary


Related articles: