Strange chess as a test

Good evening, native inhabitants!





Today I will bring to your attention a small article not related to my previous articles. More than a year ago, I had to do one test task to get a job. I completed it on time, but the competition was great and most likely they hired a person who made it using the recommended technologies and more colorful.





The essence of the problem is that there is a board of 8 by 8 cells. The player has 9 checkers, they are located in the corner of the board in a 3 by 3 square, the opponent also has the same number of checkers and they are located symmetrically diagonally in another corner in a 3 by 3 square. Each player takes turns, you need to reach the original position with checkers the opponent across the board, whoever reached the first one and won. You can only move to empty cells and only up, down, left and right (you cannot go diagonally!).





I added controls with a mouse, and play against a computer algorithm. Blacks are human, whites are AI.





Among other things, it is initially necessary to draw the board, checkers and manipulate the field.





A bit of code for clarity:





Game::Game()
{
	run = true;//     F5
	Matrix = new int* [8];// 64  -  0 -   ,    -  1  9,       10  18
	for (int i = 0; i < 8; i++)
		Matrix[i] = new int[8];
	//          , 64 
	QuadCoorXleft = new int* [8];//   Matrix      xleft    x
	QuadCoorXright = new int* [8];//xright -  x
	QuadCoorYdown = new int* [8];// y 
	QuadCoorYup = new int* [8];// y 
	for (int i = 0; i < 8; i++)
	{
		QuadCoorXleft[i] = new int[8];
		QuadCoorXright[i] = new int[8];
		QuadCoorYdown[i] = new int[8];
		QuadCoorYup[i] = new int[8];
	}
	//   
	ChessX = new double[18];//X
	ChessY = new double[18];//Y
	//     
	ActiveX = -1;//X
	ActiveY = -1;//Y
	Active = -1;//Value
	firstplayer = true;//     1 
	secondplayer = false;//     2 
	ai = new bool[18];//       
	chessai tmp;
	for (int i = 0; i < 18; i++)
	{
		ai[i] = false;
		if (i > 8)
		{
			tmp.ai = ai[i];
			tmp.value = i+1;
			Ai.push_back(tmp);//        
		}
	}
	aicountfirstrow = 0;// -  ( )   (0-)
	aicountsecondrow = 0;// -     (1-)
	aicountthirdrow = 0;// -     (2-)
}
      
      



The OpenGL and SDL2 libraries are used to draw and capture the mouse.





void Draw_Circle()
{
	// (-) 
	for (int i = 0; i <= 50; i++) {
		float a = (float)i / 50.0f * 3.1415f * 2.0f;
		glVertex2f(cos(a), sin(a));
	}
}
void Draw_Circle_Fill()
{
	// (-) 
	for (int i = 0; i <= 50; i++) {
		float a = (float)i / 50.0f * 3.1415f * 2.0f;
		glVertex2f(0.0, 0.0);
		glVertex2f(cos(a), sin(a));
	}
}
      
      



The most convenient thing is that you can use glTranslatef to fill the board with checkers with movements





...
for (int i = 0; i < 9; i++)
		{
			glPushMatrix();
			glTranslatef(ChessX[i], ChessY[i], 0);
			glScalef(0.05, 0.05, 1);
			glBegin(GL_LINE_LOOP);
			Draw_Circle();
			glEnd();
			glPopMatrix();
		}
		//   
		for (int i = 9; i < 18; i++)
		{
			glPushMatrix();
			glTranslatef(ChessX[i], ChessY[i], 0);
			glScalef(0.05, 0.05, 1);
			glBegin(GL_LINES);
			Draw_Circle_Fill();
			glEnd();
			glPopMatrix();
		}

...
      
      



Player moves:





