ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

人机大战or双人五子棋,C语言实现,附源码

人机大战or双人五子棋,C语言实现,附源码

前言

C语言实现较简单的五子棋游戏,AI算法比较简单但应该能玩赢普通人的吧😉(作者比较菜,能玩赢作者)

现在让我们开始创作

创作思路

首先,我们要有一个棋盘。用easyx开辟一个窗口,然后加载一张图片,再在图片上画棋盘就可以了。棋盘的行列数目可以自己设定。

然后,我们要实现下棋的功能。棋子用实心圆表示,有黑白两种颜色。当鼠标在棋盘点下去后,传入鼠标的位置,并在距离最近的位置画一个圆(棋子)。用一个二维数组判断棋盘位置是否已经下棋,且是什么颜色的棋子,防止重叠下棋。

之后,我们要判断输赢。循环遍历棋盘,看是否有五子连珠的情况,如果有,传出连珠颜色,结束游戏。

到这,五子棋大概框架已经成了,现在还需要一个ai下棋的算法。

以一点横着为例,如果该点左边或者右边有几个相连的自己的棋子,那么,该点就有一个分值。将每一个点的横竖左右分值加一起,为该点的总分。分值最大的地方就是ai要下棋的地方。

程序实例

准备

先加载头文件,定义背景图和棋盘大小

#include<stdio.h> #include<graphics.h> #include<windows.h> #include<math.h> IMAGE wzq;//背景图 int num = -1;//-1表示黑子下,1表示白字下。 int piece[15][15];

画棋盘

我们的背景图是不带线条的风景图,所以,接下来要画棋盘

void putbackground()//放置背景图 { putimage(0, 0, 225, 225, &wzq, 30, 30); putimage(225, 0, 224, 225, &wzq, 30, 30); putimage(0, 225, 225, 224, &wzq, 30, 30); putimage(225, 225, 224, 224, &wzq, 30, 30); } void draw_line() //画线 { setlinecolor(BLACK); int x, y; for ( x = 15; x < 450; x += 30) { line(x, 15, x, 435); } for ( y = 15; y < 450; y += 30) { line(15, y, 435, y); } } void draw_point()//画5个特殊点 { setfillcolor(BLACK); fillcircle(4 * 30 - 15, 4 * 30 - 15, 3); fillcircle(4 * 30 - 15, 12* 30 - 15, 3); fillcircle(8 * 30 - 15, 8 * 30 - 15, 3); fillcircle(12 * 30 - 15, 12 * 30 - 15, 3); fillcircle(12 * 30 - 15, 4 * 30 - 15, 3); }

棋盘初始化

初始化棋盘和改变棋子的操作

