c语言实现五子棋代码(有简单的人机对战,附解析)


前段时间,我和我的小伙伴一起做了关于五子棋的小的团队项目,我将其中一些非核心的内容简化了一下,保留了核心的内容,今天我就和你们来分享一下我们所做小项目。

因为我们定义了比较多的函数,所以我将其每个函数都单独讲解,在这个项目中,我做了两个人机对战,一个非常简单的,一个简单的。

(声明函数就不展示了)
int flag = 0;
int map[19][19];
我们先定义两个全局变量。
其中flag变量用来表示这个回合谁落子,偶数表示黑方落子,基数表示白方落子。
数组中的数组代表子的颜色,2表示黑子,1表示白字。
system(“cls”); 用来清屏。

主函数

int main() {

menuView();
return 0;

}
这里主要是调用菜单界面函数。

游戏界面函数

void gameView(void) {

int n, q, w, e = 0, r = 0, t, y, b, m, i = 0;
while (1) {
    init();
    gameView_ShowMap();
    while (i == 0) {
    
        if (flag % 2 == 0 && e != 2) {
            printf("请输入黑子坐标(输入20 20)暂停");
            scanf("%d %d", &q, &w);
            if (q + w >= 40)
                zantingView();
            t = playerMove(q, w);
            if (t == 2) {
            
                printf("落子成功\n");
            }
            e = isWin(q, w);
            if (e == 2) {
                printf("黑子赢\n");
                printf("白子输\n");
                jieshuView();

            }
        }
        if (flag % 2 == 1 && r != 1) {
            printf("请输入白子坐标(输入20 20)暂停");
            scanf("%d %d", &q, &w);
            if (q + w >= 40)
                zantingView();
            y = playerMove(q, w);
            if (y == 1) {
                printf("落子成功\n");
            }
            r = isWin(q, w);
            if (r == 1) {
                printf("白子赢\n");
                printf("黑子输\n");
                jieshuView();
            }
        }
    };
}
return;

}
在这里我们先初始化棋盘(也就是void init(void)),之后打印棋盘。
然后我们就可以输入想要落子的坐标了,在这里如果我们输入20 20那么就会进入暂停界面,当我们输入了落子坐标后,会将我们输入的坐标作为参数传入到落子的函数当中,如果成功落子,那么就会返回一个y=1的值,之后我们通过检测y的值就可以判断我们是否落子成功了。如果成功了,那么我们就可以调用胜利判断的函数,进行胜利的判断。判断胜利函数会返回一个值,我们可以通过检测函数返回的值来判断是否胜利,如果胜利了,那么我们就会打印哪一方赢了,哪一方输入,并且调用结算节目函数。

菜单界面函数

void menuView(void) {

while (1) {
    printf("1. 面对面模式\n");
    printf("2. 人机对战\n");
    printf("3. 进入设置\n");
    printf("4. 退出游戏\n");
    printf("请输入序号:");
    int choose;
    scanf("%d", &choose);
    switch (choose) {
    case 1:
        system("cls");
        gameView();
        break;
    case 2:
        system("cls");
        nanduView();
    case 3:
        printf("敬请期待\n");
        break;
    case 4:
        exit(0);
        break;
    default:
        break;
    }
}

}
进入了菜单函数,我们就可以进行选择,在这里 system(“cls”); 是用来进行清屏的,避免许多界面堆在一起。

暂停键界面函数

void zantingView(){

int x = 0,y;
printf("1.结束对局\n");
printf("2.返回游戏\n");
printf("请输入编号:\n");
scanf("%d", &x);

if (x != 1 && x != 2)
{
    printf("输入错误,请重新输入");
    scanf("%d", &x);
}

switch (x) {
case 1:
    if (flag % 2 == 1) {
        system("cls");
        printf("黑子赢\n");
        printf("白子输\n");
        jieshuView();
        
    }
    if (flag % 2 == 0) {
        system("cls");
        printf("白子赢\n");
        printf("黑子输\n");
        jieshuView();
    }
    break;
case 2:
    return;
default:
    break;
}
return;

}
暂停界面我们可以进行选择,如果选择结束游戏,那么就直接调用结算界面函数。

最简单人机对战函数

void jiandanView() {

int q, w, e = 0, t, r = 0;
while (1) {
    init();
    gameView_ShowMap();
    while (1) {
        if (flag % 2 == 0 && e != 2) {
            printf("请输入黑子坐标(输入20 20)暂停");
            scanf("%d %d", &q, &w);
            if (q + w >= 40)
                zantingView();
            t = playerMove(q, w);
            if (t == 2) {
                printf("落子成功\n");
            }
            e = isWin(q, w);
            if (e == 2) {
                printf("黑子赢\n");
                printf("白子输\n");
                jieshuView();

            }
        }
        if (flag % 2 == 1 && r != 1) {
            q = rand() % 20;
            w = rand() % 20;
            playerMove(q, w);
            r = isWin(q, w);
            if (r == 1) {
                printf("白子赢\n");
                printf("黑子输\n");
                jieshuView();
            }
        }
    }
}

}
玩家部分和前文的游戏界面函数相同,我这里主要讲解一下人机如何落子。
在这个函数中,我们采用了随机函数来生成随机数用来进行人机落子。
我们生成了两个随机数,代表两个坐标。

