【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("错误输入");
        else
            break;
    }
    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], "━┓");
                else
                    draw_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], "━┛");
                else
                    draw_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], "━┫");
                else
                    draw_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");
            else
                break;
        }
        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");
            else
                break;
        }
        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");
                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 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");
                else
                    break;
            }
            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");
                else
                    break;
            }
            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("错误输入");
        else
            break;
    }
    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], "━┓");
                else
                    draw_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], "━┛");
                else
                    draw_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], "━┫");
                else
                    draw_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");
            else
                break;
        }
        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");
            else
                break;
        }
        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");
                else
                    break;
            }
            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");
                else
                    break;
            }
            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.mfbz.cn/a/774756.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

The Sandbox 人物化身每月奖励: 七月版来了!

人物化身的持有者可以从 The Sandbox 领取自己的队服&#xff01; 视频&#xff1a;https://youtu.be/tSo5FPL7DhE 我们又推出了人物化身所有者月度奖励&#xff01;在七月&#xff0c;我们将通过 The Sandbox 队服来弘扬体育竞技精神。穿上这些时尚的元宇宙队服&#xff0c;代…

深度报告 | 百度安全携手极越安全发布《整车安全渗透测试白皮书》

注重点&#xff0c;如何确保车辆全生命周期的安全已成为整个行业亟待解决的问题。对于车企而言&#xff0c;通过渗透测试尽量多地发现安全威胁&#xff0c;是确保车辆信息系统的稳定运行、保障用户安全驾驶至关重要的措施。然而&#xff0c;传统的渗透测试方法已无法满足智能网…

Linux miniconda 安装tensorflow-gpu遇到找不到GPU问题

背景&#xff1a; Linux Miniconda python3.9 安装步骤 1、 pip install tensorflow-gpu2.8.0 -i https://pypi.tuna.tsinghua.edu.cn/simple 2、报错如下&#xff1a; 更换镜像源&#xff0c;单独安装 pip install tf-estimator-nightly2.8.0.dev2021122109 -i https:/…

使用 docker buildx 构建跨平台镜像

buildx是Docker官方提供的一个构建工具&#xff0c;它可以帮助用户快速、高效地构建Docker镜像&#xff0c;并支持多种平台的构建。使用buildx&#xff0c;用户可以在单个命令中构建多种架构的镜像&#xff0c;例如x86和arm架构&#xff0c;而无需手工操作多个构建命令。此外bu…

【docker】容器内配置环境变量

背景&#xff1a; 我要把下面的环境变量写到bash脚本里&#xff0c;起名叫environment_start.sh。 目的&#xff1a; 用于每次进入容器dev_into.sh的时候&#xff0c;让系统获取到环境变量。 操作步骤&#xff1a; 先在容器外找个合适的位置写环境变量bash脚本&#xff0c…

bmob Harmony鸿蒙快速开发搜索功能

搜索功能是很多应用都需要的功能。在很多平台上&#xff0c;要开发一个兼容性较好的搜索功能都还是需要添加比较多的视图代码的。 为了解决这个问题&#xff0c;鸿蒙ArkUI提供了一个快速添加搜索功能的视图组件给我们&#xff0c;结合Bmob Harmony鸿蒙SDK的搜索能力&#xff0…

四款主流电脑监控软件(电脑监控软件主要优势)

在现代企业环境中&#xff0c;确保员工的工作效率和企业信息的安全成为了管理者的重要任务。电脑监控软件作为一种有效的管理工具&#xff0c;能够帮助企业实现这些目标。固信电脑监控软件在这方面表现尤为出色&#xff0c;本文将详细介绍固信电脑监控软件的优势及其主要功能&a…

【C++】 解决 C++ 语言报错:Use of Uninitialized Variable

文章目录 引言 使用未初始化的变量&#xff08;Use of Uninitialized Variable&#xff09;是 C 编程中常见且危险的错误之一。它通常在程序试图使用尚未赋值的变量时发生&#xff0c;导致程序行为不可预测&#xff0c;可能引发运行时错误、数据损坏&#xff0c;甚至安全漏洞。…

基于芯片CSU8RP1382开发的咖啡秤方案

