目录
1,功能介绍
2,功能展示
3,项目代码
1,功能介绍
1,类的创建和使用
2,接口设置
3,棋盘类成员的设计
4,棋盘初始化
5,棋手下棋
6,判断棋手的点击位置
7,实现棋盘落子
8,AI的初始化
9,AI走棋
10,胜负判断
2,功能展示

3,项目代码
AI.h
#pragma once #include "Chess.h" class AI { public: void init(Chess* chess); void go(); private: Chess* chess; vector<vector<int>> scoreMap; private: void calculateScore(); ChessPos think(); };
讯享网
Chess.h
讯享网#pragma once #include <graphics.h> //easux图形库的头文件 //准备:下载easyx图形库 #include <vector> 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_t; class Chess { public: Chess(int gradeSize, int marginX, int marginY, float chessSize); //棋盘的初始化:加载棋盘的图片资源,初始化棋盘的相关数据 void init(); //判断在指定坐标(x,y)位置,是否是有效点击 //如果是有效点击,把有效点击的位置保存在参数pos中 bool clickBoard(int x, int y, ChessPos*pos); //在棋盘的指定位置(pos),落子(kind) void chessDown(ChessPos *pos, chess_kind_t kind); //获取棋盘的大小(13,15,17,19) int getGradeSize(); //获取其指定位置是黑棋,还是白棋,还是空白 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; //棋盘的顶部边界 float chessSize; //棋子的大小(棋盘小方格的大小) //存储当前棋局的棋子分布数据 // chessMap[3][5]表示棋盘的第三行第五列的落子情况 0:空白 1:黑子 -1:白子 vector<vector<int>>chessMap; //via哦是现在该谁下棋(落子) bool playerFlag; //true 黑子走 false 白子走 void updateGameMap(ChessPos* pos); bool checkWin(); ChessPos lastPos; };
ChessGame.h
#pragma once #include "AI.h" #include "Chess.h" #include "Man.h" class ChessGame { public: ChessGame(Man* man, AI* ai, Chess* chess); void play(); //开始对局 //添加数据成员 private: Man* man; AI* ai; Chess* chess; };
Man.h
讯享网#pragma once #include "Chess.h" class Man { public: void init(Chess* chess); void go(); private: Chess *chess; };
AI.cpp
#include "AI.h" void AI::init(Chess* chess) { this->chess = chess; int size = chess->getGradeSize(); for (int i = 0; i < size; i++) { vector<int>row; for (int j = 0; j < size; j++) { row.push_back(0); } scoreMap.push_back(row); } } void AI::go() { ChessPos pos = think(); Sleep(1000); chess->chessDown(&pos, CHESS_WHITE); } void AI::calculateScore() { int personNum = 0; //棋手方(黑棋)多少个连续的棋子 int aiNum = 0; //AI方(白棋)连续有多少个连续的棋子 int emptyNum = 0; // 该方向上空白位的个数 // 评分向量数组清零 for (int i = 0; i < scoreMap.size(); i++) { for (int j = 0; j < scoreMap[i].size(); j++) { scoreMap[i][j] = 0; } } int size = chess->getGradeSize(); for (int row = 0; row < size; row++) { for (int col = 0; col < size; col++) { //对每个点进行计算 if (chess->getChessData(row, col)) continue; for (int y = -1; y <= 0; y++) { //Y的范围还是-1, 0 for (int x = -1; x <= 1; x++) { //X的范围是 -1,0,1 if (y == 0 && x == 0) continue; if (y == 0 && x != 1) continue; //当y=0时,仅允许x=1 personNum = 0; aiNum = 0; emptyNum = 0; // 假设黑棋在该位置落子,会构成什么棋型 for (int i = 1; i <= 4; i++) { int curRow = row + i * y; int curCol = col + i * x; if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == 1) { personNum++; } else if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == 0) { emptyNum++; break; } else { break; } } // 反向继续计算 for (int i = 1; i <= 4; i++) { int curRow = row - i * y; int curCol = col - i * x; if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == 1) { personNum++; } else if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == 0) { emptyNum++; break; } else { break; } } if (personNum == 1) { //连2 //CSDN 程序员Rock scoreMap[row][col] += 10; } else if (personNum == 2) { if (emptyNum == 1) { scoreMap[row][col] += 30; } else if (emptyNum == 2) { scoreMap[row][col] += 40; } } else if (personNum == 3) { if (emptyNum == 1) { scoreMap[row][col] = 60; } else if (emptyNum == 2) { scoreMap[row][col] = 5000; //200 } } else if (personNum == 4) { scoreMap[row][col] = 20000; } // 假设白棋在该位置落子,会构成什么棋型 emptyNum = 0; for (int i = 1; i <= 4; i++) { int curRow = row + i * y; int curCol = col + i * x; if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == -1) { aiNum++; } else if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == 0) { emptyNum++; break; } else { break; } } for (int i = 1; i <= 4; i++) { int curRow = row - i * y; int curCol = col - i * x; if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == -1) { aiNum++; } else if (curRow >= 0 && curRow < size && curCol >= 0 && curCol < size && chess->getChessData(curRow, curCol) == 0) { emptyNum++; break; } else { break; } } if (aiNum == 0) { scoreMap[row][col] += 5; } else if (aiNum == 1) { scoreMap[row][col] += 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; } else if (emptyNum == 2) { scoreMap[row][col] += 10000; } } else if (aiNum >= 4) { scoreMap[row][col] += 30000; } } } } } } ChessPos AI::think() { calculateScore(); vector<ChessPos>maxPoints; int maxScore = 0; int size = chess->getGradeSize(); 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(); return maxPoints[index]; }
Chess.cpp
讯享网#include <math.h> #include "Chess.h" #include <mmsystem.h> #include<conio.h> #pragma comment(lib,"winmm.lib") 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 gradeSize, int marginX, int marginY, float chessSize) { this->gradeSize = gradeSize; this->margin_x = marginX; this->margin_y = marginY; this->chessSize = chessSize; playerFlag = CHESS_BLACK; for (int i = 0; i < gradeSize; i++) { vector<int>row; for (int j = 0; j < gradeSize; j++) { row.push_back(0); } chessMap.push_back(row); } } void Chess::init() { //创建游戏窗口 initgraph(897, 895); // EX_SHOWCONSOLE //显示棋盘图片 loadimage(0, "res/棋盘2.jpg"); //播放开始提示音 mciSendString("play res/start.wav", 0, 0, 0); //加载黑棋和白棋棋子的图片 loadimage(&chessBlackImg, "res/black.png",chessSize,chessSize,true); loadimage(&chessWhiteImg, "res/white.png",chessSize,chessSize,true); //棋盘清零 for (int i = 0; i < chessMap.size(); i++) { for (int j = 0; j < gradeSize; j++) { chessMap[i][j] = 0; } } playerFlag = true; } bool Chess::clickBoard(int x, int y, ChessPos* pos) { 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.4; int len; 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; 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; 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; pos->col = col + 1; if (chessMap[pos->row][pos->col] == 0) { ret = true; } break; } } while (0); return ret; } void Chess::chessDown(ChessPos* pos, chess_kind_t 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 { putimagePNG(x, y, &chessBlackImg); } updateGameMap(pos); } int Chess::getGradeSize() { return gradeSize; } int Chess::getChessData(ChessPos* pos) { return chessMap[pos-> row][pos->col]; } int Chess::getChessData(int row, int col) { return chessMap[row][col]; } bool Chess::checkOver() { if (checkWin()) { Sleep(1500); if (playerFlag == false) { mciSendString("play res/不错.mp3", 0, 0, 0); loadimage(0, "res/胜利.jpg"); } else { mciSendString("play res/失败.mp3", 0, 0, 0); loadimage(0, "res/失败.jpg"); } _getch(); return true; } return false; } void Chess::updateGameMap(ChessPos* pos) { lastPos = *pos; chessMap[pos->row][pos->col] = playerFlag ? CHESS_BLACK : CHESS_WHITE; playerFlag = !playerFlag; //黑白方交换行棋 } bool Chess::checkWin() { // 横竖斜四种大情况,每种情况都根据当前落子往后遍历5个棋子,有一种符合就算赢 // 水平方向 int row = lastPos.row; int col = lastPos.col; for (int i = 0; i < 5; i++) { // 往左5个,往右匹配4个子,20种情况 if (col - i >= 0 && col - i + 4 < gradeSize && 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; } // 竖直方向(上下延伸4个) for (int i = 0; i < 5; i++) { if (row - i >= 0 && row - i + 4 < gradeSize && 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 < gradeSize && row + i - 4 >= 0 && col - i >= 0 && col - i + 4 < gradeSize && // 第[row+i]行,第[col-i]的棋子,与右上方连续4个棋子都相同 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++) { // 第[row+i]行,第[col-i]的棋子,与右下方连续4个棋子都相同 if (row - i >= 0 && row - i + 4 < gradeSize && col - i >= 0 && col - i + 4 < gradeSize && 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.cpp
#include "ChessGame.h" ChessGame::ChessGame(Man* man, AI* ai, Chess* chess) { 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()) { chess->init(); continue; } //由AI走 ai->go(); if (chess->checkOver()) { chess->init(); continue; } } }
Man.cpp
讯享网#include "Man.h" void Man::init(Chess* chess) { this->chess = chess; } void Man::go() { MOUSEMSG msg; ChessPos pos; //通过chess对象来判断落子是否有效,以及落子功能 while (1) { //获取鼠标点击消息 msg = GetMouseMsg(); if (msg.uMsg == WM_LBUTTONDOWN && chess->clickBoard(msg.x, msg.y, &pos)) { break; } } //printf("%d,%d\n", pos.row, pos.col); //落子 chess->chessDown(&pos, CHESS_BLACK); }
执行文件
#include<iostream> #include "ChessGame.h" int main() { Man man; //Chess chess; Chess chess(13, 44, 43, 67.3); AI ai; ChessGame game(&man, &ai, &chess); game.play(); return 0; }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/74268.html