C++ 实现对战AI五子棋

news2024/7/4 22:28:06

 个人主页:日刷百题

系列专栏〖C/C++小游戏〗〖Linux〗〖数据结构〗 C语言

🌎欢迎各位点赞👍+收藏⭐️+留言📝 

前言:

     为了能够快速上手一门语言,我们往往在学习了基本语法后,采用写一个小项目的方式来加深理解语言的语法及运用,本文采用c++去实现对战AI五子棋,采用面向对象开发的一款游戏,里面应用了类和对象以及vector容器等知识。

 一、项目效果展示


 


二、游戏思路

 


 

三、游戏框架

我们这里创建四个类(可以简单的理解为加强版的结构体),玩家类、AI类、棋盘类、棋盘控制类,将玩家类、AI类、棋盘类作为参数传给棋盘控制类,棋盘控制类获取这三个类的信息,从而可以控制游戏的运行,而玩家和AI要进行下棋操作时,需要棋盘信息,所以在玩家和AI类设置棋盘类。

根据上面分析,我们搭建好框架,先实现棋盘类功能,再实现AI和玩家类,最后实现棋盘控制类

四、棋盘类实现

4.1  用棋盘类构造函数初始化

4.1.1  checkerboard.h

#include<graphics.h>//eaysx头文件
#include<vector>
using namespace std;
enum  GameResult { BLACK_WIN,WHITE_WIN,DRAW ,CONTINUE};
class checkerboard
{
public:
	//构造函数初始化成员变量
	checkerboard(int BoardSize, int margin_x, int margin_y, float ChessSize)
	{
		this->BoardSize = BoardSize;//几线棋盘
		this->margin_x=margin_x;
		this->margin_y = margin_y;
		this->ChessSize = ChessSize;//棋子大小

		 //加载黑子和白子图片到黑子和白子变量
		loadimage(&BLACK_IMG, "res/black.png", ChessSize, ChessSize, true);
		loadimage(&WHITE_IMG, "res/white.png", ChessSize, ChessSize, true);
		
	//棋盘初始化
		for (int i = 0; i < ChessSize; i++)
		{
			vector<int> row;
			for (int j = 0; j < ChessSize; j++)
			{
				row.push_back(0);
			}
			BoardMap.push_back(row);
		}

		
		 gameresult= CONTINUE;
		

	}

	

	int BoardSize;//棋盘大小
	float ChessSize;//棋子大小
	vector<vector<int>> BoardMap;//表示棋盘落子情况
private:
	IMAGE BLACK_IMG;//黑棋图片变量
	IMAGE WHITE_IMG;//白棋图片变量
	
	int margin_x;//左侧边界45
	int margin_y;//右侧边界45


};

 4.2  棋盘类初始化函数

注:

这个初始化函数和棋盘类构造函数的初始化一样,为什么再初始化一次呢?因为我们后面进行游戏运行时,一局结束,再来一局还需要再调用一次棋盘初始化,而定义棋盘类只能调用一次构造函数,所以再创一个棋盘类初始化函数

4.2.1  checkerboard.h

pubilc:
void Init();//棋盘初始化

4.2.2   checkerboard.cpp

void checkerboard::Init()
{
    initgraph(L, W, 1);//窗口大小
    //加载到窗口棋盘图片
    loadimage(0, "res/棋盘2.jpg", L,W,true);
    //播放声音
  /*  mciSendString("play res/start.WAV", 0, 0, 0);*/
    //加载黑子和白子图片到黑子和白子变量
    //loadimage(&BLACK_IMG, "res/black.png", ChessSize, ChessSize, true);
    //loadimage(&WHITE_IMG, "res/white.png", ChessSize, ChessSize, true);

    //后面没有调用构造函数,调用初始化,所有在这里还需要对容器归0
    for (int i = 0; i < ChessSize; i++)
    {
        
        for (int j = 0; j < ChessSize; j++)
        {
            BoardMap[i][j] = 0;
        }
        
    }

    gameresult = CONTINUE;
  
}

4.3  检查鼠标点击是否有效

