这次来讲一讲我才很久以前编的一个project——五子棋AI(刚从我的U盘里翻出来)
实际上我还是可以下赢这个AI的,因为这个AI不会下三三、三四这样的棋(不懂的可以去网上搜一搜,很好理解),也有一些奇奇怪怪的bug。
主要思路就是用dfs给每个没有下棋的点进行评分,从进攻、防守两个方面进行评分,看四周的棋子的数量,周围对方或自己的棋子连得越长,评分就越高,再把棋下在评分最高的位置。
那就直接上代码吧
#include <conio.h>
#include <windows.h>
#include <ctime>
#include <iostream>
const int MAXSIZE = 14;
char chessBoard[MAXSIZE][MAXSIZE];
namespace AI {
char ai1, ai2;
int b[MAXSIZE][MAXSIZE] = {0};
#define random(m, n) rand() % (n - m + 1) + m
void setplayer1(int &s, int &ps, int step = 2) {
ps += step;
if (ps == 2) s += 11;
if (ps == 3) s += 21;
if (ps == 4) s += 51;
if (ps == 5) s += 71;
if (ps == 6) s += 101;
if (ps == 7) s += 201;
if (ps == 8) s += 2001;
if (ps == 10) s += 10001;
}
void setplayer2(int &s, int &ps, int step = 2) {
ps += step;
if (ps == 2) s += 10;
if (ps == 3) s += 20;
if (ps == 4) s += 50;
if (ps == 5) s += 70;
if (ps == 6) s += 100;
if (ps == 7) s += 200;
if (ps == 8) s += 1000;
if (ps == 10) s += 10000;
}
void point(int &s, int x, int y, int player, int dir, int ps) {
int oldps;
if (dir == 0) {
if (x + 1 < MAXSIZE && chessBoard[x + 1][y] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x + 1, y, 2, 1, ps);
ps = oldps;
}
if (y + 1 < MAXSIZE && chessBoard[x][y + 1] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x, y + 1, 2, 2, ps);
ps = oldps;
}
if (x - 1 > 0 && chessBoard[x - 1][y] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x - 1, y, 2, 3, ps);
ps = oldps;
}
if (y - 1 > 0 && chessBoard[x][y - 1] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x, y - 1, 2, 4, ps);
ps = oldps;
}
if (x + 1 < MAXSIZE && y + 1 < MAXSIZE &&
chessBoard[x + 1][y + 1] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x + 1, y + 1, 2, 5, ps);
ps = oldps;
}
if (x - 1 > 0 && y - 1 > 0 && chessBoard[x - 1][y - 1] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x - 1, y - 1, 2, 6, ps);
ps = oldps;
}
if (x + 1 < MAXSIZE && y - 1 > 0 && chessBoard[x + 1][y - 1] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x + 1, y - 1, 2, 7, ps);
ps = oldps;
}
if (y + 1 < MAXSIZE && x - 1 > 0 && chessBoard[x - 1][y + 1] == 'O') {
oldps = ps;
setplayer2(s, ps);
point(s, x - 1, y + 1, 2, 8, ps);
ps = oldps;
} //连自己
if (x + 1 < MAXSIZE && chessBoard[x + 1][y] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x + 1, y, 1, 1, ps);
ps = oldps;
}
if (y + 1 < MAXSIZE && chessBoard[x][y + 1] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x, y + 1, 1, 2, ps);
ps = oldps;
}
if (x - 1 > 0 && chessBoard[x - 1][y] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x - 1, y, 1, 3, ps);
ps = oldps;
}
if (y - 1 > 0 && chessBoard[x][y - 1] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x, y - 1, 1, 4, ps);
ps = oldps;
}
if (x + 1 < MAXSIZE && y + 1 < MAXSIZE &&
chessBoard[x + 1][y + 1] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x + 1, y + 1, 1, 5, ps);
ps = oldps;
}
if (x - 1 > 0 && y - 1 > 0 && chessBoard[x - 1][y - 1] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x - 1, y - 1, 1, 6, ps);
ps = oldps;
}
if (x + 1 < MAXSIZE && y - 1 > 0 && chessBoard[x + 1][y - 1] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x + 1, y - 1, 1, 7, ps);
ps = oldps;
}
if (y + 1 < MAXSIZE && x - 1 > 0 && chessBoard[x - 1][y + 1] == 'X') {
oldps = ps;
setplayer1(s, ps);
point(s, x - 1, y + 1, 1, 8, ps);
ps = oldps;
} //防守
}
if (player == 2) //进攻
{
if (x + 1 < MAXSIZE && chessBoard[x + 1][y] != 'X' && dir == 1) {
oldps = ps;
if (chessBoard[x + 1][y] == 'O') {
setplayer2(s, ps);
point(s, x + 1, y, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x + 1, y, player, dir, ps);
}
ps = oldps;
}
if (y + 1 < MAXSIZE && chessBoard[x][y + 1] != 'X' && dir == 2) {
oldps = ps;
if (chessBoard[x][y + 1] == 'O') {
setplayer2(s, ps);
point(s, x, y + 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x, y + 1, player, dir, ps);
}
ps = oldps;
}
if (x - 1 > 0 && chessBoard[x - 1][y] != 'X' && dir == 3) {
oldps = ps;
if (chessBoard[x - 1][y] == 'O') {
setplayer2(s, ps);
point(s, x - 1, y, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x - 1, y, player, dir, ps);
}
ps = oldps;
}
if (y - 1 > 0 && chessBoard[x][y - 1] != 'X' && dir == 4) {
oldps = ps;
if (chessBoard[x][y - 1] == 'O') {
setplayer2(s, ps);
point(s, x, y - 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x, y - 1, player, dir, ps);
}
ps = oldps;
}
if (x + 1 < MAXSIZE && y + 1 < MAXSIZE &&
chessBoard[x + 1][y + 1] != 'X' && dir == 5) {
oldps = ps;
if (chessBoard[x + 1][y + 1] == 'O') {
setplayer2(s, ps);
point(s, x + 1, y + 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x + 1, y + 1, player, dir, ps);
}
ps = oldps;
}
if (x - 1 > 0 && y - 1 > 0 && chessBoard[x - 1][y - 1] != 'X' &&
dir == 6) {
oldps = ps;
if (chessBoard[x - 1][y - 1] == 'O') {
setplayer2(s, ps);
point(s, x - 1, y - 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x - 1, y - 1, player, dir, ps);
}
ps = oldps;
}
if (x + 1 < MAXSIZE && y - 1 > 0 && chessBoard[x + 1][y - 1] != 'X' &&
dir == 7) {
oldps = ps;
if (chessBoard[x + 1][y - 1] == 'O') {
setplayer2(s, ps);
point(s, x + 1, y - 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x + 1, y - 1, player, dir, ps);
}
ps = oldps;
}
if (y + 1 < MAXSIZE && x - 1 > 0 && chessBoard[x - 1][y + 1] != 'X' &&
dir == 8) {
oldps = ps;
if (chessBoard[x - 1][y + 1] == 'O') {
setplayer2(s, ps);
point(s, x - 1, y + 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer2(s, ps, 1);
point(s, x - 1, y + 1, player, dir, ps);
}
ps = oldps;
}
} else if (player == 1) //防守
{
if (x + 1 < MAXSIZE && chessBoard[x + 1][y] != 'O' && dir == 1) {
oldps = ps;
if (chessBoard[x + 1][y] == 'X') {
setplayer1(s, ps);
point(s, x + 1, y, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x + 1, y, player, dir, ps);
}
ps = oldps;
}
if (y + 1 < MAXSIZE && chessBoard[x][y + 1] != 'O' && dir == 2) {
oldps = ps;
if (chessBoard[x][y + 1] == 'X') {
setplayer1(s, ps);
point(s, x, y + 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x, y + 1, player, dir, ps);
}
ps = oldps;
}
if (x - 1 > 0 && chessBoard[x - 1][y] != 'O' && dir == 3) {
oldps = ps;
if (chessBoard[x - 1][y] == 'X') {
setplayer1(s, ps);
point(s, x - 1, y, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x - 1, y, player, dir, ps);
}
ps = oldps;
}
if (y - 1 > 0 && chessBoard[x][y - 1] != 'O' && dir == 4) {
oldps = ps;
if (chessBoard[x][y - 1] == 'X') {
setplayer1(s, ps);
point(s, x, y - 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x, y - 1, player, dir, ps);
}
ps = oldps;
}
if (x + 1 < MAXSIZE && y + 1 < MAXSIZE &&
chessBoard[x + 1][y + 1] != 'O' && dir == 5) {
oldps = ps;
if (chessBoard[x + 1][y + 1] == 'X') {
setplayer1(s, ps);
point(s, x + 1, y + 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x + 1, y + 1, player, dir, ps);
}
ps = oldps;
}
if (x - 1 > 0 && y - 1 > 0 && chessBoard[x - 1][y - 1] != 'O' &&
dir == 6) {
oldps = ps;
if (chessBoard[x - 1][y - 1] == 'X') {
setplayer1(s, ps);
point(s, x - 1, y - 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x - 1, y - 1, player, dir, ps);
}
ps = oldps;
}
if (x + 1 < MAXSIZE && y - 1 > 0 && chessBoard[x + 1][y - 1] != 'O' &&
dir == 7) {
oldps = ps;
if (chessBoard[x + 1][y - 1] == 'X') {
setplayer1(s, ps);
point(s, x + 1, y - 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x + 1, y - 1, player, dir, ps);
}
ps = oldps;
}
if (y + 1 < MAXSIZE && x - 1 > 0 && chessBoard[x - 1][y + 1] != 'O' &&
dir == 8) {
oldps = ps;
if (chessBoard[x - 1][y + 1] == 'X') {
setplayer1(s, ps);
point(s, x - 1, y + 1, player, dir, ps);
} else if (0 == ps % 2) {
setplayer1(s, ps, 1);
point(s, x - 1, y + 1, player, dir, ps);
}
ps = oldps;
}
}
}
void ai() {
int Max = 0;
for (int i = 1; i < MAXSIZE; i++) {
for (int j = 1; j < MAXSIZE; j++) {
b[i][j] = 0;
}
}
ai1 = 0;
ai2 = 0;
for (int i = 1; i < MAXSIZE; i++) {
for (int j = 1; j < MAXSIZE; j++) {
if (chessBoard[i][j] == ' ') {
point(b[i][j], i, j, 0, 0, 0);
}
}
}
for (int i = 1; i < MAXSIZE; i++) {
for (int j = 1; j < MAXSIZE; j++) {
if (b[i][j] > Max && chessBoard[i][j] == ' ') {
Max = b[i][j];
ai1 = i;
ai2 = j;
} else if (b[i][j] == Max && chessBoard[i][j] == ' ') {
if (random(0, 2) == 1) {
Max = b[i][j];
ai1 = i;
ai2 = j;
}
}
}
std::cout << std::endl;
}
}
} // namespace AI
namespace chess {
void gotoxy(int x, int y) {
COORD coord;
HANDLE hscr;
coord.X = x, coord.Y = y;
hscr = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hscr, coord);
}
void gotoqp(int x, int y) { gotoxy(4 * x + 7, 2 * y); }
namespace checker {
bool checkPos(int x) { return (x > 0) && (x <= MAXSIZE); }
bool checkRow(int x, int y, char player) {
int dx[] = {0, 0, 0, 1, -1, 1, -1, 1, -1},
dy[] = {0, 1, -1, 0, 0, 1, -1, -1, 1}, cnt[9] = {0};
if (chessBoard[x][y] != player) return 0;
for (int i = 1; i <= 8; ++i) {
int nx = x, ny = y;
while (checkPos(nx) && checkPos(ny) && chessBoard[nx][ny] == player)
cnt[i]++, nx += dx[i], ny += dy[i];
}
for (int i = 1; i <= 4; ++i)
if (cnt[i * 2 - 1] + cnt[i * 2] - 1 >= 5) return 1;
return 0;
}
int checkResult(char player) {
int flag = 0;
for (int i = 1; i < MAXSIZE; i++)
for (int j = 1; j < MAXSIZE; j++)
if (chessBoard[i][j] == ' ') {
flag = 1;
break;
}
if (flag == 0) return 2; // draw
for (int i = 1; i < MAXSIZE; i++)
for (int j = 1; j < MAXSIZE; j++) {
if (checkRow(i, j, player)) return 1; // win
}
return 0; // nothing happened
}
bool print(char player) {
if (player == 'X') {
if (checkResult('X') == 1) {
gotoxy(0, MAXSIZE * 2 + 3), std::cout << "您赢了" << std::endl;
return 1;
}
if (checkResult('X') == 2) {
gotoxy(0, MAXSIZE * 2 + 3), std::cout << "平局" << std::endl;
return 1;
}
} else {
if (checker::checkResult('O') == 1) {
gotoxy(0, MAXSIZE * 2 + 3), std::cout << "电脑赢了" << std::endl;
return 1;
}
if (checker::checkResult('O') == 2) {
gotoxy(0, MAXSIZE * 2 + 3), std::cout << "平局" << std::endl;
return 1;
}
}
return 0;
}
} // namespace checker
void draw(int x, int y, char ch) {
gotoqp(x, y), chessBoard[x][y] = ch;
if (ch == 'X') std::cout << chessBoard[x][y];
if (ch == 'O')
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_RED),
std::cout << chessBoard[x][y],
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_GREEN);
}
int x = 7, y = 7;
void initialize() {
srand(time(0)), system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY),
system("Color A");
for (int i = 1; i < MAXSIZE; i++)
for (int j = 1; j < MAXSIZE; j++) chessBoard[i][j] = ' ';
std::string title =
" 1 2 3 4 5 6 7 8 9 10 11 12 13";
std::cout << title << std::endl;
for (int i = 1; i < MAXSIZE; i++) {
std::cout << "\t ";
for (int m = 5; m < 4 * MAXSIZE; m++) std::cout << "-";
std::cout << std::endl
<< i << "\t"
<< " | ";
for (int j = 1; j < MAXSIZE; j++) {
if (i == 0 && j == 0) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_RED);
std::cout << chessBoard[i][j];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY);
std::cout << " | ";
} else
std::cout << chessBoard[i][j] << " | ";
}
std::cout << std::endl;
}
std::cout << " ";
for (int m = 5; m < 4 * MAXSIZE; m++) std::cout << "-";
gotoxy(0, MAXSIZE * 2 + 1);
std::cout << "请按方向键控制光标位置,按空格键确定下棋,按 Shift+e 退出。"
<< std::endl
<< "作者:杨千睿" << std::endl;
gotoqp(x, y);
}
void getMovement() {
int ch = getch();
if (ch == 224) ch = getch();
while (ch != 32) {
if (ch == 72)
if (y > 1) y--, gotoqp(x, y);
if (ch == 80)
if (y < MAXSIZE - 1) y++, gotoqp(x, y);
if (ch == 75)
if (x > 1) x--, gotoqp(x, y);
if (ch == 77)
if (x < MAXSIZE - 1) x++, gotoqp(x, y);
if (ch == 69) gotoxy(0, MAXSIZE * 2 + 4), system("pause"), exit(0);
ch = getch();
if (ch == 224) ch = getch();
}
}
void playerMove() {
int errorClickCnt = 0;
getMovement();
while (chessBoard[x][y] != ' ') {
errorClickCnt++;
if (errorClickCnt == 5) {
gotoxy(0, MAXSIZE * 2 + 4),
std::cout << "这里有棋,别点了……" << std::endl;
gotoqp(x, y);
}
getMovement();
}
draw(x, y, 'X');
if (checker::print('X')) system("pause"), exit(0);
}
void aiMove() {
while (chessBoard[x][y] != ' ' || !checker::checkPos(x) ||
!checker::checkPos(y))
AI::ai(), x = AI::ai1, y = AI::ai2;
draw(x, y, 'O');
if (checker::print('O')) system("pause"), exit(0);
}
} // namespace chess
int main() {
chess::initialize();
while (1) chess::playerMove(), chess::aiMove();
return 0;
}
有点长,大家不愿意看的就不用看了,可以下下来运行试一下(可以在机房里玩五子棋并在被发现时向教练解释说自己在调试程序),遇到一些bug也可以私信我
现在已知的bug有:
这两个bug我 懒得改了 有时间再改
代码风格可能比较奇怪,毕竟是我去年写的,那时还是一个蒟蒻 现在也是,所以用了goto语句,注释也比较少,大家有看不懂的地方可以私信我,我可能也看不懂,那就这样吧,感谢各位巨佬阅读我的文章,祝你们akioi 好吧你们早就ak了