五子棋入门图解,五子棋入门步骤图走法

首页 > 生活 > 作者:YD1662022-12-29 08:15:23

AI走棋原理

计算每个合法的落子点的“权值”,然后再权值最大的点落子

以后,可以在这个基础之上,实现多个层次的计算.

对于每个空白点,分别计算周围的八个方向

五子棋入门图解,五子棋入门步骤图走法(21)

因为在计算某个方向时,正向和反向需同时考虑,所以实际上只需计算4个方向即可:

五子棋入门图解,五子棋入门步骤图走法(22)

如果黑棋走这个点

产生效果

评分

连2

10

死3

30

活3

40

死4

60

活4

200

连5

20000

如果白棋AI走这个点

产生效果

评分

连1(普通)

5

连2

10

死3

25

活3

50

死4

55

活4

300

连5

30000

计算各点的“权值”

权值的计算,放在ChessData模块中。

ChessData.h

void calculateScore(ChessData* data);

ChessData.cpp

#include <string.h> //memset函数 // 最关键的计算评分函数 void calculateScore(ChessData* data) { if (!data) return; // 统计玩家或者电脑连成的子 int personNum = 0; // 玩家连成子的个数 int botNum = 0; // AI连成子的个数 int emptyNum = 0; // 各方向空白位的个数 // 清空评分数组 memset(data->scoreMap, 0, sizeof(data->scoreMap)); for (int row = 0; row < BOARD_GRAD_SIZE; row ) for (int col = 0; col < BOARD_GRAD_SIZE; col ) { // 空白点就算 if (row >= 0 && col >= 0 && data->chessMap[row][col] == 0) { // 遍历周围4个方向,分别计算正反两个方向 int directs[4][2] = { {1,0}, {1,1}, {0,1}, {-1,1 } }; for (int k = 0; k < 4; k ) { int x = directs[k][0]; int y = directs[k][1]; // 重置 personNum = 0; botNum = 0; emptyNum = 0; // 对黑棋评分(正向) for (int i = 1; i <= 4; i ) { if (row i * y >= 0 && row i * y < BOARD_GRAD_SIZE && col i * x >= 0 && col i * x < BOARD_GRAD_SIZE && data->chessMap[row i * y][col i * x] == 1) { // 真人玩家的子 personNum ; } else if (row i * y >= 0 && row i * y < BOARD_GRAD_SIZE && col i * x >= 0 && col i * x < BOARD_GRAD_SIZE && data->chessMap[row i * y][col i * x] == 0) { // 空白位 emptyNum ; break; // 遇到空白位置,停止该方向的搜索 } else // 出边界,或者遇到白棋,就停止该方向的搜索 break; } // 对黑棋评分(反向) for (int i = 1; i <= 4; i ) { if (row - i * y >= 0 && row - i * y < BOARD_GRAD_SIZE && col - i * x >= 0 && col - i * x < BOARD_GRAD_SIZE && data->chessMap[row - i * y][col - i * x] == 1) { // 玩家的子 personNum ; } else if (row - i * y >= 0 && row - i * y < BOARD_GRAD_SIZE && col - i * x >= 0 && col - i * x < BOARD_GRAD_SIZE && data->chessMap[row - i * y][col - i * x] == 0) { // 空白位 emptyNum ; break; } else // 出边界,或者有AI自己的棋子 break; } if (personNum == 1) // *二 data->scoreMap[row][col] = 10; else if (personNum == 2) { // *三 if (emptyNum == 1) // 死三 data->scoreMap[row][col] = 30; else if (emptyNum == 2) // 活三 data->scoreMap[row][col] = 40; } else if (personNum == 3) { // *四 if (emptyNum == 1) //死四 data->scoreMap[row][col] = 60; else if (emptyNum == 2) //活四 data->scoreMap[row][col] = 200; } else if (personNum == 4) // *五 data->scoreMap[row][col] = 20000; // 进行一次清空 emptyNum = 0; // 对白棋评分(正向) for (int i = 1; i <= 4; i ) { if (row i * y > 0 && row i * y < BOARD_GRAD_SIZE && col i * x > 0 && col i * x < BOARD_GRAD_SIZE && data->chessMap[row i * y][col i * x] == -1) { // 玩家的子 botNum ; } else if (row i * y > 0 && row i * y < BOARD_GRAD_SIZE && col i * x > 0 && col i * x < BOARD_GRAD_SIZE && data->chessMap[row i * y][col i * x] == 0) { // 空白位 emptyNum ; break; } else break; } // 对白棋评分(反向) for (int i = 1; i <= 4; i ) { if (row - i * y > 0 && row - i * y < BOARD_GRAD_SIZE && col - i * x > 0 && col - i * x < BOARD_GRAD_SIZE && data->chessMap[row - i * y][col - i * x] == -1) { // AI的子 botNum ; } else if (row - i * y > 0 && row - i * y < BOARD_GRAD_SIZE && col - i * x > 0 && col - i * x < BOARD_GRAD_SIZE && data->chessMap[row - i * y][col - i * x] == 0) { // 空白位 emptyNum ; break; } else // 出边界 break; } if (botNum == 0) // 普通下子 data->scoreMap[row][col] = 5; else if (botNum == 1) // 活二 data->scoreMap[row][col] = 10; else if (botNum == 2) { if (emptyNum == 1) // 死三 data->scoreMap[row][col] = 25; else if (emptyNum == 2) data->scoreMap[row][col] = 50; // 活三 } else if (botNum == 3) { if (emptyNum == 1) // 死四 data->scoreMap[row][col] = 55; else if (emptyNum == 2) data->scoreMap[row][col] = 300; // 活四 } else if (botNum >= 4) data->scoreMap[row][col] = 30000; // 活五,应该具有最高优先级 } } } }AI思考落子点

