最终实现的效果展示
五子棋(ai版) 2024-01-14 15-28-35
目录
本次代码实现要具备easy图形库软件
五子棋目录
分为四个板块,分别为
棋盘、棋手、ai、游戏运行管理
ai
ai板块 ai.h
#pragma once
#include "Chess.h"
#include<vector>//这个是用c++写向量要的
//对ai的设置
//要进行初始化,就是要告诉他棋盘大小以及棋子种类这种
//ai的思想就是,计算每个落子的位置的价值,哪个好下哪个
class AI
{
public:
//初始化
void init(Chess *chess );
//下棋
void go();
private:
Chess* chess;
//int data[13][13];
vector<vector <int> > scoreMap; //
private:
void calculateScore();//评分
ChessPos think(); //ai思考
};
ai.cpp文件
#include "AI.h"
#include<vector>//这个是用c++写向量要的
//还有个跳三没处理
//AI的思考方式
/*
棋理格言:敌之好点,即我之好点。
就是说,每个点,都要考虑,如果敌方占领了这个点,会产生多大的价值,如果我方占领了这个点,又会产生多大的价值。
如果我方占领这个点,价值只有1000,但是敌方要是占领了这个点,价值有2000,而在自己在其它位置没有价值更高的点,
那么建议直接抢占这个敌方的好点。
*/
void AI::init(Chess* chess)
{
this->chess = chess;
//初始化二维数组
int size = 0; //这里错误,void不能转为int
size=chess->getqipansize(); //这里getqipansize没有值
for (int i = 0; i < 13; i++)//这里越界?
{
vector<int>row;
for (int j = 0; j < 13; j++)
{
row.push_back(0);
}
scoreMap.push_back(row); //搞明白这个row是和意义,好像是数组名吧对应上面那个
}
}
//ai下棋
void AI::go()
{
ChessPos pos = think();
//ai 太快了,弄一个时间
Sleep(1000);
chess->chessDown(&pos, chess_white);
}
//计算评分
void AI::calculateScore()
{
//棋手和ai分别有多少个连续的棋子
int personNum = 0;//玩家连成子的个数
int aiNum = 0;//ai连成子的个数
int emptyNum = 0; //该方向上空白位的个数
//先对评分向量数组清0,不道为啥,好像每次评分都要清,那清了我评啥
//for (int i = 0; i < scoreMap.size(); i++) //scoreMap.size()这个东西不道啥
//{
// for (int j = 0; j < scoreMap[i].size(); j++)
// {
// scoreMap[i][j] = 0;
// }
//}
//清空评分数组
for (int i = 0; i < 13; i++) //scoreMap.size()这个东西不道啥
{
for (int j = 0; j < 13; j++)
{
scoreMap[i][j] = 0;
}
}
//int size = chess->getqipansize();
//进行评分计算
//下面后进行优化,这就是数据结构的意义吧
int size = 13;
for (int row = 0; row < size; row++)
{
for (int col = 0; col < size; col++)
{
//每次要进行清0计算才可以
/*personNum = 0;
aiNum = 0;
emptyNum = 0;*/
//对每个点进行计算,前提是为空才计算。
if (chess->getChessData(row, col) == 0)
{
//负1为左边,正1为右边,0为本身位置
for (int y = -1; y <= 0; y++)
{
for (int x = -1; x <= 1; x++)
{
//八个方向改为4个方向
if (y == 0 && x == 0)
continue;
if (y == 0 && x != 1)
continue;
//每个方向都初始化
personNum = 0;
aiNum = 0;
emptyNum = 0; //该方向上空白位的个数
if (!(y == 0 && x == 0))
{
//假设黑棋在该位置落子,会构成什么棋型
//往前数四个
for (int i = 1; i <= 4; i++)
{
int courRow = row + i * y;
int courCol = col + i * x;
//判断是否有笑范围
if (courRow >= 0 && courRow < size && courCol >= 0 && courCol < size
&& chess->getChessData(courRow, courCol) == 1)
{
personNum++; //黑棋连续棋子加1
}
//碰到空白和白棋都跳出去重新换个方向计算
//空白
else if (courRow >= 0 && courRow < size && courCol >= 0 && courCol < size
&& chess->getChessData(courRow, courCol) == 0)
{
emptyNum++;
break;
}
//白棋
else
break;
}
//也要求反方向的棋子是否连续
for (int i = 1; i <= 4; i++)
{
int courRow = row - i * y;
int courCol = col - i * x;
//判断是否有笑范围
if (courRow >= 0 && courRow < size && courCol >= 0 && courCol < size
&& chess->getChessData(courRow, courCol) == 1)
{
personNum++; //黑棋连续棋子加1
}
//碰到空白和白棋都跳出去重新换个方向计算
//空白
else if (courRow >= 0 && courRow < size && courCol >= 0 && courCol < size
&& chess->getChessData(courRow, courCol) == 0)
{
emptyNum++;
break;
}
//白棋
else
break;
}
//上面计算好了棋型,下面进行评分
//连二状态
if (personNum == 1)
{
scoreMap[row][col] += 10; //连二给10分
}
//连三分为活三和死三
else if (personNum == 2)
{
if (emptyNum == 1) //一个空,说明是死三
{
scoreMap[row][col] += 30; //30分
}
else if (emptyNum == 2) //两个空,说明是活三
{
scoreMap[row][col] += 40;
}
}
//连四也分活四和死四
else if (personNum == 3)
{
if (emptyNum == 1) //一个空,说明是死四
{
scoreMap[row][col] += 60; //30分
}
else if (emptyNum == 2) //两个空,说明是活四
{
scoreMap[row][col] += 200;
}
}
//五子连珠
else if (personNum == 4)
{
scoreMap[row][col] = 20000;
}
//假设白棋在该位置落子,会构成什么棋型
//空白位置清0
emptyNum = 0;
//差不多的代码就能实现
for (int i = 1; i <= 4; i++)
{
int courRow = row + i * y;
int courCol = col + i * x;
//判断是否有笑范围
if (courRow > 0 && courRow < size && courCol > 0 && courCol < size
&& chess->getChessData(courRow, courCol) == -1)
{
aiNum++; //白棋连续棋子加1
}
//碰到空白和白棋都跳出去重新换个方向计算
//空白
else if (courRow > 0 && courRow < size && courCol > 0 && courCol < size
&& chess->getChessData(courRow, courCol) == 0)
{
emptyNum++;
break;
}
//黑棋
else
break;
}
//白棋切换方向
for (int i = 1; i <= 4; i++)
{
int courRow = row - i * y;
int courCol = col - i * x;
//判断是否有笑范围
if (courRow > 0 && courRow < size && courCol > 0 && courCol < size
&& chess->getChessData(courRow, courCol) == -1)
{
aiNum++; //白棋连续棋子加1
}
//碰到空白和白棋都跳出去重新换个方向计算
//空白
else if (courRow > 0 && courRow < size && courCol > 0 && courCol < size
&& chess->getChessData(courRow, courCol) == 0)
{
emptyNum++;
break;
}
//黑棋
else
break;
}
//判断白棋分数
//上面计算好了棋型,下面进行评分
if (aiNum == 0)
{
scoreMap[row][col] += 5; //连1给5分
}
//连二状态
else if (aiNum == 1)
{
scoreMap[row][col] += 10; //连二给10分
}
//连三分为活三和死三
else if (aiNum == 2)
{
if (emptyNum == 1) //一个空,说明是死三
{
scoreMap[row][col] += 25;
}
else if (emptyNum == 2) //两个空,说明是活三
{
scoreMap[row][col] += 50;
}
}
//连四也分活四和死四
else if (aiNum == 3)
{
if (emptyNum == 1) //一个空,说明是死四
{
scoreMap[row][col] += 55; //30分
}
else if (emptyNum == 2) //两个空,说明是活四
{
scoreMap[row][col] += 10000;
}
}
//五子连珠
else if (aiNum >= 4)
{
scoreMap[row][col] += 30000; //这里居然写了 ==号
}
}
}
}
}
}
}
}
//ai思考
ChessPos AI::think()
{
//计算平均分
calculateScore();
//printf("11\n");
/*int size = chess->getGradeSize();*/
//int size = chess->getqipansize(); //这个取值,不道为啥报错
//int size = scoreMap.size(); //这个取值,不道为啥报错
//防止出现有多个最大评分,那只能随机了
vector<ChessPos> maxPoints; //创建一个数组存放那个最大的评分多个
//搞半天原来是这个玩意搞坏了我的初始化,size
int size = 13;
int maxScore = 0;
//取最大的评分
for (int row = 0; row < size; row++)
{
for (int col = 0; col < size; col++)
{
if (chess->getChessData(row, col) == 0)
{
if (scoreMap[row][col] > maxScore)
{
maxScore = scoreMap[row][col];
maxPoints.clear(); //清空
maxPoints.push_back(ChessPos(row, col));
}
else if (scoreMap[row][col] == maxScore)
{
maxPoints.push_back(ChessPos(row, col));
}
}
}
}
int index = rand() % maxPoints.size(); //bug1,求余的为0;
return maxPoints[index]; //取得的最大的评分
}
棋手板块
man.h
#pragma once
#include"Chess.h"
#include<vector>//这个是用c++写向量要的
class Man
{
public:
//初始化
void init(Chess* chess);
//下棋
void go();
//为了调用棋盘,用指针指向,得到关系能调用就行
private:
Chess* chess;
};
man.cpp
#include "Man.h"
#include"Chess.h"
#include<vector>//这个是用c++写向量要的
//这个的初始化放在游戏控制那里进行
//这个错误很难受,居然没有那个:号就会错误
void Man::init(Chess* chess)
{
this->chess = chess;
}
//棋手下棋,鼠标点哪里我走哪里
void Man::go()
{
//定义鼠标变量
MOUSEMSG msg;
ChessPos pos;
//要解决不小心点到外面,或者点到格子里面
//通过chess对象,来调用判断落子是否有效,以及落子的功能
//检测是否左点击和范围是否有效
while (1)
{
//获取鼠标点击信息3
msg = GetMouseMsg();
//这里有问题
if (msg.uMsg == WM_LBUTTONDOWN && chess->clickBoard(msg.x,msg.y,&pos)) //这里不出选择,我很慌
{
/*printf("有效\n");*/
printf("%d,%d\n",msg.x,msg.y);
break;
}
}
printf("%d,%d\n", pos.row, pos.col);
//落子
chess->chessDown(&pos,chess_black );//黑棋掀开 kind种类
}
棋盘板块
chess.h
#pragma once
#include<graphics.h>
#include<vector>//这个是用c++写向量要的
using namespace std;//这叫命名空间
//先大概做好要实现什么 功能,后面再慢慢实现。
//棋子功能
//用来落子
//想到什么先写好什么
//表示落子的位置坐标
struct ChessPos {
int row;
int col;
ChessPos(int r=0 ,int c=0):row(r),col(c){} //这个是用在存放最大评分数组用的,不道啥意思
};
//定义棋子总类
typedef enum {
chess_white = -1,//白棋
chess_black = 1
}chess_kind; //kind总类 chess棋子
class Chess
{
//好像c++规定要写这个才能不会报错
//public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
//如果不加,好像mian会调用不了,属于私人,加了就可以所有对外调用
public:
//Chess(int gradSize, int marginX, int marginY, float chessSize);
Chess(int gradSize, int marginX, int marginY, int chessSize);
//初始化
void init();
//判断鼠标落子位置,然后符合的话返回坐标再落子
bool clickBoard(int x, int y, ChessPos* pos);//成功则保存到结构体pos里面
//实现落子
void chessDown(ChessPos *pos, chess_kind kind);//val ChessPos *pos这个应该是给结构体命名传参吧,后面可以直接引用
//获取棋盘大小
int getqipansize();
// 获取指定位置是黑棋,还是白棋,还是空白
int getChessData(ChessPos* pos);
int getChessData(int row, int col);
//检查棋局是否结束
bool checkover();
//开始弄资源图片的加载
//在棋盘类做好初始定义内容
private:
IMAGE chessBlackimg;//黑棋棋子
IMAGE chessWhiteimg;//白棋棋子
//定义棋盘的大小
int gradeSize;
//定义距离棋盘的大小宽度和长度
int margin_x;//棋盘的左侧边界
int margin_y;//棋盘的顶部边界 margin 范围,边缘
//定义棋子的大小
int chessSize;//棋子的大小(棋盘小方格的长宽跟棋子的直径一样大嘛)
//做一个数组存放已经落子的数据,就可以知道哪里不能下了
//c写法,但由于不能改变只能固定,然后就只能采用c++里面的可以改变的写法
//int chessMap[20][20]; //后面我要用c来改
//c++写法
//chessmap[3][5] 表示棋盘的第3行第五列的落子情况 0为空白,黑子为1,白字为-1
vector<vector<int>> chessMap;
//表示现在该谁下棋
bool playerFlag; //true 黑子走,false 白子走
void uppdateGameMap(ChessPos* pos);
bool chekWin(); //检查输赢,返回true为真,否则假
ChessPos lastPos; //最近落子点的位置
};
chess.cpp
#include "Chess.h"
#include<math.h>//求根号头文件
#include<graphics.h>
#include<conio.h>//暂停函数
#include<mmsystem.h>//音乐头文件
#pragma comment(lib,"winmm.lib")//音乐播放功能
//怎么播放一个音乐直到结束呢
//提升ai强大的方法就是
// 要对ai进行跳三跳四的判断
//再强大就是对黑棋进行禁手了
//解决图片背景透明化
void putimagePNG(int x, int y, IMAGE* picture) //x为载入图片的X坐标,y为Y坐标
{
// 变量初始化
DWORD* dst = GetImageBuffer(); // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带
DWORD* draw = GetImageBuffer();
DWORD* src = GetImageBuffer(picture); //获取picture的显存指针
int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带
int picture_height = picture->getheight(); //获取picture的高度,EASYX自带
int graphWidth = getwidth(); //获取绘图区的宽度,EASYX自带
int graphHeight = getheight(); //获取绘图区的高度,EASYX自带
int dstX = 0; //在显存里像素的角标
// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
for (int iy = 0; iy < picture_height; iy++)
{
for (int ix = 0; ix < picture_width; ix++)
{
int srcX = ix + iy * picture_width; //在显存里像素的角标
int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度
int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R
int sg = ((src[srcX] & 0xff00) >> 8); //G
int sb = src[srcX] & 0xff; //B
if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)
{
dstX = (ix + x) + (iy + y) * graphWidth; //在显存里像素的角标
int dr = ((dst[dstX] & 0xff0000) >> 16);
int dg = ((dst[dstX] & 0xff00) >> 8);
int db = dst[dstX] & 0xff;
draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr
| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg
| (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db
}
}
}
}
//初始化棋盘
Chess::Chess(int gradSize, int marginX, int marginY, int chessSize)
{
this->gradeSize = gradeSize;
this->margin_x = marginX;
this->margin_y = marginY;
this->chessSize = chessSize;
playerFlag = chess_black; //黑棋
//初始化数组
//真没看懂下面的操作
for (int i = 0; i < 13; i++)
{
//每次搞一行
vector<int>row; //这里创建一行,下面直接填充这一行数据为0
for (int j = 0; j < 13; j++)
{
row.push_back(0); //push_back() 在Vector最后添加一个元素(参数为要插入的值)
//相当于在弄数组的初始化,全部填充为0;
}
//在尾部追加一行,为啥呢作用,没太懂这行
chessMap.push_back(row);
}
}
IMAGE image1;
//在这里开始绘制游戏窗口界面
void Chess::init()
{
//创建游戏窗口
//这个的大小根据棋盘大小来创建
initgraph(897, 895,EW_SHOWCONSOLE); //graph 意思为图表 显示控制台
loadimage(0, "res/menu.png");
//586 754
//显示开始游戏
loadimage(&image1, "res/1.png");
putimage(611, 776, &image1);
MOUSEMSG msg;
while (1)
{
msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN)
{
//显示棋盘
//加载图片 scanf
loadimage(0, "res/棋盘2.jpg");
//播放游戏开始音乐,要加头文件
mciSendString("play res/start.wav", 0, 0, 0);
break;
}
}
//加载黑棋和白棋的图片到棋子变量里面存放好
//去边角才行,改为透明图片
loadimage(&chessBlackimg, "res/black.png",chessSize,chessSize,true);//在这里,棋子图片太大了83*83,所以加载进来的时候要跟方格的尺寸一样才行
loadimage(&chessWhiteimg, "res/white.png",chessSize,chessSize,true);
//给棋盘数组初始化清空
//这里数组为0
/*for (int i = 0; i < gradeSize; i++)
{
for (int j = 0; j < gradeSize; j++)
{
chessMap[i][j] = 0;
}
}*/
//给棋盘数组初始化清空
//这里数组为0
for (int i = 0; i < 13; i++)
{
for (int j = 0; j < 13; j++)
{
chessMap[i][j] = 0;
}
}
//定义棋子一开始为黑棋
playerFlag = true;//
}
//这里判断有效点击,x,y为鼠标点的坐标
bool Chess::clickBoard(int x, int y, ChessPos* pos)
{
//先求鼠标在的行和列数
//思路画图,就可以知道,x长度减去边界长度,然后除以格子的长度就可以知道x的坐标了
//类型记得用int 这样就会取整
int col = (x - margin_x) / chessSize;//列数
int row = (y - margin_y) / chessSize;//行数
//求左上角的坐标
int leftTopPosX = margin_x + chessSize * col;
int leftTopPosY = margin_y + chessSize * row;
//设置一个误差,就是不小心点到方格里面偏离了一些,这个参数
int offset = chessSize * 0.5; //我取一半吧
//求鼠标的坐标的位置离中心的距离
//int len; //这个要开根号,我觉得为了精确要改为float 或者double吧
int len;
//len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY)); //直角三角形里面的求斜边玩法
//这里用int?
int ret = false;
//bool ret = false; //在这里设置一个标志
//下面的就是进行判断,他在哪个中心
//拿误差来比较
//得出准确的落棋位置
//在这个之后要提前知道是否为空,若有棋子就不用下棋了
//要判断他要落子在四个角是哪个角
do
{
//这个居然放在里面
len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY)); //直角三角形里面的求斜边玩法
if (len < offset)
{
pos->row = row;
pos->col = col;
if (chessMap[pos->row][pos->col] == 0)
{
ret = true;
}
break;
}
//右上角判断
int x2 = leftTopPosX + chessSize;
int y2 = leftTopPosY;
len = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
if (len < offset)
{
pos->row = row;
pos->col = col+1; //行不变,列要加1
if (chessMap[pos->row][pos->col] == 0)
{
ret = true;
}
break;
}
//左下角判断
x2 = leftTopPosX ;
y2 = leftTopPosY + chessSize;
len = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
if (len < offset)
{
pos->row = row+1 ;//列不变,行要加1
pos->col = col;
if (chessMap[pos->row][pos->col] == 0)
{
ret = true;
}
break;
}
//右下角判断
x2 = leftTopPosX + chessSize;
y2 = leftTopPosY + chessSize;
len = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
if (len < offset)
{
pos->row = row + 1;//列不变,行要加1
pos->col = col + 1;
if (chessMap[pos->row][pos->col] == 0)
{
ret = true;
}
break;
}
} while (0);
return ret;
}
//下棋他来了
//终于知道一个bug玩法了
//就是绘制棋子的坐标时候不能写中心坐标呀,因为绘制的话是从左上角坐标绘制的
//所以呢,我要写的坐标,写的是本来的坐标减去半个方格的长度,宽度也是。
void Chess::chessDown(ChessPos* pos, chess_kind kind)
{
mciSendString("play res/down7.WAV", 0, 0, 0);
int x = (margin_x + chessSize * pos->col) - (0.5 * chessSize);
int y = (margin_y + chessSize * pos->row) - (0.5 * chessSize);
if (kind == chess_white)
{
putimagePNG(x, y, &chessWhiteimg); //输出棋子
}
else
{
//putimage(x, y, &chessBlackimg);
putimagePNG(x, y, &chessBlackimg);
}
//放入更新函数
uppdateGameMap(pos);
}
int Chess::getChessData(ChessPos* pos)
{
return chessMap[pos->row][pos->col];
}
int Chess::getChessData(int row, int col)
{
return chessMap[row][col];
}
//棋盘大小
int Chess::getqipansize()
{
return gradeSize;
}
//判断是否结束
bool Chess::checkover()
{
//输赢要显示出
// printf("11");
if (chekWin()== true)
{
Sleep(2000);
if (playerFlag == false)
{
//false说明最后一步是棋手,也就是胜利者
mciSendString("play res/不错.mp3", 0, 0, 0);
loadimage(0, "res/胜利.jpg");
MessageBox(GetHWnd(), "你赢了", "温馨提醒", MB_OK);//消息盒子,对话框函数
Sleep(500);
//mciSendString("play ./稻香 - 周杰伦.320.mp3", NULL, 0, NULL);
}
else
{
//false说明最后一步是棋手,也就是胜利者
mciSendString("play res/失败.mp3", 0, 0, 0);
loadimage(0, "res/失败.jpg");
MessageBox(GetHWnd(), "你输了", "温馨提醒", MB_OK);//消息盒子,对话框函数
Sleep(500);
//mciSendString("play ./稻香 - 周杰伦.320.mp3", NULL, 0, NULL);
}
//暂停键
//_getch(); //按任意键
return true;
}
//暂停键
// _getch(); //按任意键
return false;
}
//每次更改棋盘的数据
void Chess::uppdateGameMap(ChessPos* pos)
{
lastPos = *pos; //获取最新的落子位置
chessMap[pos->row][pos->col] = playerFlag ? chess_black : chess_white; //三目运算符
playerFlag = !playerFlag; //棋子的切换
}
//判断五子连珠
bool Chess::chekWin()
{
//判断落子点的周围四个方向即可
//落子坐标
int row = lastPos.row;
int col = lastPos.col;
//落子点的水平方向
for (int i = 0; i < 5; i++)
{
//最左到最有往右移动
//要注意防止越界
if (col - i >= 0 && col - i + 4 < 13 &&
chessMap[row][col - i] == chessMap[row][col - i + 1] &&
chessMap[row][col - i] == chessMap[row][col - i + 2] &&
chessMap[row][col - i] == chessMap[row][col - i + 3] &&
chessMap[row][col - i] == chessMap[row][col - i + 4] )
{
return true;
}
}
//落子点的垂直方向
for (int i = 0; i < 5; i++)
{
//最左到最有往右移动
//要注意防止越界
if (row - i >= 0 && row - i + 4 < 13 &&
chessMap[row-i][col] == chessMap[row - i + 1][col ] &&
chessMap[row - i][col] == chessMap[row - i + 2][col] &&
chessMap[row - i][col] == chessMap[row - i + 3][col] &&
chessMap[row - i][col] == chessMap[row - i + 4][col] )
{
return true;
}
}
//左下方到右上方 /
for (int i = 0; i < 5; i++)
{
if (row + i < 13 && row + i - 4 >= 0 &&
col - i >= 0 && col - i + 4 < 13 &&
chessMap[row + i][col - i] == chessMap[row + i - 1][col - i + 1] &&
chessMap[row + i][col - i] == chessMap[row + i - 2][col - i + 2] &&
chessMap[row + i][col - i] == chessMap[row + i - 3][col - i + 3] &&
chessMap[row + i][col - i] == chessMap[row + i - 4][col - i + 4])
{
return true;
}
}
//这里有问题
//'\'下方到右上方
for (int i = 0; i < 5; i++)
{
if (col - i >= 0 && row - i + 4 < 13 &&
row - i >= 0 && col - i + 4 < 13 &&
chessMap[row - i][col - i] == chessMap[row - i + 1][col - i + 1] &&
chessMap[row - i][col - i] == chessMap[row - i + 2][col - i + 2] &&
chessMap[row - i][col - i] == chessMap[row - i + 3][col - i + 3] &&
chessMap[row - i][col - i] == chessMap[row - i + 4][col - i + 4])
{
return true;
}
}
return false;
}
游戏控制管理板块
chessgame.h
#pragma once
#include"AI.h"
#include"Chess.h"
#include"Man.h"
#include<vector>//这个是用c++写向量要的
//游戏控制
class ChessGame
{
public:
//开始对局这个不同
ChessGame(Man *man,AI *ai,Chess *chess);
void play();//有一把刷子按住ctrl可以进行创建,就可以方便切换了
//private表示私有,私有的意思就是除了class自己之外
//任何人都不可以直接使用,私有财产神圣不可侵犯嘛,即便是子女,朋友,都不可以使用。
//添加数据成员
//下面这些定义好像跟结构体差不多
private:
Man* man;
AI* ai;
Chess* chess;
};
chessgame.cpp
#include "ChessGame.h"
#include<vector>//这个是用c++写向量要的
ChessGame::ChessGame(Man* man, AI* ai, Chess* chess)
{
//this是一个变量 ,一个引用。
//this保存的就是当前对象的地址,指向对象本身,即this代表的就是“当前对象”。
//初始化
this->man = man;
this->ai = ai;
this->chess= chess;
man->init(chess);
ai->init(chess);
}
//对局开始(开始玩)
void ChessGame::play()
{
//下之前要对游戏界面棋盘啥的资源加载初始化
chess->init();
//思路
//先确定谁先走,人先走,电脑后
//走一步判断一步是否结束
//如果结束了那就继续下一把
while (1)
{
//棋手走
man->go();
//判断是否结束
if (chess->checkover())
{
printf("11\n");
chess->init();//如果结束那就重新初始化。这个初始化每次也需要把存棋子的数组给初始化
continue;//这个意思就是如果结束了然后返回去继续玩。
}
//这里就断了
//ai走
ai->go(); //ai挂了跑不起来
//printf("电脑你快下,不下就是挂了\n");
//判断是否结束
if (chess->checkover())
{
//system("pause");
chess->init();
continue;
}
}
}
到此就结束了,有问题可以留言哈。