注:

虽然代码很长,但是思路很简单,先计算点击位置(x,y) 附近的4个落棋位置的实际坐标位置,然后再计算点击位置到这四个落棋位置之间的距离,如果落棋位置与点击位置距离小于棋子大小的0.4倍,就认为这个落棋位置是玩家想要落棋的位置,存储在pos中。若此时该位置没有其他棋子,则为有效点击,返回真。

4.3.1 checkerboard.h

棋盘类外:

//落子位置
struct ChessPos
{
	int row;
	int col;
};
enum  chess_type{CHESS_WHITE=-1,CHESS_BLACK=1};

棋盘类内:

public:
bool ClickBord(int x, int y, ChessPos& pos);//检查有效点击

4.3.2 checkerboard.cpp

bool checkerboard::ClickBord(int x, int y, ChessPos& pos)
{
    //保证在棋盘内
    if (x >= margin_x && x <= (L - margin_x) && y >= margin_y && y <= (W - margin_y))
    {
        int col = (x - margin_x) / ChessSize;
        int row = (y - margin_y) / ChessSize;
        //该位置左上角的交点的坐标
        int LTPos_x = margin_x + ChessSize * col;
        int LTPos_y = margin_y + ChessSize * row;

        int critical = ChessSize * 0.4;//临界值
        //鼠标点击位置与右上角交点之间的距离
        int distance1 = sqrt((x - LTPos_x) * (x - LTPos_x) + (y - LTPos_y) * (y - LTPos_y));//勾股定理


         //该位置右上角的交点的坐标
        int RTPos_x = LTPos_x + ChessSize;
        int RTPos_y = LTPos_y;


        //鼠标点击位置与右上角交点之间的距离
        int distance2 = sqrt((x - RTPos_x) * (x - RTPos_x) + (y - RTPos_y) * (y - RTPos_y));//勾股定理

         //该位置左下角的交点的坐标
        int LDPos_x = LTPos_x;
        int LDPos_y = LTPos_y + ChessSize;


        //鼠标点击位置与左下角交点之间的距离
        int distance3 = sqrt((x - LDPos_x) * (x - LDPos_x) + (y - LDPos_y) * (y - LDPos_y));//勾股定理



         //该位置右下角的交点的坐标
        int RDPos_x = LTPos_x + ChessSize;
        int RDPos_y = LTPos_y + ChessSize;


        //鼠标点击位置与右下角交点之间的距离
        int distance4 = sqrt((x - RDPos_x) * (x - RDPos_x) + (y - RDPos_y) * (y - RDPos_y));//勾股定理
        if (distance1 <= critical)
        {
            pos.col = col;
            pos.row = row;
            if (BoardMap[pos.row][pos.col] == 0)//该坐标没有棋子
            {
                return true;
            }
            return false;

        }
        else if (distance2 <= critical)
        {
            pos.col = col + 1;
            pos.row = row;
            if (BoardMap[pos.row][pos.col] == 0)//该坐标没有棋子
            {
                return true;
            }
            return false;


        }
        else if (distance3 <= critical)
        {
            pos.col = col;
            pos.row = row + 1;
            if (BoardMap[pos.row][pos.col ] == 0)//该坐标没有棋子
            {
                return true;
            }
            return false;


        }
        else if (distance4 <= critical)
        {
            pos.col = col + 1;
            pos.row = row + 1;
            if (BoardMap[pos.row ][pos.col] == 0)//该坐标没有棋子
            {
                return true;
            }
            return false;


        }
        else
        {
            return false;
        }
    }

    else
    {
        return false;
    }
}

4.4   下棋

功能:实现记录最后一次落子的位置以及最后一次下棋是玩家方还是AI方,在棋盘二维数组记录落子数据。

 4.4.1 checkerboard.h

 棋盘类外:

//落子位置
struct ChessPos
{
	int row;
	int col;
};
enum  chess_type{CHESS_WHITE=-1,CHESS_BLACK=1};

棋盘类内:

public:
	void PlayChess(ChessPos& pos,chess_type type);//下棋

  4.4.2 checkerboard.cpp