void initpiece() { int i; for (i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) piece[i][j] = 0;//0表示该点没有棋子 } } int change_piece(int x, int y)//下棋时判断该点能不能下棋,是不是空的 { if (piece[x][y] == 0) return 0; return 1; } int draw_piece(int m,int n)//画黑棋 { setfillcolor(BLACK); int x, y; x = fabs(n) / 30 ; y = fabs(m) / 30 ; if (change_piece(x, y) == 0) { piece[x][y] = -1; fillcircle(y * 30 + 15, x * 30 + 15, 15); return 1; } return -1; } int draw_piece1(int m, int n)//画白棋 { setfillcolor(WHITE); int x, y; x = fabs(n) / 30; y = fabs(m) / 30; if (change_piece(x, y) == 0) { piece[x][y] = 1; fillcircle(y * 30 + 15, x * 30 + 15, 15); return -1; } return 1; }

检测是否获胜

接下来就是基本的检查是否获胜是否五子连棋,这一部分按自己的思路写也可以

int check_five_piece(int x, int y) { if (piece[x - 2][y] == piece[x][y] && piece[x - 1][y] == piece[x][y] && piece[x][y] == piece[x + 1][y] && piece[x][y] == piece[x + 2][y] != 0) return 1; if (piece[x][y - 2] ==piece[x][y]&& piece[x][y - 1] ==piece[x][y]&& piece[x][y] == piece[x][y + 1]&&piece[x][y] == piece[x][y + 2] != 0) return 1; if (piece[x + 1][y + 1] ==piece[x][y]&& piece[x + 2][y + 2] == piece[x][y]&&piece[x][y] == piece[x - 1][y - 1]&&piece[x][y] == piece[x - 2][y - 2] != 0) return 1; if (piece[x - 2][y + 2] ==piece[x][y]&& piece[x - 1][y + 1] == piece[x][y]&&piece[x][y] == piece[x + 1][y - 1]&&piece[x][y] == piece[x + 2][y - 2] != 0) return 1; return 0; } int check_over() { for (int i = 0; i < 15; i++) for (int j = 0; j < 15; j++) { if (piece[i][j] == 0) continue; if (check_five_piece(i, j) ==1) return piece[i][j]; } return 0; }

ai判断下棋

基本的功能就完成了

接下来让ai能够智能点下棋

int gobang_rollback(int self, int e) { if (self == 5 && e == 2)return 500000; if (self == 5 && e == 1)return 500000; if (self == 5 && e == 0)return 500000; if (self == 4 && e == 2)return 1000; if (self == 4 && e == 1)return 3000; if (self == 4 && e == 0)return 50000; if (self == 3 && e == 2)return 500; if (self == 3 && e == 1)return 1000; if (self == 3 && e == 0)return 3000; if (self == 2 && e == 2)return 100; if (self == 2 && e == 1)return 200; if (self == 2 && e == 0)return 500; if (self == 1 && e == 2)return 30; if (self == 1 && e == 1)return 50; if (self == 1 && e == 0)return 100; return 0; }//为每种局势赋分

让ai判断棋盘上的情况,横竖撇捺四个方向的情况

int gobang_getHorizontalScore(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = x - 1; i >= 0; i--) { if (piece[i][y] == pieces) { self++; } else if (piece[i][y] == 0) { break; } else { ai++; break; } } for (int i = x + 1; i <15; i++) { if (piece[i][y] == pieces) { self++; } else if (piece[i][y] == 0) { break; } else { ai++; break; } } return gobang_rollback(self,ai); } int gobang_getVercitalScor(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = y - 1; i >= 0; i--) { if (piece[x][i] == pieces) { self++; } else if (piece[x][i] == 0) { break; } else { ai++; break; } } for (int i = y + 1; i < 15; i++) { if (piece[x][i] == pieces) { self++; } else if (piece[x][i] == 0) { break; } else { ai++; break; } } return gobang_rollback(self,ai); } int gobang_getLhtScore(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = 1; i <= x&&i<15-y; i++) { if (piece[x - i][y + i] == pieces) { self++; } else if (piece[x - i][y + i] == 0) { break; } else { ai++; break; } } for (int i = 1; i <= y&&i<15-x; i++) { if (piece[x + i][y - i] == pieces) { self++; } else if (piece[x + i][y - i] == 0) { break; } else { ai++; break; } } return gobang_rollback(self, ai); } int gobang_getRhtScore(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = 1; i <= y && i <= x; i++) { if (piece[x - i][y - i] == pieces) { self++; } else if (piece[x - i][y - i] == 0) { break; } else { ai++; break; } } for (int i = 1; i < 15-y && i < 15 - x; i++) { if (piece[x + i][y + i] == pieces) { self++; } else if (piece[x + i][y + i] == 0) { break; } else { ai++; break; } } return gobang_rollback(self, ai); }

ai分析棋盘上各个位置的情况,找出最佳位置