简单人机对战函数

void renjiView() {

int q, w, e = 0, t, r = 0, p = 0, k = 0;
while (1) {
    init();
    gameView_ShowMap();
    while (1) {
        if (flag % 2 == 0 && e != 2) {
            printf("请输入黑子坐标(输入20 20)暂停");
            scanf("%d %d", &q, &w);
            if (q + w >= 40)
                zantingView();
            t = playerMove(q, w);
            if (t == 2) {
                printf("落子成功\n");
            }
            e = isWin(q, w);
            if (e == 2) {
                printf("黑子赢\n");
                printf("白子输\n");
                jieshuView();
            }
        }
        if (flag % 2 == 1 && r != 1) {
            p = rand() % 8;
            switch (p) {
            case 1:
                if (map[q - 1][w - 1] == 0 && q - 1 > 0 && q - 1 < 18 && w - 1 > 0 && w - 1 < 18) {
                    map[q - 1][w - 1] = 1;
                    gameView_ShowMap();
                    k = isWin(q - 1, w - 1);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            case 2:
                if (map[q][w - 1] == 0 && q > 0 && q < 18 && w - 1 > 0 && w - 1 < 18) {
                    map[q][w - 1] = 1;
                    gameView_ShowMap();
                    k = isWin(q, w - 1);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;

                }
                else
                    p = rand() % 8;
                continue;
            case 3:
                if (map[q + 1][w - 1] == 0 && q + 1 > 0 && q + 1 < 18 && w - 1 > 0 && w - 1 < 18) {
                    map[q + 1][w - 1] = 1;
                    gameView_ShowMap();
                    k = isWin(q + 1, w - 1);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            case 4:
                if (map[q + 1][w] == 0 && q + 1 > 0 && q + 1 < 18 && w > 0 && w < 18) {
                    map[q + 1][w] = 1;
                    gameView_ShowMap();
                    k = isWin(q + 1, w);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            case 5:
                if (map[q + 1][w + 1] == 0 && q + 1 > 0 && q + 1 < 18 && w + 1 > 0 && w + 1 < 18) {
                    map[q + 1][w + 1] = 1;
                    gameView_ShowMap();
                    k = isWin(q + 1, w + 1);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            case 6:
                if (map[q][w + 1] == 0 && q > 0 && q < 18 && w + 1 > 0 && w + 1 < 18) {
                    map[q][w + 1] = 1;
                    gameView_ShowMap();
                    k = isWin(q, w + 1);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            case 7:
                if (map[q - 1][w + 1] == 0 && q - 1 > 0 && q - 1 < 18 && w + 1 > 0 && w + 1 < 18) {
                    map[q - 1][w + 1] = 1;
                    gameView_ShowMap();
                    k = isWin(q - 1, w + 1);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            case 8:
                if (map[q - 1][w] == 0 && q - 1 > 0 && q - 1 < 18 && w > 0 && w < 18) {
                    map[q - 1][w] = 1;
                    gameView_ShowMap();
                    k = isWin(q - 1, w);
                    if (k == 1) {
                        printf("白子赢\n");
                        printf("黑子输\n");
                        jieshuView();
                    }
                    ++flag;
                    break;
                }
                else
                    p = rand() % 8;
                continue;
            default:
                break;
            }

        }
    }
}

}
这里我们的主要思路是,在玩家落子的四周随机落子来达到类似围堵的效果,if里许多的判断条件为了避免数组越界,并且在人机落子之后,我们调用判断胜利函数来判断人机是否胜利,最后用随机函数重新生成一个数。

落子函数

int playerMove(int x, int y) {

extern int flag;
extern int map[19][19];
if (map[x][y] == 0&&(x+y)<40&&x>0&&y>0) {
    if (flag % 2 == 0) {
        map[x][y] = 2;
        flag++;
        gameView_ShowMap();
        return 2;
    }
    else if (flag % 2 == 1) {
        map[x][y] = 1;
        flag++;
        gameView_ShowMap();
        return 1;
    }
}

}
在这里,我们先判断玩家输入的坐标是否符合我们的要求,如果符合了,那么就改变数组内对应的值,并且返回一个值用以判断是否落子成功。

判断胜利函数

int isWin(int x, int y) {

int b = 0, k, c, d,z;
extern int map[19][19];
if (map[x][y] == 2) {
    b += 1;
    for (k = 1; map[x - k][y - k] == 2; k++)
        b += 1;
    for (k = 1; map[x + k][y + k] == 2; k++)
        b += 1;
    for (k = 1, z = 1; map[x - k][y + k] == 2; k++)
        z += 1;
    for (k = 1; map[x + k][y - k] == 2; k++)
        z += 1;
    for (k = 1, c = 1; map[x + k][y] == 2; k++)
        c += 1;
    for (k = 1; map[x - k][y] == 2; k++)
        c += 1;
    for (k = 1, d = 1; map[x][y + k] == 2; k++)
        d += 1;
    for (k = 1; map[x][y - k] == 2; k++)
        d += 1;
    if (b >= 5 || c >= 5 || d >= 5 || z >= 5)
        return 2;

}
int e = 0, h, f, g,n;
if (map[x][y] == 1) {
    e += 1;
    for (h = 1; map[x - h][y - h] == 1; h++)
        e += 1;
    for (h = 1; map[x + h][y + h] == 1; h++)
        e += 1;
    for (k = 1, n = 1; map[x - k][y + k] == 2; k++)
        n += 1;
    for (k = 1; map[x + k][y - k] == 2; k++)
        n += 1;
    for (h = 1, f = 1; map[x + h][y] == 1; h++)
        f += 1;
    for (h = 1; map[x - h][y] == 1; h++)
        f += 1;
    for (h = 1, g = 1; map[x][y + h] == 1; h++)
        g += 1;
    for (h = 1; map[x][y - h] == 1; h++)
        g += 1;
    if (e >= 5 || f >= 5 || g >= 5 || n>=5)
        return 1;


}

}
这个判断胜利的函数看似复杂,其实并不怎么复杂,我们将玩家输入的坐标作为参数,开始逐个查找,先是左上方,右下方,之后是右上方,右下方,之后是正下方和正上方,之后是正右方,正左方逐个查找,最后判断是否满足胜利的条件,如果满足,就返回一个值到游戏界面函数,之后游戏界面函数通过判断这个值进入游戏结算函数

初始化棋盘函数

void init(void) {

extern int flag;
extern int map[19][19];
for (int i = 0; i < 19; i++)
{
    for (int j = 0; j < 19; j++)
    {
        map[i][j] = 0;
    }
}
flag = 0;
return;

}
这个函数通过两个循环将map数组初始化以便进行游戏。

打印棋盘函数

void gameView_ShowMap(void) {

extern int map[19][19];
int b = 0;
printf("            口为黑棋,龘为白棋,十为空地\n");
printf("   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18\n");
for (int i = 0; i < 19; i++) {
    printf("%-2d ", b++);
    for (int j = 0; j < 19; j++) {
        if (map[i][j] == 0) {
            printf("十 ");
        }
        else if (map[i][j] == 1) {
            printf("龘 ");
        }
        else {
            printf("口 ");
        }
    }
    printf("\n");
}
return;

}
这个函数用来打印棋盘,如果是空白就为十,黑子就为口,白字就为龘。

结算界面函数

void jieshuView() {

int y;
printf("请输入编号:\n");
printf(" 1.退出游戏\n");
printf(" 2.返回菜单\n");
scanf_s("%d", &y);
if (y != 1 && y != 2) {
    printf("输入错误,请重新输入:");
    scanf_s("%d", &y);
}
switch (y) {
case 1:
    exit(0);
    break;
case 2:
    system("cls");
    menuView();
    break;
default:
    break;
}

}
结算界面函数让我们进行选择,我们可以选择返回菜单继续游戏,也可以直接退出游戏

暂停界面

void zantingView() {

int x = 0,y;
printf("1.结束对局\n");
printf("2.返回游戏\n");
printf("请输入编号:\n");
scanf("%d", &x);

if (x != 1 && x != 2)
{
    printf("输入错误,请重新输入");
    scanf("%d", &x);
}

switch (x) {
case 1:
    if (flag % 2 == 1) {
        system("cls");
        printf("黑子赢\n");
        printf("白子输\n");
        jieshuView();
        
    }
    if (flag % 2 == 0) {
        system("cls");
        printf("白子赢\n");
        printf("黑子输\n");
        jieshuView();
    }
    break;
case 2:
    return;
default:
    break;
}
return;

}
暂停界面我们有两个选择,一个是返回游戏,一个是结束游戏,如果结束游戏那么就直接进入游戏结算函数,如果返回游戏,则游戏继续。

至此,代码讲解完毕。
(本人是新手写作,可能有很多地方没有解释清楚并且可能有一些出错的地方,请大家谅解,由于自己技术不足,代码可读性可能很差,在这里我说一声抱歉,也请大家谅解。并且代码可能有许多可以简化的地方,但是我还没发现,也请各位指出。

  • 37
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值