void checkerboard::PlayChess(ChessPos& pos, chess_type type)
{
    int x = margin_x + ChessSize * pos.col-ChessSize*0.5;
    int y = margin_y + ChessSize * pos.row- ChessSize *0.5;
   
        BoardMap[pos.row][pos.col] = type;
        lastpos.row = pos.row;
        lastpos.col = pos.col;
        lasttype = type;
    
    if (type == CHESS_BLACK)
    {
        putimagePNG(x, y, &BLACK_IMG);
       
    }
    else
    {
        putimagePNG(x, y, &WHITE_IMG);

    }
}

4.5  判断棋盘是否下满

4.5.1 checkerboard.h

bool BoardFull();

4.5.2 checkerboard.cpp

bool checkerboard::BoardFull()
{
    for (int row = 0; row < BoardSize; row++)
    {
        for (int col = 0; col < BoardSize; col++)
        {
            if (BoardMap[row][col] == 0)//棋盘没满
            {
                return false;
            }
        }
   }
    return true;
}

 4.6  判断游戏状态

4.6.1 checkerboard.h

 棋盘类外:

enum  GameResult { BLACK_WIN,WHITE_WIN,DRAW ,CONTINUE};

 棋盘类内: 

private:
GameResult gameresult;
GameResult IsWin();

4.6.2 checkerboard.cpp 

GameResult checkerboard::IsWin()
{
    bool boardfull = BoardFull();
    
    //每个方向记连续棋子个数
    int Black_Num = 0;
    int  White_Num = 0;
    if (lasttype == CHESS_BLACK)//黑子方
    {
        //计算四个方向是否有5个
        for (int i = 0; i <= 1; i++)//分横,竖,上斜,下斜4个方向
        {
            for (int j = -1; j <= 1; j++)
            {
                //每个方向记连续棋子个数
                Black_Num = 0;
                White_Num = 0;


                if ((i == 0 && j == 0) || (i == 0 && j == 1))
                {
                    continue;
                }
                for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中的单向
                {
                    int Cur_row = lastpos.row + i * k;
                    int Cur_col = lastpos.col + j * k;
                    if (Cur_row >= 0 && Cur_row < BoardSize &&
                        Cur_col >= 0 && Cur_col < BoardSize &&
                        BoardMap[Cur_row][Cur_col] == CHESS_BLACK)
                    {
                        Black_Num++;
                    }

                    else//超出棋盘或者是白子或者空白
                    {
                        break;
                    }
                }
                for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中单向的另一个方向
                {
                    int Cur_row = lastpos.row - i * k;
                    int Cur_col = lastpos.col - j * k;
                    if (Cur_row >= 0 && Cur_row < BoardSize &&
                        Cur_col >= 0 && Cur_col < BoardSize &&
                        BoardMap[Cur_row][Cur_col] == CHESS_BLACK)
                    {
                        Black_Num++;
                    }
                    else//超出棋盘或者是白子或者空白
                    {
                        break;
                    }
                }
                //判断游戏状态
                if (Black_Num == 4)//5个黑子,游戏结束
                {
                    
                    return BLACK_WIN;
                }
                else
                {
                    if (boardfull)
                    {
                        return  DRAW;
                    }
                    
                }

            }
        }

    }
    else//白子方
    {
        //计算四个方向是否有5个
        for (int i = 0; i <= 1; i++)//分横,竖,上斜,下斜4个方向
        {
            for (int j = -1; j <= 1; j++)
            {
                //每个方向记连续棋子个数
                Black_Num = 0;
                White_Num = 0;


                if ((i == 0 && j == 0) || (i == 0 && j == 1))
                {
                    continue;
                }
                for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中的单向
                {
                    int Cur_row = lastpos.row + i * k;
                    int Cur_col = lastpos.col + j * k;
                    if (Cur_row >= 0 && Cur_row < BoardSize &&
                        Cur_col >= 0 && Cur_col < BoardSize &&
                        BoardMap[Cur_row][Cur_col] == CHESS_WHITE)
                    {
                        White_Num++;
                    }

                    else//超出棋盘或者是黑子或者空白
                    {
                        break;
                    }
                }
                for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中单向的另一个方向
                {
                    int Cur_row = lastpos.row - i * k;
                    int Cur_col = lastpos.col - j * k;
                    if (Cur_row >= 0 && Cur_row < BoardSize &&
                        Cur_col >= 0 && Cur_col < BoardSize &&
                        BoardMap[Cur_row][Cur_col] == CHESS_WHITE)
                    {
                       White_Num++;
                    }
                    else//超出棋盘或者是黑子或者空白
                    {
                        break;
                    }
                }
                //判断游戏状态
                if (White_Num == 4)//5个白子,游戏结束
                {

                    return WHITE_WIN;
                }
                else
                {
                    if (boardfull)
                    {
                        return  DRAW;
                    }

                }

            }
        }

    }
    return CONTINUE;
}