int gobang_getScore(int x,int y) { int numH1 = gobang_getHorizontalScore(x, y, -1); int numH2 = gobang_getHorizontalScore(x, y, 1); int numV1 = gobang_getVercitalScor(x, y, -1); int numV2 = gobang_getVercitalScor(x, y, 1); int numL1 = gobang_getLhtScore(x, y, -1); int numL2 = gobang_getLhtScore(x, y, 1); int numR1 = gobang_getRhtScore(x, y, -1); int numR2 = gobang_getRhtScore(x, y, 1); int all = numH1 + numH2 + numV1 + numV2 + numL1 + numL2 + numR1 + numR2; return all; }

ai做出选择

int ai_choose() { int Score = 0; int a=0, b=0; for (int x = 0; x < 15; x++) { for (int y = 0; y < 15; y++) { if (change_piece(x, y) == 1) continue; if (gobang_getScore(x, y) > Score) { Score = gobang_getScore(x, y); a = x; b = y; } } } //printf("%d %d\n", a, b); setfillcolor(WHITE); piece[a][b] = 1; fillcircle(b*30+15,a*30+15, 15); return -1; }

人机和双人两种模式的选择

选择模式人机or双人

int chose_model() { printf("请选择模式:\n"); printf("1 人机对抗\n"); printf("2 双人模式\n"); int model,n=1; scanf_s("%d",&model); while (model != 1 && model != 2) { printf("请输入1或2,不要乱输\n"); printf("再输一次吧:\n"); scanf_s("%d", &model); n++; if (n > 3) { printf("??你小汁给我好好输\n"); } } return model; }

人机对战

int ai_human() { MOUSEMSG m; settextcolor(RED); settextstyle(40, 40, _T("隶书")); while (1) { if (num == -1) { m = GetMouseMsg(); if (m.uMsg == 513) { num = draw_piece(m.x, m.y); } } else if (num == 1) { num = ai_choose(); } if (check_over() == 1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("白棋胜利")); system("pause"); return 0; } else if (check_over() == -1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("黑棋胜利")); system("pause"); return 0; } } }

双人对战

int human_human() { MOUSEMSG m; settextcolor(RED); settextstyle(40, 40, _T("隶书")); while (1) { if (num == -1) { m = GetMouseMsg(); if (m.uMsg == 513) { num = draw_piece(m.x, m.y); } } else if (num == 1) { m = GetMouseMsg(); if (m.uMsg == 513) { num = draw_piece1(m.x, m.y); } } if (check_over() == 1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("白棋胜利")); system("pause"); return 0; } else if (check_over() == -1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("黑棋胜利")); system("pause"); return 0; } } }

main函数

最后,写上main函数