咖啡电子秤芯片方案精确值可做到分度值0.1g的精准称重,并带有过载提示、自动归零、去皮称重、压低报警等功能&#xff0c;工作电压在2.4V~3.6V之间&#xff0c;满足于咖啡电子秤的电压使用。同时咖啡电子秤PCBA设计可支持四个单位显示&#xff0c;分别为&#xff1a;g、lb、oz、…

云仓酒庄天津分公司:深化业务常态化运营

标题&#xff1a;云仓酒庄天津分公司&#xff1a;深化业务常态化运营&#xff0c;以沙龙为纽带&#xff0c;构建价值叠加的酒业新生态 在当今复杂多变的经济环境中&#xff0c;传统酒业面临着前所未有的挑战与机遇。随着数字化转型的加速和消费者偏好的日益多元化&#xff0c;…

JAVA--JSON转换工具类

JSON转换工具类 import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackso…

2024年保安员职业资格考试题库大数据揭秘,冲刺高分!

186.安全技术防范是一种由探测、&#xff08;&#xff09;、快速反应相结合的安全防范体系。 A.保安 B.出警 C.延迟 D.监控 答案&#xff1a;C 187.安全技术防范是以&#xff08;&#xff09;和预防犯罪为目的的一项社会公共安全业务。 A.预防灾害 B.预防损失 C.预防失…

StreamSets: 数据采集工具详解

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 欢迎关注微信公众号&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&a…

【EI会议/稳定检索】2024年应用数学、化学研究与物理工程国际会议(AMPE 2024)

2024 International Conference on Applied Mathematics, Chemical Research, and Physical Engineering 2024年应用数学、化学研究与物理工程国际会议(AMPE 2024) 【会议信息】 会议简称&#xff1a;AMPE 2024 大会时间&#xff1a;点击查看 截稿时间&#xff1a;官网查看 大…

【T+】畅捷通T+产品,将原财务报表中的模板转换到财务报表菜单下。

【问题描述】 畅捷通T3产品中账套使用行业性质是【新会计准测制度】升级到畅捷通T+产品, 行业性质默认为【2001年企业会计制度】, 但是升级成功后,账套的财务报表下没有对应报表模板,需要手工编辑,太费劲了。 并且在T+产品中新建账套,行业性质选择【2001年企业会计制度】…

verilog行为建模(一):基本概念

目录 1.行为描述2.过程(procedural)块3.过程赋值(procedural assignment)4.过程时序控制5.简单延时6.边沿敏感时序7.wait语句 微信公众号获取更多FPGA相关源码&#xff1a; 1.行为描述 行为级描述是对系统的高抽象级描述。在这个级别&#xff0c;表达的是输入和输出之间转换…

比 PIP 快 100 倍的安装工具

uv 是一个由 Rust 开发的 pip 工具&#xff0c;比 pip 快 100 倍&#xff0c;难以置信&#xff0c;不过真的是快太多了。 安装 在 Mac 上直接通过 brew install uv 安装即可。 venv 创建运行环境&#xff0c;默认当前目录下 .venv uv venv 依赖安装 uv pip install -r re…

【Mathematica14.0】快速从下载安装到使用

目录 1.简介 2.下载安装 下载 安装 3.一小时掌握mathematica使用 单元模式 内置函数 符号表达式 迭代器 赋值 通配符及查找替换 函数定义 匿名函数&#xff08;拉姆达表达式&#xff09; 函数映射 函数式与运算符 函数自定义选项 图形可视化 交互式界面 数值…

深度神经网络语言识别

「AI秘籍」系列课程&#xff1a; 人工智能应用数学基础人工智能Python基础人工智能基础核心知识人工智能BI核心知识人工智能CV核心知识 使用 DNN 和字符 n-gram 对一段文本的语言进行分类&#xff08;附 Python 代码&#xff09; 资料来源&#xff0c;flaticon&#xff1a;htt…

京东金融大数据分析平台总体架构:剖析和解读

京东金融大数据分析平台总体架构&#xff1a;剖析和解读 在现代金融行业中&#xff0c;大数据分析已成为决策支持和业务创新的重要工具。京东金融凭借其强大的大数据分析平台&#xff0c;成功地将海量数据转化为洞察力&#xff0c;为企业和用户提供优质服务。本文将深入探讨京…