4.7   判断游戏是否结束

4.7.1 checkerboard.h

bool CheckOver();//检查游戏是否结束 

4.7.2  checkerboard.cpp

bool checkerboard::CheckOver()
{
    gameresult = IsWin();
    if (gameresult == BLACK_WIN)
    {
        Sleep(2000);
        loadimage(0, "res/胜利.jpg",W,L,true);
        //播放声音
        mciSendString("play res/胜利.mp3", 0, 0, 0);
        _getch();
        return true;
    }
    else if (gameresult == WHITE_WIN)
    {
        Sleep(2000);
        loadimage(0, "res/失败.jpg",W , L, true);
        //播放声音
        mciSendString("play res/失败.mp3", 0, 0, 0);
        _getch();//暂停,按任意键继续
        return true;
    }
    else if (gameresult == DRAW)
    {
        Sleep(2000);
        loadimage(0, "res/平局.png",W , L , true);
        _getch();
        return true;
        
    }
    else//继续游戏
    {
        return false;
    }

}

五、玩家类实现 

5.1  用玩家类构造函数初始化

5.1.1  chess_player.h

#include"checkerboard.h"
#include"AI.h"
class chess_player
{
public:
	chess_player(checkerboard& checkerboard)
	{
		this->checkerboard = &checkerboard;
	}
	
	void go();
private:
	checkerboard* checkerboard;
};

5.2  玩家下棋

5.2.1 chess_player.h

void go();

5.2.2  chess_player.cpp 

void chess_player::go()
{
	
	ChessPos pos;
	while (1)
	{
		MOUSEMSG mousemsg = GetMouseMsg();//鼠标信息结构体变量
		bool click_board = checkerboard->ClickBord(mousemsg.x, mousemsg.y, pos);
		if (mousemsg.uMsg == WM_LBUTTONDOWN &&click_board )//用到checkboard对象的成员
		{
			printf("%d,%d\n", pos.row, pos.col);
			break;
		}
	}
	
	checkerboard->PlayChess(pos, CHESS_BLACK);//黑子下棋的位置(渲染和记录)
}

六、AI类实现

6.1 用AI类构造函数初始化

6.1.1  AI.h

#include"checkerboard.h"
#include<vector>
class AI
{
public:
	AI(checkerboard& checkerboard)//AI构造函数
	{
		this->checkerboard = &checkerboard;
		for (int i = 0; i <checkerboard.ChessSize; i++)
		{
			vector<int> row;
			for (int j = 0; j <checkerboard.ChessSize; j++)
			{
				row.push_back(0);
			}
			ScoreMap.push_back(row);
		}
	}

	void go();

private:
	checkerboard* checkerboard;
	vector<vector<int>>  ScoreMap;
	void  CalculateScore();
	ChessPos   MaxScore();
	
};

6.2  AI计算权值最高的棋盘空白位置

计算棋盘空白位置的权值,首先对该位置的横、竖、上斜、下斜四个方位做判断,以该位置为起点,每个方位只需要在单方向上判断4个棋子位,反方向判断四个棋子位,统计连续的白子或者黑子个数,根据下面的表格给出相应权重值,选择出累计权值最高的位置为AI落子点。

 6.2.1  AI.h 