在各落子点,找到分值最大的点。如果有多个分值相同的点,直接在其中取一个随机点。

在ChesssData模块实现。

ChessData.h

typedef struct point { int row; int col; } point_t; point_t actionByAI(ChessData* data); // 机器执行下棋

ChessData.cpp

#include <time.h> #include <stdlib.h> point_t actionByAI(ChessData *data) { // 计算评分 calculateScore(data); // 从评分中找出最大分数的位置 int maxScore = 0; //std::vector<std::pair<int, int>> maxPoints; point_t maxPoints[BOARD_GRAD_SIZE * BOARD_GRAD_SIZE] = { 0, }; int k=0; for (int row = 0; row < BOARD_GRAD_SIZE; row ) for (int col = 0; col < BOARD_GRAD_SIZE; col ) { // 前提是这个坐标是空的 if (data->chessMap[row][col] == 0) { if (data->scoreMap[row][col] > maxScore) // 找最大的数和坐标 { //maxPoints.clear(); memset(maxPoints, 0, sizeof(maxPoints)); k = 0; maxScore = data->scoreMap[row][col]; //maxPoints.push_back(std::make_pair(row, col)); maxPoints[k].row = row; maxPoints[k].col = col; k ; } else if (data->scoreMap[row][col] == maxScore) { // 如果有多个最大的数,都存起来 //maxPoints.push_back(std::make_pair(row, col)); maxPoints[k].row = row; maxPoints[k].col = col; k ; } } } // 随机落子,如果有多个点的话 srand((unsigned)time(0)); int index = rand() % k; return maxPoints[index]; }实现AI落子

void AI_GO() { //AI走棋 point_t point = actionByAI(&game); clickPosRow = point.row; clickPosCol = point.col; Sleep(1000); //AI计算的太快,此处以假装思考 chessDown(clickPosRow, clickPosCol, CHESS_WHITE); updateGameMap(&game, clickPosRow, clickPosCol); }11.判断棋局是否结束在ChessData模块定义判断输赢的接口

原理分析:

在4个方向上搜索。

五子棋入门图解,五子棋入门步骤图走法(23)

以右下方向为例:(黑色棋子表示刚下的棋子)

从当前棋子开始,向右下方数5个

五子棋入门图解,五子棋入门步骤图走法(24)

上一页23456下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.