【C语言】五子棋(c语言实现)

这里写目录标题

  • 最终效果
  • 菜单打印函数
  • 棋盘的初始化和打印
  • 人人对战
    • 落子判空函数
    • 悔棋函数
    • 判胜负函数
    • 人人对战
  • 人机对战
    • 一是将直接调用rand生成随机值,这就不可控
    • 二是根据棋子赢面来判断哪里落子最好
  • 如果选择退出程序直接exit就行
  • 主函数调用逻辑
  • 源代码

在这里插入图片描述

最终效果

五子棋c语言实现

菜单打印函数

使用这个函数来接收用户选择的模式,并通过返回值返回。
逻辑是使用一个死循环来打印,根据玩家输入的数来判断进入什么模式,输入错误数字就不出循环,正确就出循环。

int menu()
{int choice = -1;while (1){printf("----------------欢迎使用五子棋------------------------\n");printf("-                 请选择模式                         -\n");printf("-                    1.人-人对战游戏                 -\n");printf("-                    2.人-机对战游戏                 -\n");printf("-                    0.退出游戏                      -\n");printf("------------------------------------------------------\n");printf("------------------------------------------------------\n");scanf("%d", &choice);if (choice > 4 || choice < 0)printf("错误输入");elsebreak;}return choice;
}

棋盘的初始化和打印

在这个函数中将表示棋盘的二维数组初始化为空状态,并通过棋盘数组的只来打印棋盘。打印棋盘时用到的符号:┏ ┳ ┓┣ ╋ ┫┗ ┻ ┛。要注意有些地方添加━和空格来控制打印的棋盘是正确的。
里面每一次打印都调用draw_chessman这个函数,在这个函数中将根据数组值来判断如何打印。

//绘制棋子
void draw_chessman(int type, char* tableline) {if (type == WHITE)printf(" ●");if (type == BLACK)printf(" ○");if (type == NO)printf("%s", tableline);
}

打印棋盘的逻辑就是因为没能设置光标坐标那就只有一行一行打印然后根据边界行列值来判断。
如果要看如何打印改变光标可以参考这篇文章win32 API

void initMap(int map[N + 1][N + 1])
{//第一行和第一列显示数字for (int i = 0; i < N + 1; i++){map[0][i] = i;map[i][0] = i;if (i >= 10){map[0][i] = i - 10;map[i][0] = i - 10;}}for (int i = 0; i < N + 1; i++){//打印第一行数字if (i == 0){for (int j = 0; j < N + 1; j++){printf("%-2d", map[0][j]);}printf("\n");}//打印第一行棋盘else if (i == 1){for (int j = 0; j < N + 1; j++){if (j == 0)printf("%d", map[i][j]);else if (j == 1)draw_chessman(map[i][j], " ┏");else if (j == N)draw_chessman(map[i][j], "━┓");elsedraw_chessman(map[i][j], "━┳");}printf("\n");}//打印最后一行else if (i == N){for (int j = 0; j < N + 1; j++){if (j == 0)printf("%d", map[i][j]);else if (j == 1)draw_chessman(map[i][j], " ┗");else if (j == N)draw_chessman(map[i][j], "━┛");elsedraw_chessman(map[i][j], "━┻");}printf("\n");}else{for (int j = 0; j < N + 1; j++){if (j == 0)printf("%d", map[i][j]);else if (j == 1)draw_chessman(map[i][j], " ┣");else if (j == N)draw_chessman(map[i][j], "━┫");elsedraw_chessman(map[i][j], "━╋");}printf("\n");}}
}

人人对战

人人对战逻辑中就是先让黑方下棋,输入坐标,输入错误就再次输入(死循环实现),将该坐标的二维数组值变为黑,然后让其选择悔不悔棋,我实现的是只要1是悔棋其他数字就是不悔棋。执行完不悔棋后就判断是否胜利,如果胜就跳出选择是否重来一局,如果没胜就白棋下执行相同逻辑。

落子判空函数

在这个函数中判断坐标代表的二维数组值是不是空,不是就重新输入坐标。

void judgeEmpty(int map[][N + 1], int x, int y, int goal)
{while (1){if (map[x][y] != NO){printf("已有棋子,重新输入\n");scanf("%d%d", &x, &y);}else{map[x][y] = goal;initMap(map);break;}}
}

悔棋函数

该函数里面就是根据用户选择,如果悔棋然后将刚才的地方的数组值变回空。

int retract(int map[][N + 1], int x, int y)
{int choice = -1;printf("是否悔棋:是1\n");scanf("%d", &choice);if (choice == 1){map[x][y] = NO;initMap(map);}return choice;
}