private:
	
	vector<vector<int>>  ScoreMap;
	void  CalculateScore();

  6.2.2  AI.cpp

void AI::CalculateScore()
{
	int Black_Num = 0;
	int White_Num = 0;
	int Empty_Num = 0;
	for(int row=0;row<checkerboard->BoardSize;row++)
		for (int col = 0; col< checkerboard->BoardSize; col++)
		{
			if (checkerboard->BoardMap[row][col] != 0)//有棋子,则跳过判断
			{
				continue;
			}
			//先假设下黑子,计分情况
			for (int i = 0; i <= 1; i++)//分横,竖,上斜,下斜4个方向
			{
				for (int j = -1; j <= 1; j++)
				{
					//每个方向记连续棋子个数
					Black_Num = 0;
					 White_Num = 0;
					 Empty_Num = 0;

					if ((i == 0 && j == 0) || (i ==0 && j == 1))
					{
						continue;
					}
					for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中的单向
					{
						int Cur_row = row + i * k;
						int Cur_col = col + j * k;
						if (Cur_row>=0&&Cur_row<checkerboard->BoardSize&&
							Cur_col>=0&&Cur_col<checkerboard->BoardSize&&
							checkerboard->BoardMap[Cur_row][Cur_col] == CHESS_BLACK)
						{
							Black_Num++;
						}
						else if(Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] ==0)
						{
							Empty_Num++;
							break;
						}
						else//超出棋盘或者是白子
						{
							break;
						}
					}
					for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中单向的另一个方向
					{
						int Cur_row = row - i * k;
						int Cur_col = col - j * k;
						if (Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] == CHESS_BLACK)
						{
							Black_Num++;
						}
						else if (Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] == 0)
						{
							Empty_Num++;
							break;
						}
						else//超出棋盘或者是白子
						{
							break;
						}
					}
					//该位置的得分情况
					if (Black_Num == 1)//2个黑子
					{
						ScoreMap[row][col] += 10;
					}
					else if (Black_Num == 2)//连续三个黑子
					{
						if (Empty_Num == 1)
						{
							ScoreMap[row][col] += 30;
						}
						else if(Empty_Num==2)
						{
							ScoreMap[row][col] += 40;
						}
					}
					else if (Black_Num == 3)//连续4个黑子
					{
						if (Empty_Num == 1)
						{
							ScoreMap[row][col] += 60;
						}
						else if (Empty_Num == 2)
						{
							ScoreMap[row][col] += 200;
						}
					}
					else if (Black_Num == 4)//连续5个黑子
					{
						ScoreMap[row][col] += 20000;
					}
				}
			}
			//假设该位置下白子,计分情况
			for (int i = 0; i <= 1; i++)//分横,竖,上斜,下斜4个方向
			{
				for (int j = -1; j <= 1; j++)
				{
					//每个方向记连续棋子个数
					Black_Num = 0;
					White_Num = 0;
					Empty_Num = 0;

					if ((i == 0 && j == 0) || (i == 0 && j == 1))
					{
						continue;
					}
					for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中的单向
					{
						int Cur_row = row + i * k;
						int Cur_col = col + j * k;
						if (Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] == CHESS_WHITE)
						{
							White_Num++;
						}
						else if (Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] == 0)
						{
							Empty_Num++;
							break;
						}
						else//超出棋盘或者是黑子
						{
							break;
						}
					}
					for (int k = 1; k <= 4; k++)//最多判断五个子,四个方向中单向的另一个方向
					{
						int Cur_row = row - i * k;
						int Cur_col = col - j * k;
						if (Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] == CHESS_WHITE)
						{
							White_Num++;
						}
						else if (Cur_row >= 0 && Cur_row < checkerboard->BoardSize &&
							Cur_col >= 0 && Cur_col < checkerboard->BoardSize &&
							checkerboard->BoardMap[Cur_row][Cur_col] == 0)
						{
							Empty_Num++;
							break;
						}
						else//超出棋盘或者是黑子
						{
							break;
						}
					}
					//该位置的得分情况
					if (White_Num == 0)//1个白子
					{
						ScoreMap[row][col] += 5;
					}
					else if (White_Num == 1)//连续2个白子
					{
						
						ScoreMap[row][col] += 10;
						
					}
					else if (White_Num == 2)//连续3个白子
					{
						if (Empty_Num == 1)
						{
							ScoreMap[row][col] += 25;
						}
						else if (Empty_Num == 2)
						{
							ScoreMap[row][col] += 50;
						}
					}
					else if (White_Num == 3)//连续4个白子
					{
						if (Empty_Num == 1)
						{
							ScoreMap[row][col] += 55;
						}
						else if (Empty_Num == 2)
						{
							ScoreMap[row][col] += 300;
						}
					}
					else if (White_Num == 4)//连续5个白子
					{
						ScoreMap[row][col] += 30000;

					}
				}
			}
		}
}