int main() { int d; d=chose_model(); initgraph(450, 450);//定义像素点多少。 loadimage(&wzq, _T("wzq1.jpg")); putbackground(); draw_line(); draw_point(); initpiece(); if (d == 1) ai_human(); else if (d == 2) human_human(); return 0; }

本程序所用图片背景,大家也可以找一张其他好看的jpg图片,命名为wzq1即可

源码呈上

最后,附上源码。

#include<stdio.h> #include<graphics.h> #include<windows.h> #include<math.h> IMAGE wzq; int num = -1;//-1表示黑子下,1表示白字下。 int piece[15][15]; void putbackground() { putimage(0, 0, 225, 225, &wzq, 30, 30); putimage(225, 0, 224, 225, &wzq, 30, 30); putimage(0, 225, 225, 224, &wzq, 30, 30); putimage(225, 225, 224, 224, &wzq, 30, 30); } void draw_line() //画线 { setlinecolor(BLACK); int x, y; for ( x = 15; x < 450; x += 30) { line(x, 15, x, 435); } for ( y = 15; y < 450; y += 30) { line(15, y, 435, y); } } void draw_point()//画特殊点 { setfillcolor(BLACK); fillcircle(4 * 30 - 15, 4 * 30 - 15, 3); fillcircle(4 * 30 - 15, 12* 30 - 15, 3); fillcircle(8 * 30 - 15, 8 * 30 - 15, 3); fillcircle(12 * 30 - 15, 12 * 30 - 15, 3); fillcircle(12 * 30 - 15, 4 * 30 - 15, 3); } void initpiece() { int i; for (i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) piece[i][j] = 0; } } int change_piece(int x, int y) { if (piece[x][y] == 0) return 0; return 1; } int check_five_piece(int x, int y) { if (piece[x - 2][y] == piece[x][y] && piece[x - 1][y] == piece[x][y] && piece[x][y] == piece[x + 1][y] && piece[x][y] == piece[x + 2][y] != 0) return 1; if (piece[x][y - 2] ==piece[x][y]&& piece[x][y - 1] ==piece[x][y]&& piece[x][y] == piece[x][y + 1]&&piece[x][y] == piece[x][y + 2] != 0) return 1; if (piece[x + 1][y + 1] ==piece[x][y]&& piece[x + 2][y + 2] == piece[x][y]&&piece[x][y] == piece[x - 1][y - 1]&&piece[x][y] == piece[x - 2][y - 2] != 0) return 1; if (piece[x - 2][y + 2] ==piece[x][y]&& piece[x - 1][y + 1] == piece[x][y]&&piece[x][y] == piece[x + 1][y - 1]&&piece[x][y] == piece[x + 2][y - 2] != 0) return 1; return 0; } int gobang_rollback(int self, int e) { if (self == 5 && e == 2)return 500000; if (self == 5 && e == 1)return 500000; if (self == 5 && e == 0)return 500000; if (self == 4 && e == 2)return 1000; if (self == 4 && e == 1)return 3000; if (self == 4 && e == 0)return 50000; if (self == 3 && e == 2)return 500; if (self == 3 && e == 1)return 1000; if (self == 3 && e == 0)return 3000; if (self == 2 && e == 2)return 100; if (self == 2 && e == 1)return 200; if (self == 2 && e == 0)return 500; if (self == 1 && e == 2)return 30; if (self == 1 && e == 1)return 50; if (self == 1 && e == 0)return 100; return 0; } int check_over() { for (int i = 0; i < 15; i++) for (int j = 0; j < 15; j++) { if (piece[i][j] == 0) continue; if (check_five_piece(i, j) ==1) return piece[i][j]; } return 0; } int draw_piece(int m,int n) { setfillcolor(BLACK); int x, y; x = fabs(n) / 30 ; y = fabs(m) / 30 ; if (change_piece(x, y) == 0) { piece[x][y] = -1; fillcircle(y * 30 + 15, x * 30 + 15, 15); return 1; } return -1; } int draw_piece1(int m, int n) { setfillcolor(WHITE); int x, y; x = fabs(n) / 30; y = fabs(m) / 30; if (change_piece(x, y) == 0) { piece[x][y] = 1; fillcircle(y * 30 + 15, x * 30 + 15, 15); return -1; } return 1; } int gobang_getHorizontalScore(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = x - 1; i >= 0; i--) { if (piece[i][y] == pieces) { self++; } else if (piece[i][y] == 0) { break; } else { ai++; break; } } for (int i = x + 1; i <15; i++) { if (piece[i][y] == pieces) { self++; } else if (piece[i][y] == 0) { break; } else { ai++; break; } } return gobang_rollback(self,ai); } int gobang_getVercitalScor(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = y - 1; i >= 0; i--) { if (piece[x][i] == pieces) { self++; } else if (piece[x][i] == 0) { break; } else { ai++; break; } } for (int i = y + 1; i < 15; i++) { if (piece[x][i] == pieces) { self++; } else if (piece[x][i] == 0) { break; } else { ai++; break; } } return gobang_rollback(self,ai); } int gobang_getLhtScore(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = 1; i <= x&&i<15-y; i++) { if (piece[x - i][y + i] == pieces) { self++; } else if (piece[x - i][y + i] == 0) { break; } else { ai++; break; } } for (int i = 1; i <= y&&i<15-x; i++) { if (piece[x + i][y - i] == pieces) { self++; } else if (piece[x + i][y - i] == 0) { break; } else { ai++; break; } } return gobang_rollback(self, ai); } int gobang_getRhtScore(int x,int y,int pieces) { int self = 1; int ai = 0; for (int i = 1; i <= y && i <= x; i++) { if (piece[x - i][y - i] == pieces) { self++; } else if (piece[x - i][y - i] == 0) { break; } else { ai++; break; } } for (int i = 1; i < 15-y && i < 15 - x; i++) { if (piece[x + i][y + i] == pieces) { self++; } else if (piece[x + i][y + i] == 0) { break; } else { ai++; break; } } return gobang_rollback(self, ai); } int gobang_getScore(int x,int y) { int numH1 = gobang_getHorizontalScore(x, y, -1); int numH2 = gobang_getHorizontalScore(x, y, 1); int numV1 = gobang_getVercitalScor(x, y, -1); int numV2 = gobang_getVercitalScor(x, y, 1); int numL1 = gobang_getLhtScore(x, y, -1); int numL2 = gobang_getLhtScore(x, y, 1); int numR1 = gobang_getRhtScore(x, y, -1); int numR2 = gobang_getRhtScore(x, y, 1); int all = numH1 + numH2 + numV1 + numV2 + numL1 + numL2 + numR1 + numR2; return all; } int ai_choose() { int Score = 0; int a=0, b=0; for (int x = 0; x < 15; x++) { for (int y = 0; y < 15; y++) { if (change_piece(x, y) == 1) continue; if (gobang_getScore(x, y) > Score) { Score = gobang_getScore(x, y); a = x; b = y; } } } //printf("%d %d\n", a, b); setfillcolor(WHITE); piece[a][b] = 1; fillcircle(b*30+15,a*30+15, 15); return -1; } int chose_model() { printf("请选择模式:\n"); printf("1 人机对抗\n"); printf("2 双人模式\n"); int model,n=1; scanf_s("%d",&model); while (model != 1 && model != 2) { printf("请输入1或2,不要乱输\n"); printf("再输一次吧:\n"); scanf_s("%d", &model); n++; if (n > 3) { printf("??你小汁给我好好输\n"); } } return model; } int ai_human() { MOUSEMSG m; settextcolor(RED); settextstyle(40, 40, _T("隶书")); while (1) { if (num == -1) { m = GetMouseMsg(); if (m.uMsg == 513) { num = draw_piece(m.x, m.y); } } else if (num == 1) { num = ai_choose(); //printf("%d\n", num); } if (check_over() == 1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("白棋胜利")); /*for (int i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) { printf("%d", piece[i][j]); } printf("\n"); }*/ system("pause"); return 0; } else if (check_over() == -1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("黑棋胜利")); /*for (int i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) printf("%d", piece[i][j]); printf("\n"); }*/ system("pause"); return 0; } } } int human_human() { MOUSEMSG m; settextcolor(RED); settextstyle(40, 40, _T("隶书")); while (1) { if (num == -1) { m = GetMouseMsg(); if (m.uMsg == 513) { num = draw_piece(m.x, m.y); } } else if (num == 1) { m = GetMouseMsg(); if (m.uMsg == 513) { num = draw_piece1(m.x, m.y); } } if (check_over() == 1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("白棋胜利")); system("pause"); return 0; } else if (check_over() == -1) { outtextxy(60, 180, _T("游戏结束")); outtextxy(60, 220, _T("黑棋胜利")); system("pause"); return 0; } } } int main() { int d; d=chose_model(); initgraph(450, 450);//定义像素点多少。 loadimage(&wzq, _T("wzq1.jpg")); putbackground(); draw_line(); draw_point(); initpiece(); if (d == 1) ai_human(); else if (d == 2) human_human(); return 0; }
返回列表