void Game::Move_Up()
{
	//  
	if (Active > 0 && ActiveX != 0 && Matrix[ActiveX-1][ActiveY] == 0)//           
	{
		Matrix[ActiveX-1][ActiveY] = Matrix[ActiveX][ActiveY] ;//   ( )
		Matrix[ActiveX][ActiveY] = 0;//     
		ChessY[Active-1] += 0.2;//      
		ActiveX = -1;//   
		ActiveY = -1;//   
		Active = -1;//    
		std::cout << " Player MoveUp " << Active << std::endl;
		firstplayer = false;
		secondplayer = true;//      
	}
}
void Game::Move_Down()
{
	//  
	if (Active > 0 && ActiveX != 7 && Matrix[ActiveX+1][ActiveY] == 0)//           
	{
		Matrix[ActiveX+1][ActiveY] = Matrix[ActiveX][ActiveY] ;//   ( )
		Matrix[ActiveX][ActiveY] = 0;//     
		ChessY[Active-1] -= 0.2;//      
		ActiveX = -1;//   
		ActiveY = -1;//   
		Active = -1;//    
		std::cout << "Player MoveDown " << Active << std::endl;
		firstplayer = false;
		secondplayer = true;//      
	}
}
void Game::Move_Right()
{
	//  
	if (Active > 0 && ActiveY != 7 && Matrix[ActiveX][ActiveY+1] == 0)//           
	{
		Matrix[ActiveX][ActiveY+1] = Matrix[ActiveX][ActiveY] ;//   ( )
		Matrix[ActiveX][ActiveY] = 0;//     
		ChessX[Active-1] += 0.2;//      
		ActiveX = -1;//   
		ActiveY = -1;//   
		Active = -1;//    
		std::cout << "MoveRight " << Active << std::endl;
		firstplayer = false;
		secondplayer = true;//      
	}
}
void Game::Move_Left()
{
	//   
	if (Active > 0 && ActiveY != 0 && Matrix[ActiveX][ActiveY-1] == 0)//           
	{
		Matrix[ActiveX][ActiveY-1] = Matrix[ActiveX][ActiveY] ;//   ( )
		Matrix[ActiveX][ActiveY] = 0;//     
		ChessX[Active-1] -= 0.2;//      
		ActiveX = -1;//   
		ActiveY = -1;//   
		Active = -1;//    
		std::cout << "MoveLeft " << Active << std::endl;
		firstplayer = false;
		secondplayer = true;//      
	}
}
      
      



The moves of the computer are almost similar to the moves of the player, at the end there will be a link to the full code of the game, if anyone is interested.





void Game::ReccurentWalk()
{
	//  
	current = -1, currentI = -1, currentJ = -1;//    
	for (int i = 0; i < Ai.size(); i++)//  
		if (!Ai[i].ai)//      
		{
			if (Check_MoveUp(Ai[i].value) || Check_MoveLeft(Ai[i].value))//     ?
			{
				current = Ai[i].value;//  
				break;
			}
			else
			{
				//       
				std::vector<chessai>::iterator position = std::find_if(Ai.begin(), Ai.end(), find_s(Ai[i].value));
				if (position != Ai.end()) // == vector.end() means the element was not found
					Ai.erase(position);
			}
		}
	for (int i = 0; i < 8; i++)
		for (int j = 0; j < 8; j++)
			if (Matrix[i][j] == current)//      
			{
				currentI = i;
				currentJ = j;
				break;
			}
	if (currentI != -1 && currentJ != -1)//        
	{
		if (!Move_UpAI(currentI, currentJ))
			if (!Move_LeftAI(currentI, currentJ))
			{
				ReccurentWalk();
			}
	}
	else
	{
		//       
		chessai tmp;
		for (int i = 0; i < 18; i++)
		{
			ai[i] = false;
			if (i > 8)
			{
				tmp.ai = ai[i];
				tmp.value = i + 1;
				Ai.push_back(tmp);
			}
		}
		//       
		for (int i = 0; i < Ai.size(); i++)
			if (!Ai[i].ai)
			{
				if (Check_MoveRight(Ai[i].value) || Check_MoveDown(Ai[i].value))
				{
					current = Ai[i].value;
					break;
				}
				else
				{
					//      
					std::vector<chessai>::iterator position = std::find_if(Ai.begin(), Ai.end(), find_s(Ai[i].value));
					if (position != Ai.end()) // == Vector.end() means the element was not found
						Ai.erase(position);
				}
			}
		//    
		for (int i = 0; i < 8; i++)
			for (int j = 0; j < 8; j++)
				if (Matrix[i][j] == current)
				{
					currentI = i;
					currentJ = j;
					break;
				}
		//   
		if(!Move_RightAI(currentI, currentJ))
			if (!Move_DownAI(currentI, currentJ))
			{
				std::cout <<"Artificial Intellegence asked: WTF?" << std::endl;
			}
	}
	chessai tmp;
	if(Ai.empty())//      
		for (int i = 0; i < 18; i++)
		{
			ai[i] = false;
			if (i > 8)
			{
				tmp.ai = ai[i];
				tmp.value = i + 1;
				Ai.push_back(tmp);
			}
		}
}
      
      



Well, in fact, I will describe in words what the AI ​​is doing. He collects three pawns at the top on the 0-th line and if it is impossible to move to the left, then he moves up the remaining 3 pawns by 1 line, similarly to the 2-nd line. If it is impossible to move left and up, then he takes any checker and moves either down or to the right if it is possible, of course, that is, he always strives to move to the left or up (provided that there are less than three checkers in the line above).





Well, actually, the gameplay:





And a link to the source code .








All Articles