6.3  选择权值最高的棋盘位置

 6.3.1  AI.h 

private:
ChessPos   MaxScore();

 6.3.2  AI.cpp

ChessPos AI::MaxScore()
{
	int max = 0;
	vector<ChessPos> maxscore_pos;
	ChessPos pos;
	CalculateScore();
	for (int row = 0; row < checkerboard->BoardSize; row++)
	{
		for (int col = 0; col < checkerboard->BoardSize; col++)
		{
			if (ScoreMap[row][col] > max)
			{
				max = ScoreMap[row][col];
				maxscore_pos.clear();
				pos.row = row;
				pos.col = col;
				maxscore_pos.push_back(pos);
			}
			else if (ScoreMap[row][col] == max)
			{
				pos.row = row;
				pos.col = col;
				maxscore_pos.push_back(pos);
			}
		}
	}

	//计分棋盘归0
	for (int i = 0; i < checkerboard->ChessSize; i++)
	{
		for (int j = 0; j < checkerboard->ChessSize; j++)
		{
			ScoreMap[i][j] = 0;
		}
		
	}
	int index = rand() % maxscore_pos.size();
	return maxscore_pos[index];
}

 6.4 AI下棋

 6.4.1  AI.h 

void go();

 6.4.2  AI.cpp

void AI::go()
{
	ChessPos pos = MaxScore();
	checkerboard->PlayChess(pos, CHESS_WHITE);//白子下棋的位置(渲染和记录)
}

 七、棋盘控制类实现

7.1 用棋盘控制类构造函数初始化

7.1.1 ChessGame.h

#include"chess_player.h"
#include"AI.h"
#include"checkerboard.h"
class ChessGame
{
public:
	ChessGame(chess_player& chess_player, AI& ai, checkerboard& checkerboard)//构造函数初始化
	{
		this->chess_player = &chess_player;
		this->ai = &ai;
		this->checkerboard = &checkerboard;
	}
	void play();//开始游戏


//创建数据成员变量
private:
	chess_player* chess_player;
	AI* ai;
	checkerboard* checkerboard;

};

7.2 控制游戏进行

7.2.1 ChessGame.h 

void play();//开始游戏

7.2.2 ChessGame.cpp

//开始游戏

void ChessGame::play()
{
again:
	checkerboard->Init();
	while (1)
	{
		//棋手先走
		chess_player->go();
		if (checkerboard->CheckOver())
		{
			goto  again;
			
		}
		//AI走
		ai->go();
		if (checkerboard->CheckOver())
		{
			
			goto  again;

		}

	}
}

八、主函数

#include<iostream>
#include"ChessGame.h"
int main()
{
	srand((unsigned int)time(NULL));
	checkerboard checkerboard( 13, 45*0.7, 45*0.7,67.25*0.7);//自动调用构造函数
	chess_player chess_player(checkerboard);//自动调用构造函数
	AI ai(checkerboard);//自动调用构造函数;
	ChessGame chessgame(chess_player,ai, checkerboard);//引用传值
	
	chessgame.play();
	return 0;
	

}