执行完不悔棋后就判断是否胜利

判胜负函数

这个函数就是将下的这个棋子的横竖斜方向判胜负。(没有判断和棋情况),如果要判断就是二维数组全不为空状态,使用遍历判断就行。

int judgeWin(int map[][N + 1], int x, int y)
{for (int i = 1; i < N + 1; i++){for (int j = 1; j < N + 1; j++){if (j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//横{if (map[i][j] == map[i][j + 1]&& map[i][j + 1] == map[i][j + 2]&& map[i][j + 2] == map[i][j + 3]&& map[i][j + 3] == map[i][j + 4])return map[i][j];}if (i < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//竖{if (map[i][j] == map[i + 1][j]&& map[i + 1][j] == map[i + 2][j]&& map[i + 2][j] == map[i + 3][j]&& map[i + 3][j] == map[i + 4][j])return map[i][j];}if (i < N + 1 - 4 && j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右下_{if (map[i][j] == map[i + 1][j + 1]&& map[i + 1][j + 1] == map[i + 2][j + 2]&& map[i + 2][j + 2] == map[i + 3][j + 3]&& map[i + 3][j + 3] == map[i + 4][j + 4])return map[i][j];}if (i > 4 && j > 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右上{if (map[i][j] == map[i - 1][j - 1]&& map[i - 1][j - 1] == map[i - 2][j - 2]&& map[i - 2][j - 2] == map[i - 3][j - 3]&& map[i - 3][j - 3] == map[i - 4][j - 4])return map[i][j];}}}return NO;
}

人人对战

void peopleFight(int map[][N + 1])
{printf("--------人-人对战---------------\n");initMap(map);while (1){int x = -1;int y = -1;black:while (1){printf("黑方落子\n");printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, BLACK);if (retract(map, x, y) == 1)goto black;//判断胜利int ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}white:while (1){printf("白方落子\n");printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, WHITE);if (retract(map, x, y) == 1)goto white;//判断胜利ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}}
}

人机对战

在这个函数中用户选择落子方,然后执行逻辑与人人对战一样。
但是电脑生成棋子提供两种选择:

一是将直接调用rand生成随机值,这就不可控

方法一这样写对棋子的位置生成是很不可控的,会让机器随机乱落子。

void machine(int map[][N + 1])
{printf("--------人-机对战---------------\n");srand(time(NULL));int choice = -1;printf("请输入你执黑棋还是白棋,黑1,白2\n");scanf("%d", &choice);if (choice == 1){while (1){int x = -1;int y = -1;black:while (1){printf("黑方落子\n");printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, BLACK);//判断胜利int ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}if (retract(map, x, y) == 1)goto black;next:x = rand() % 15 + 1;y = rand() % 15 + 1;if (map[x][y] != NO)goto next;judgeEmpty(map, x, y, WHITE);//判断胜利ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}}}else if (choice == 2){while (1){int x = -1;int y = -1;next2:x = rand() % 15 + 1;y = rand() % 15 + 1;if (map[x][y] != NO)goto next2;judgeEmpty(map, x, y, BLACK);//判断胜利int ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}white:while (1){printf("白方落子\n");printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, WHITE);//判断胜利ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}if (retract(map, x, y) == 1)goto white;}}}

二是根据棋子赢面来判断哪里落子最好

这样实现就会让机器落子一直是去围堵你的棋子,虽然还是很垃圾,但是比方法一好多了。

void AIjudge(int color, int map[N+1][N+1])
{int num = 1, left = 0, right = 0;int n, m, score = 0, max = 0;int dx, dy;for (int i = 1; i < N+1; i++){for (int j = 1; j < N+1; j++){score = 0;if (map[i][j] != 0)continue;else{dx = 1, dy = 0, n = i, m = j;while (1)//水平向右{n += dx, m += dy;if (map[n][m] == 0){right = 0; break;}else if (map[n][m] != color || n > 15){right++; break;}else if (num < 5) { num++; }}dx = -1, dy = 0;while (1) {//水平向左n += dx; m += dy;if (map[n][m] == 0) { left = 0; break; }else if (map[n][m] != color || n < 1) { left++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);//用data来算分数,并用score来记录//  |方向num = 1; right = 0, left = 0;//每一次改变方向要重置这些变量dx = 0; dy = -1; n = i; m = j;//向上while (1) {n += dx; m += dy;if (map[n][m] == 0) { left = 0; break; }else if (map[n][m] != color || m < 1) { left++; break; }else if (num < 5) { num++; }}//向下dx = 0; dy = 1; n = i; m = j;while (1) {n += dx; m += dy;if (map[n][m] == 0) { right = 0; break; }else if (map[n][m] != color || m > 15) { right++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);//  \方向num = 1; right = 0, left = 0;dx = 1; dy = 1; n = i; m = j;//向右下while (1) {n += dx; m += dy;if (map[n][m] == 0) { right = 0; break; }else if (map[n][m] != color || m > 15 || n > 15) { right++; break; }else if (num < 5) { num++; }}//向左上dx = -1; dy = -1; n = i; m = j;while (1) {n += dx; m += dy;if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }else if ((n > 0 && m > 0 && map[n][m] != color) || m < 1 || n < 1) { left++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);//  /方向`num = 1; right = 0, left = 0;dx = 1; dy = -1; n = i; m = j;//向右上while (1) {n += dx; m += dy;if (map[n][m] == 0) { right = 0; break; }else if (map[n][m] != color || n > 15 || m < 1) { right++; break; }else if (num < 5) { num++; }}//向左下dx = -1; dy = 1; n = i; m = j;while (1) {n += dx; m += dy;if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }else if ((n > 0 && m > 0 && map[n][m] != color) || n < 1 || m > 15) { left++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);if (score > max) {//每一次用max保存分数,下一次比较,最后找出最大值max = score;position[0] = i;//用来保存每一次的位置和分数position[1] = j;position[2] = score;}}}}
}
int Data(int num, int count)
{switch (num){case 1:	if (count == 0)//活一:表示在该处落子,就只有这一个棋子,两边都没有阻挡(边界或对方的棋子)优势较大return 2;else if (count == 1)//冲一:表示在该处落子,就只有这一个棋子,两边有一种阻挡(边界或对方的棋子)优势较小return 1;else return 0;break;case 2:if (count == 0)//活二;接下来都同理活一和冲一return 20;else if (count == 1)//冲二return 10;else return 0;break;case 3:if (count == 0)//活三return 300;else if (count == 1)//冲三return 50;else return 0;break;case 4:if (count == 0)//活四return 4000;else if (count == 1)//冲四return 1000;else return 0;break;case 5://五return 5000;break;default:return 0;break;}
}
void machine(int map[][N + 1])
{printf("--------人-机对战---------------\n");int choice = -1;do {printf("请输入你执黑棋还是白棋,黑1,白2\n");scanf("%d", &choice);} while (choice != 1 && choice != 2);initMap(map);if (choice == 1){while (1){int x = -1;int y = -1;black:while (1){printf("黑方落子\n");printf("现在棋盘为%d*%d请输入要落下的坐标x y\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, BLACK);if (retract(map, x, y)){map[x][y] = 0;initMap(map);goto black;}int ret = judgeWin(map, x, y);if (ret == BLACK)       //判断胜利break;int old_max = 0, new_max = 0, n = 0, m = 0;int AIx = -1, AIy = -1;AIjudge(1, map);//判断黑子的优势位置old_max = position[2];//保存该位置分数AIx = position[0]; AIy = position[1];//保存该位置的坐标,注意行列和xy轴的对应关系position[0] = 0, position[1] = 0, position[2] = 0;AIjudge(-1, map);//判断白子的优势位置new_max = position[2];//保存分数if (new_max >= old_max) //判断哪个位置的分数大,从而判断是堵截还是进攻{AIx = position[0]; AIy = position[1];}judgeEmpty(map, AIx, AIy, WHITE);ret = judgeWin(map, x, y);if (ret == WHITE)       //判断胜利break;}}else if (choice == 2){while (1){int x = -1, y = -1;int old_max = 0, new_max = 0, n = 0, m = 0;int AIx = -1, AIy = -1;AIjudge(1, map);//判断黑子的优势位置old_max = position[2];//保存该位置分数AIx = position[0]; AIy = position[1];//保存该位置的坐标,注意行列和xy轴的对应关系position[0] = 0, position[1] = 0, position[2] = 0;AIjudge(-1, map);//判断白子的优势位置new_max = position[2];//保存分数if (new_max >= old_max) //判断哪个位置的分数大,从而判断是堵截还是进攻{AIx = position[0]; AIy = position[1];}judgeEmpty(map, AIx, AIy, BLACK);int ret = judgeWin(map, x, y);if (ret == BLACK)       //判断胜利 break;white:while (1){printf("白方落子\n");printf("现在棋盘为%d*%d请输入要落下的坐标x y\n", N, N);scanf("%d,%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, WHITE);if (retract(map, x, y)){map[x][y] = 0;initMap(map);goto white;}ret = judgeWin(map, x, y);if (ret == WHITE)       //判断胜利break;}}}

如果选择退出程序直接exit就行

主函数调用逻辑

用死循环调用,然后根据menu返回值通过switch-case来调用相应模式函数,最后在让用户选择是否再来一局,如果再来一局就不出循环,不再来就出循环。

int main()
{while (1){int map[N + 1][N + 1] = { 0 };int choice = menu();switch (choice){case 1://调用人人对打peopleFight(map);break;case 2://调用人机对打machine(map);break;case 0:printf("退出成功\n");exit(0);break;}int a = 0;printf("是否再来一盘:是1,不是0\n");scanf("%d", &a);if (a == 0)break;}return 0;
}

源代码

源码呈上,为方便复制写在同一个文件之下,可以多文件进行。

# define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h>
#include<time.h>
#define N 15 //表示棋盘的行列
#define NO 0 //表示没下子的状态
#define BLACK 1
#define WHITE -1
//棋盘初始化函数
void initMap(int map[N + 1][N + 1]);
//落子函数
void judgeEmpty(int map[][N + 1], int x, int y, int goal);
//人人对打
void peopleFight(int map[][N + 1]);
//判断胜利
int judgeWin(int map[][N + 1], int x, int y);
//悔棋
int retract(int map[][N + 1], int x, int y);
//人机对打
void machine(int map[][N + 1]);
//打印菜单并返回选择的模式
int menu();
void AIjudge(int color, int map[N + 1][N + 1]);
int Data(int num, int count);
int position[3];int main()
{while (1){int map[N + 1][N + 1] = { 0 };int choice = menu();switch (choice){case 1://调用人人对打peopleFight(map);break;case 2://调用人机对打machine(map);break;case 0:printf("退出成功\n");exit(0);break;}int a = 0;printf("是否再来一盘:是1,不是0\n");scanf("%d", &a);if (a == 0)break;}return 0;
}
int menu()
{int choice = -1;while (1){printf("----------------欢迎使用五子棋------------------------\n");printf("-                 请选择模式                         -\n");printf("-                    1.人-人对战游戏                 -\n");printf("-                    2.人-机对战游戏                 -\n");printf("-                    0.退出游戏                      -\n");printf("------------------------------------------------------\n");printf("------------------------------------------------------\n");scanf("%d", &choice);if (choice > 4 || choice < 0)printf("错误输入");elsebreak;}return choice;
}void judgeEmpty(int map[][N + 1], int x, int y, int goal)
{while (1){if (map[x][y] != NO){printf("已有棋子,重新输入\n");scanf("%d%d", &x, &y);}else{map[x][y] = goal;initMap(map);break;}}
}int judgeWin(int map[][N + 1], int x, int y)
{for (int i = 1; i < N + 1; i++){for (int j = 1; j < N + 1; j++){if (j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//横{if (map[i][j] == map[i][j + 1]&& map[i][j + 1] == map[i][j + 2]&& map[i][j + 2] == map[i][j + 3]&& map[i][j + 3] == map[i][j + 4])return map[i][j];}if (i < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//竖{if (map[i][j] == map[i + 1][j]&& map[i + 1][j] == map[i + 2][j]&& map[i + 2][j] == map[i + 3][j]&& map[i + 3][j] == map[i + 4][j])return map[i][j];}if (i < N + 1 - 4 && j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右下_{if (map[i][j] == map[i + 1][j + 1]&& map[i + 1][j + 1] == map[i + 2][j + 2]&& map[i + 2][j + 2] == map[i + 3][j + 3]&& map[i + 3][j + 3] == map[i + 4][j + 4])return map[i][j];}if (i > 4 && j > 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右上{if (map[i][j] == map[i - 1][j - 1]&& map[i - 1][j - 1] == map[i - 2][j - 2]&& map[i - 2][j - 2] == map[i - 3][j - 3]&& map[i - 3][j - 3] == map[i - 4][j - 4])return map[i][j];}}}return NO;
}//绘制棋子
void draw_chessman(int type, char* tableline) {if (type == WHITE)printf(" ●");if (type == BLACK)printf(" ○");if (type == NO)printf("%s", tableline);
}void initMap(int map[N + 1][N + 1])
{//第一行和第一列显示数字for (int i = 0; i < N + 1; i++){map[0][i] = i;map[i][0] = i;if (i >= 10){map[0][i] = i - 10;map[i][0] = i - 10;}}for (int i = 0; i < N + 1; i++){//打印第一行数字if (i == 0){for (int j = 0; j < N + 1; j++){printf("%-2d", map[0][j]);}printf("\n");}//打印第一行棋盘else if (i == 1){for (int j = 0; j < N + 1; j++){if (j == 0)printf("%d", map[i][j]);else if (j == 1)draw_chessman(map[i][j], " ┏");else if (j == N)draw_chessman(map[i][j], "━┓");elsedraw_chessman(map[i][j], "━┳");}printf("\n");}//打印最后一行else if (i == N){for (int j = 0; j < N + 1; j++){if (j == 0)printf("%d", map[i][j]);else if (j == 1)draw_chessman(map[i][j], " ┗");else if (j == N)draw_chessman(map[i][j], "━┛");elsedraw_chessman(map[i][j], "━┻");}printf("\n");}else{for (int j = 0; j < N + 1; j++){if (j == 0)printf("%d", map[i][j]);else if (j == 1)draw_chessman(map[i][j], " ┣");else if (j == N)draw_chessman(map[i][j], "━┫");elsedraw_chessman(map[i][j], "━╋");}printf("\n");}}
}//void machine(int map[][N + 1])
//{
//    printf("--------人-机对战---------------\n");
//    srand(time(NULL));
//    int choice = -1;
//    printf("请输入你执黑棋还是白棋,黑1,白2\n");
//    scanf("%d", &choice);
//    if (choice == 1)
//    {
//        while (1)
//        {
//            int x = -1;
//            int y = -1;
//        black:
//            while (1)
//            {
//                printf("黑方落子\n");
//                printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);
//                scanf("%d%d", &x, &y);
//                if (x < 0 || x > N || y < 0 || y > N)
//                    printf("错误输入\n");
//                else
//                    break;
//            }
//            judgeEmpty(map, x, y, BLACK);
//            //判断胜利
//            int ret = judgeWin(map, x, y);
//            if (ret == BLACK)
//            {
//                printf("黑方获胜\n");
//                return;
//            }
//            else if (ret == WHITE)
//            {
//                printf("白方获胜\n");
//                return;
//            }
//            if (retract(map, x, y) == 1)
//                goto black;
//        next:
//            x = rand() % 15 + 1;
//            y = rand() % 15 + 1;
//            if (map[x][y] != NO)
//                goto next;
//            judgeEmpty(map, x, y, WHITE);
//            //判断胜利
//            ret = judgeWin(map, x, y);
//            if (ret == BLACK)
//            {
//                printf("黑方获胜\n");
//                return;
//            }
//            else if (ret == WHITE)
//            {
//                printf("白方获胜\n");
//                return;
//            }
//        }
//    }
//    else if (choice == 2)
//    {
//        while (1)
//        {
//            int x = -1;
//            int y = -1;
//        next2:
//            x = rand() % 15 + 1;
//            y = rand() % 15 + 1;
//            if (map[x][y] != NO)
//                goto next2;
//            judgeEmpty(map, x, y, BLACK);
//            //判断胜利
//            int ret = judgeWin(map, x, y);
//            if (ret == BLACK)
//            {
//                printf("黑方获胜\n");
//                return;
//            }
//            else if (ret == WHITE)
//            {
//                printf("白方获胜\n");
//                return;
//            }
//        white:
//            while (1)
//            {
//                printf("白方落子\n");
//                printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);
//                scanf("%d%d", &x, &y);
//                if (x < 0 || x > N || y < 0 || y > N)
//                    printf("错误输入\n");
//                else
//                    break;
//            }
//            judgeEmpty(map, x, y, WHITE);
//            //判断胜利
//            ret = judgeWin(map, x, y);
//            if (ret == BLACK)
//            {
//                printf("黑方获胜\n");
//                return;
//            }
//            else if (ret == WHITE)
//            {
//                printf("白方获胜\n");
//                return;
//            }
//            if (retract(map, x, y) == 1)
//                goto white;
//
//        }
//    }
//
//}void peopleFight(int map[][N + 1])
{printf("--------人-人对战---------------\n");initMap(map);while (1){int x = -1;int y = -1;black:while (1){printf("黑方落子\n");printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, BLACK);if (retract(map, x, y) == 1)goto black;//判断胜利int ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}white:while (1){printf("白方落子\n");printf("请输入要落下的坐标现在棋盘为%d*%d\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, WHITE);if (retract(map, x, y) == 1)goto white;//判断胜利ret = judgeWin(map, x, y);if (ret == BLACK){printf("黑方获胜\n");return;}else if (ret == WHITE){printf("白方获胜\n");return;}}
}int retract(int map[][N + 1], int x, int y)
{int choice = -1;printf("是否悔棋:是1\n");scanf("%d", &choice);if (choice == 1){map[x][y] = NO;initMap(map);}return choice;
}
void AIjudge(int color, int map[N+1][N+1])
{int num = 1, left = 0, right = 0;int n, m, score = 0, max = 0;int dx, dy;for (int i = 1; i < N+1; i++){for (int j = 1; j < N+1; j++){score = 0;if (map[i][j] != 0)continue;else{dx = 1, dy = 0, n = i, m = j;while (1)//水平向右{n += dx, m += dy;if (map[n][m] == 0){right = 0; break;}else if (map[n][m] != color || n > 15){right++; break;}else if (num < 5) { num++; }}dx = -1, dy = 0;while (1) {//水平向左n += dx; m += dy;if (map[n][m] == 0) { left = 0; break; }else if (map[n][m] != color || n < 1) { left++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);//用data来算分数,并用score来记录//  |方向num = 1; right = 0, left = 0;//每一次改变方向要重置这些变量dx = 0; dy = -1; n = i; m = j;//向上while (1) {n += dx; m += dy;if (map[n][m] == 0) { left = 0; break; }else if (map[n][m] != color || m < 1) { left++; break; }else if (num < 5) { num++; }}//向下dx = 0; dy = 1; n = i; m = j;while (1) {n += dx; m += dy;if (map[n][m] == 0) { right = 0; break; }else if (map[n][m] != color || m > 15) { right++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);//  \方向num = 1; right = 0, left = 0;dx = 1; dy = 1; n = i; m = j;//向右下while (1) {n += dx; m += dy;if (map[n][m] == 0) { right = 0; break; }else if (map[n][m] != color || m > 15 || n > 15) { right++; break; }else if (num < 5) { num++; }}//向左上dx = -1; dy = -1; n = i; m = j;while (1) {n += dx; m += dy;if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }else if ((n > 0 && m > 0 && map[n][m] != color) || m < 1 || n < 1) { left++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);//  /方向`num = 1; right = 0, left = 0;dx = 1; dy = -1; n = i; m = j;//向右上while (1) {n += dx; m += dy;if (map[n][m] == 0) { right = 0; break; }else if (map[n][m] != color || n > 15 || m < 1) { right++; break; }else if (num < 5) { num++; }}//向左下dx = -1; dy = 1; n = i; m = j;while (1) {n += dx; m += dy;if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }else if ((n > 0 && m > 0 && map[n][m] != color) || n < 1 || m > 15) { left++; break; }else if (num < 5) { num++; }}score += Data(num, right + left);if (score > max) {//每一次用max保存分数,下一次比较,最后找出最大值max = score;position[0] = i;//用来保存每一次的位置和分数position[1] = j;position[2] = score;}}}}
}
int Data(int num, int count)
{switch (num){case 1:	if (count == 0)//活一:表示在该处落子,就只有这一个棋子,两边都没有阻挡(边界或对方的棋子)优势较大return 2;else if (count == 1)//冲一:表示在该处落子,就只有这一个棋子,两边有一种阻挡(边界或对方的棋子)优势较小return 1;else return 0;break;case 2:if (count == 0)//活二;接下来都同理活一和冲一return 20;else if (count == 1)//冲二return 10;else return 0;break;case 3:if (count == 0)//活三return 300;else if (count == 1)//冲三return 50;else return 0;break;case 4:if (count == 0)//活四return 4000;else if (count == 1)//冲四return 1000;else return 0;break;case 5://五return 5000;break;default:return 0;break;}
}
void machine(int map[][N + 1])
{printf("--------人-机对战---------------\n");int choice = -1;do {printf("请输入你执黑棋还是白棋,黑1,白2\n");scanf("%d", &choice);} while (choice != 1 && choice != 2);initMap(map);if (choice == 1){while (1){int x = -1;int y = -1;black:while (1){printf("黑方落子\n");printf("现在棋盘为%d*%d请输入要落下的坐标x y\n", N, N);scanf("%d%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, BLACK);if (retract(map, x, y)){map[x][y] = 0;initMap(map);goto black;}int ret = judgeWin(map, x, y);if (ret == BLACK)       //判断胜利break;int old_max = 0, new_max = 0, n = 0, m = 0;int AIx = -1, AIy = -1;AIjudge(1, map);//判断黑子的优势位置old_max = position[2];//保存该位置分数AIx = position[0]; AIy = position[1];//保存该位置的坐标,注意行列和xy轴的对应关系position[0] = 0, position[1] = 0, position[2] = 0;AIjudge(-1, map);//判断白子的优势位置new_max = position[2];//保存分数if (new_max >= old_max) //判断哪个位置的分数大,从而判断是堵截还是进攻{AIx = position[0]; AIy = position[1];}judgeEmpty(map, AIx, AIy, WHITE);ret = judgeWin(map, x, y);if (ret == WHITE)       //判断胜利break;}}else if (choice == 2){while (1){int x = -1, y = -1;int old_max = 0, new_max = 0, n = 0, m = 0;int AIx = -1, AIy = -1;AIjudge(1, map);//判断黑子的优势位置old_max = position[2];//保存该位置分数AIx = position[0]; AIy = position[1];//保存该位置的坐标,注意行列和xy轴的对应关系position[0] = 0, position[1] = 0, position[2] = 0;AIjudge(-1, map);//判断白子的优势位置new_max = position[2];//保存分数if (new_max >= old_max) //判断哪个位置的分数大,从而判断是堵截还是进攻{AIx = position[0]; AIy = position[1];}judgeEmpty(map, AIx, AIy, BLACK);int ret = judgeWin(map, x, y);if (ret == BLACK)       //判断胜利 break;white:while (1){printf("白方落子\n");printf("现在棋盘为%d*%d请输入要落下的坐标x y\n", N, N);scanf("%d,%d", &x, &y);if (x < 0 || x > N || y < 0 || y > N)printf("错误输入\n");elsebreak;}judgeEmpty(map, x, y, WHITE);if (retract(map, x, y)){map[x][y] = 0;initMap(map);goto white;}ret = judgeWin(map, x, y);if (ret == WHITE)       //判断胜利break;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/40230.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

‘艾’公益——微笑行动「广安站」为艾祝福,让笑起舞

艾多美“微笑行动”广安站拉开帷幕 此次爱心帮助7名唇腭裂患儿 重新绽放微笑 艾多美“微笑行动”广安站拉开帷幕 此次爱心帮助7名唇腭裂患儿 重新绽放微笑 不让笑容留有缺憾 每个孩子都有微笑的权利 艾多美向唇腭裂儿童伸出援手 绽放笑容&#xff0c;拥抱全新的未来 2…

进程、程序、应用程序之间的关系

文章目录 进程和程序进程和应用程序总结参考资料 进程和程序 程序&#xff1a;程序是存放在硬盘中的可执行文件&#xff0c;主要包括代码指令和数据。程序本身是一个静态的文件&#xff0c;只有在被操作系统加载到内存中并执行时才会变成进程。 进程&#xff1a;进程是程序在…

卫星轨道平面简单认识

目录 一、轨道平面 1.1 轨道根数 1.2 应用考虑 二、分类 2.1 根据运行高度 2.2 根据运行轨迹偏心率 2.3 根据倾角大小 三、卫星星座中的轨道平面 四、设计轨道平面的考虑因素 一、轨道平面 1.1 轨道根数 轨道平面是定义卫星或其他天体绕行另一天体运动的平面。这个平…

第十六章 Qt的文件处理操作详解

目录 一、基本文件操作 二、二进制文件读写 三、文本文件读写 四、操作例子 1、QTextStream的流操作符 一、基本文件操作 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。在所有的 I/O 设备中,文件 I/O 是最重要的部分之…

TF-IDF和BM25原理和区别

TF-IDF TF-IDF是TF&#xff08;词频&#xff0c;Term Frequency&#xff09;和IDF&#xff08;逆文档频率&#xff0c;Inverse Document Frequency&#xff09;的乘积。我们先来看他们分别是怎么计算的&#xff1a; TF的计算有多种方式&#xff0c;常见的是 除以文章总词数是…

从CPU的视角看C++的构造函数和this指针

从汇编角度&#xff0c;清晰的去看构造函数和this指针到底是个什么东西呢&#xff1f;也许可以解决你的一点小疑问 首先写一个很简单的代码demo&#xff1a; class A{ public:int a;A(){;}void seta(int _a){a_a;}A* getA(){return this;} };int fun1(int px){return px; }in…

【FreeRTOS】同步互斥与通信 有缺陷的同步示例

目录 1 同步互斥与通信1.1 同步互斥与通信概述1.2 同步与互斥的概念1.3 同步的例子&#xff1a;有缺陷1.4 freertos.c源码3. 互斥的例子&#xff1a;有缺陷4. 通信的例子&#xff1a;有缺陷5. FreeRTOS的解决方案 1 同步互斥与通信 1.1 同步互斥与通信概述 参考《FreeRTOS入门…

搞钱四步:干活、出名、破圈、整合

搞钱这事儿&#xff0c;说起来有四步&#xff1a;干活、出名、破圈、整合。 咱们现在这个时代&#xff0c;谁要是能把自尊心放一边&#xff0c;勇敢站到舞台上展示才华&#xff0c;变现那是分钟的事儿。 只要你敢承认自己想要财富&#xff0c;并且不停地使用正确的方法论&…

python语句前面有一个$是什么意思

“$”是汇编语言中的一个预定义符号&#xff0c;等价于当前正汇编到的段的当前偏移值。例如&#xff1a;指令“jmp $3”中的“$”表示当前这条指令在代码段中的偏移量。 代表当前指令的地址&#xff0c;如&#xff1a; data segment str1 db a,b,c,d leng equ $-str 就是当前地…

JVM专题之性能优化

运行时优化 方法内联 > 方法内联,是指 **JVM在运行时将调用次数达到一定阈值的方法调用替换为方法体本身** ,从而消除调用成本,并为接下来进一步的代码性能优化提供基础,是JVM的一个重要优化手段之一。 > > **注:** > > * **C++的inline属于编译后内联,…

知名品牌因商标痛失市场:114家直营店山寨店7000多家!

奶茶知名品牌“鹿角巷”当年红遍大江南北&#xff0c;是最早的新茶饮品牌&#xff0c;但是当年商标注册存在问题&#xff0c;被同行奶茶品牌抢占了先机&#xff0c;发声明“对大陆商标注册细则不详&#xff0c;在商标注册过程中让假店钻了法律空档”&#xff0c;最夸张的时候全…

如何用Python向PPT中批量插入图片

办公自动化办公中&#xff0c;Python最大的优势是可以批量操作&#xff0c;省去了用户粘贴、复制、插入等繁琐的操作。经常做PPT的朋友都知道&#xff0c;把图片插入到PPT当中的固定位置是一个非常繁琐的操作&#xff0c;往往调整图片时耗费大量的时间和精力。如何能省时省力插…

windows启动Docker闪退Docker desktop stopped

Windows启动Docker闪退-Docker desktop stopped 电脑上很早就安装有Docker了&#xff0c;但是有一段时间都没有启动了&#xff0c;今天想启动启动不起来了&#xff0c;打开没几秒就闪退&#xff0c;记录一下解决方案。仅供参考 首先&#xff0c;参照其他解决方案&#xff0c;本…

【刷题汇总--游游的you、腐烂的苹果、孩子们的游戏(圆圈中最后剩下的数)】

C日常刷题积累 今日刷题汇总 - day0051、游游的you1.1、题目1.2、思路1.3、程序实现 - 蛮力法1.4、程序实现 - 贪心(优化) 2、腐烂的苹果2.1、题目2.2、思路2.3、程序实现 - bfs 3、孩子们的游戏(圆圈中最后剩下的数)3.1、题目3.2、思路3.3、程序实现 -- 环形链表3.4、程序实现…

2个方法教你轻松移除pdf文件编辑限制

PDF是一种常见的办公文档格式&#xff0c;常用于文件共享和保护。然而&#xff0c;有时候我们需要编辑PDF文件中的内容&#xff0c;但受到了编辑限制。本文将介绍一些有效的方法&#xff0c;帮助您解除PDF的编辑限制&#xff0c;轻松进行编辑和修改。 一、通过密码取消PDF“限制…

雷电模拟器报错remount of the / superblock failed: Permission denied remount failed

报错截图 解决方法 打开设置 设置配置system.vmdk可写入 解决

Transformer和Mamba强强结合!最新混合架构全面开源,推理速度狂飙8倍

最近发现&#xff0c;将Mamba和Transformer模块混合使用&#xff0c;效果会比单独使用好很多&#xff0c;这是因为该方法结合了Mamba的长序列处理能力和Transformer的建模能力&#xff0c;可以显著提升计算效率和模型性能。 典型案例如大名鼎鼎的Jamba&#xff1a;Jamba利用Tr…

Python统计实战:时间序列分析之简单指数平滑和Holt指数平滑

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能&#xff0c;从而更快地掌握解决问题所需的能力。 &#xff08;以下练习题来源于《统计学—基于Python》。请在Q群455547227下载原始数据。&#xff09; 练习题 下表是某只股票…

金属3D打印如何精准选材

随着3D打印技术的飞跃发展&#xff0c;模具制造领域迎来了前所未有的创新机遇。在众多3D打印技术中&#xff0c;SLM金属3D打印以其精度高、复杂结构成型能力&#xff0c;成为众多行业的优选。然而&#xff0c;金属打印材料&#xff0c;如何精准选择&#xff0c;以最大化满足项目…

linux 内核打印log太多咋办?

有时候发现&#xff0c;linux 内核打印太多消息了&#xff0c;对有用消息造成了干扰&#xff0c;如果你一个个源文件去关闭打印太麻烦了&#xff0c;有没有一种更方便的方式来关闭这些消息呢&#xff1f; 对这个需求&#xff0c;内核提供了一个强大而又灵活的方式&#xff0c;…