完整代码及素材:c和c++代码: 争取每日一更。。。。。。 - Gitee.comicon-default.png?t=N7T8https://gitee.com/daily-brush-100-questions/c-language-training-camp/tree/master/c++AI%E4%BA%94%E5%AD%90%E6%A3%8B/c++AI%E4%BA%94%E5%AD%90%E6%A3%8B

希望大家阅读完可以有所收获,同时也感谢各位铁汁们的支持。文章有任何问题可以在评论区留言,百题一定会认真阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1360008.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【自学笔记】01Java基础-09Java关键字详解

介绍java&#xff08;基于java11&#xff09;中所有关键字&#xff0c;以及主要重要的关键字详解。 1 Java 11中的关键字&#xff1a; 1.1 类型声明与变量定义 boolean&#xff1a;声明布尔类型变量&#xff0c;只有两个可能值 true 或 false。byte&#xff1a;声明一个8位有…

[UUCTF 2022 新生赛]ez_rce

[UUCTF 2022 新生赛]ez_rce wp 在做这道题时&#xff0c;我参考了这篇博客&#xff1a; https://www.cnblogs.com/bkofyZ/p/17594549.html 认识到了自己的一些不足。 题目代码如下&#xff1a; <?php ## 放弃把&#xff0c;小伙子&#xff0c;你真的不会RCE,何必在此纠…

实验笔记之——基于COLMAP的Instant-NGP与3D Gaussian Splatting的对比

之前博客进行了COLMAP在服务器下的测试 实验笔记之——Linux实现COLMAP-CSDN博客文章浏览阅读794次&#xff0c;点赞24次&#xff0c;收藏6次。学习笔记之——NeRF SLAM&#xff08;基于神经辐射场的SLAM&#xff09;-CSDN博客NeRF 所做的任务是 Novel View Synthesis&#xf…

静态网页设计——个人兴致小屋(HTML+CSS+JavaScript)

前言 使用技术&#xff1a;HTMLCSSJS 主要内容&#xff1a;对个人兴致的一些介绍&#xff0c;画风优美。 主要内容 1、首页 首页是一个优美的背景加一句欢迎来到xxx的兴致小屋&#xff0c;可将XXX改成自己。点击确定可以跳到主页。 部分代码&#xff1a; <body><…

接口自动化-allure测试报告

学习目标&#xff1a; 1、测试报告的作用 2、allure的安装 3、allure的基本使用 4、allure的高级使用 学习内容&#xff1a; 1、测试报告的作用 自动化接口的结果呈现虽然可以通过日志文件去查看用例的成功或者失败&#xff0c;但是这样的结果就是不美观&#xff0c;不能…

外包干了3个多月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

阿里云大模型「让照片跳舞」刷屏朋友圈,有哪些信息值得关注?

介绍 大家好&#xff0c;我分享聊聊阿里通义千问APP中全民舞王功能。 网络热舞结合AI视频&#xff0c;这是以后不用学习跳舞&#xff1f; 可以尝试下效果&#xff0c;一张图片生成视频。 APP快速使用 搜索下载通义千问APP 打开APP&#xff0c;选中一张照片来跳舞。 这里…

Halcon算子精讲:形态学操作(圆形操作)

膨胀操作&#xff08;圆形膨胀&#xff09; 算子 dilation_circle(Region, RegionDilation, 3.5) 原理 将区域中边界的每个像素点以3.5为半径做圆&#xff0c;原有区域 所做圆区域 膨胀后区域。 作用 扩大目标所在区域或连接区域破碎部分。 对比图 腐蚀操作&#xff08;圆…

陀螺研究院发布《中国产业区块链生态图谱 2024版》

从发展实践来看&#xff0c;产业区块链在我国已历经了4年的高速发展&#xff0c;发展至今&#xff0c;我国区块链发展环境基本夯实&#xff0c;形成了技术突破与应用拓宽的创新土壤&#xff0c;围绕区块链为主体的产业链条不断纵深延伸&#xff0c;在基础设施支撑、融合创新拓展…

外包干了5个月,技术明显退步了...

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年12月份&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

惊呆:RocketMQ顺序消息,是“4把锁”实现的(顺序消费)

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多关于RocketMQ 的、很重要的面试题&#xff1a; 如何保证RocketMQ消息有序&#xff1f; Ro…

一文详解 Java 限流接口实现

作者&#xff1a;非有 一、限流 1.1 为什么要进行限流&#xff1f; 1.瞬时流量过高&#xff0c;服务被压垮&#xff1f; 2.恶意用户高频光顾&#xff0c;导致服务器宕机&#xff1f; 3.消息消费过快&#xff0c;导致数据库压力过大&#xff0c;性能下降甚至崩溃&#xff1f…

图像分割实战-系列教程10:U2NET显著性检测实战2

&#x1f341;&#x1f341;&#x1f341;图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 U2NET显著性检测实战1 U2NET显著性检测实战2 U2NET显著性检测实战3 5、残差Unet模块 class RSU7(n…

【经验】VSCode连接远程服务器(可以使用git管理、方便查看和编辑Linux源码)

1、查看OpenSSH Windows10通常自带OpenSSH不需要安装。 Windows10下检查是否已经安装OpenSSH的方法: 1)按下快捷键Win + X,选择Windows PoweShell(管理员) 2)输入以下指令: Get-WindowsCapability -Online | ? Name -like ‘OpenSSH*’ 3)如果电脑未安装OpenSSH,…

全视通-医院智能视讯系统 病房视讯系统解决方案 智能医院对讲系统信息发布系统

医院智能视讯系统解决方案 1、行业背景 对于患者来说现阶段各大医院的住院部大都面临同样的问题&#xff0c;例如患者就医缺乏精准化医疗&#xff0c;缺乏对患者的心理健康引导&#xff0c;缺乏多维度沟通渠道&#xff0c;缺乏多元增值服务等。 对于传统医院住院部病房&am…

C# Attribute特性实战(1):Swtich判断优化

文章目录 前言简单Switch问题无参Swtich方法声明Swtich Attribute声明带有Swtich特性方法主方法结果 有参Switch修改代码修改运行过程运行结果 总结 前言 在经过前面两章内容的讲解&#xff0c;我们已经简单了解了如何使用特性和反射。我们这里解决一个简单的案例 C#高级语法 …

【Unity】如何在Unity中使用C#的NuGet 包资源

【背景】 Unity的脚本语言是C#&#xff0c;而C#有很多功能和能力可以通过nuget包提供。有没有办法把这些能力结合到Unity中一起使用呢&#xff1f;如果可以&#xff0c;那将大大扩展Unity中各类功能实现的便捷性。 【方法】 答案是&#xff1a;你可以&#xff01; 获取Nuge…

【数据库原理】(8)关系数据库的关系代数

关系数据语言可以分为三类: 关系代数、关系演算和介于关系代数与关系演算之间的语言 SQL。 下面专门讲述用对关系进行运算来表达查询要求的关系代数。关系代数的运算对象是关系&#xff0c;运算结果也是关系。关系代数用到的运算符包括四类:集合运算符、专门的关系运算符、算术…

Mac上安装 Node.js 的版本管理工具 n,以及 n 使用,的使用

安装 最近刚更换 Mac 本进行项目的开发&#xff0c;刚上手 Mac 本还不是很熟练&#xff0c;需要安装 Node.js 的包管理工具 在 Windows 上我是实用的 nvm 来管理的 Node 版本&#xff0c;但是我尝试下载 Nvm &#xff0c;发现下载安装后的 Nvm 无法使用&#xff0c;提示 “Th…

关于苹果iOS 16:揭开伪装成飞机模式的隐形蜂窝接入漏洞的动态情报

一、基本内容 在日常生活中&#xff0c;网络威胁不断演变&#xff0c;给个人和组织带来了一系列重大挑战。网络犯罪分子使用的一种最常见的、最具破坏性的方法之一就是网络钓鱼。这种攻击方式通过电子邮件、短信或其他通讯渠道冒充可信实体&#xff0c;诱使个人泄露敏感信息&am…