【C语言】实现三子棋(N子棋)+电脑智能算法+万字详解

前言:C语言中的三子棋,有利于总结数组前面的知识,并且是N子棋的基础。本文会一步步讲述如何去实现我们的三子棋代码,以及如何让电脑下棋变得更聪明。本文的重头戏在于电脑下棋的算法中(大家可以通过目录跳过去)希望大家看完后,会有所帮助,避免自己下棋把把老八出局。如有不对,望请斧正!

思路分析

ok,我们在写代码前,首先应该有一步一步的思路,可以先不用想你的代码如何实现,我们可以先把大体框架先构思出来。而在电脑下棋中,我们可以添加进攻算法,防守算法让电脑下棋变得更加聪明。值得注意得是进攻算法的优先级是高于防守算法的。因为最好的防守就是进攻(让电脑快速胜利

为了程序的封装性,安全性,可读性,易维护性,建议大家用多文件的写法去写一个较长的代码。如在三子棋中我们可以构建大体框架

test.c 用于测试游戏的逻辑
game.c 函数的具体实现
game.h 函数的所有声明,头文件,全局定义等。

为了实现目的我们要解决以下函数,当我们建立好以后,就需要我们的game函数来调用这些函数,即如何将这些函数玩成花来。

1.菜单的打印
2.创造棋盘
3.打印棋盘
4.玩家下棋与电脑下棋(包括电脑智能算法,玩家与电脑谁先开始等问题)
5.判断棋盘是否填满
6.判断输赢

具体步骤实现

1.主函数框架

在我们的test.c中放我们最简单的菜单打印,这个时候你的三子棋实现可以统一想像成你的game函数

tese.c

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)
#include "game.h" //自己的文件用""

void menu()
{
    printf("*******************\n");
    printf("***** 1 start *****\n");
    printf("***** 0 quit  *****\n");
    printf("*******************\n");
}

int main()
{
    int num = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("\n请根据菜单选择一个数(1/0): ");
        scanf("%d", &num);
        switch (num)
        {
        case 1:
            printf("下面是棋盘\n");
            game();
            break;
        case 0:
            printf("quit this game...\n");
            break;
        default:
            printf("please chose one again\n");
            break;
        }
    } while (num);
    return 0;
}

上面这些无非是一个简单利用do...while,switch的菜单,以便玩完一遍后可以重来。值得注意的是我们的do...while的特性是先斩后奏。

2.设置棋盘

我们要写3子棋,就需要设置一个3*3的棋盘大小,但意识到我们的棋盘以后可以改变成N子棋,为了方便更改维护,我们采用宏的形式,以后在game.h更改就可以了

//全局变量
#define ROW 3    //行
#define COL 3    //列

接下来我们要初始化棋盘,用我们的空格字符初始化,即每一个棋盘元素都为空,

我们选择字符空格而不选择数字0的原因:
选择0后我们打印出来全是0的3*3棋盘,缺少观赏性,并且我们和电脑下棋的棋子都是字符(#与*)。
void init(char board[ROW][COL], int row, int col)
{
    /*int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            board[i][j] = ' ';
        }
    }*/
    //初始化一块空间,首元素地址知道了,初始为什么呢?初始化多少字节呢?
    memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}

3.打印棋盘

void print(char board[ROW][COL], int row, int col)
{
    int i = 0;
    for (i = 1; i <= 3; i++)
    {
        printf("%d   ", i);
    }
    printf("\n");
    for (i = 0; i < row; i++)
    {
        int j = 0;
        //数据的打印
        for (j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if (j < col - 1)
                printf("|"); //1个数据打印完后,打印|
        }
        printf("%d", i + 1);
        printf("\n");
        //分割行的打印
        if (i < row - 1)
        {
            for (j = 0; j < col; j++)
            {
                printf("___");
                if (j < col - 1)
                    printf("|");
            }
        }
        printf("\n");
    }
}

在打印棋盘中我们值得注意的是如何让我们打印出来的棋盘更利于观赏,以上无法是对于循环的利用

下面是打印棋盘后的效果

4.判断电脑和玩家谁先手

我们在打印出棋盘后,就可判断我们的电脑和玩家谁先手下棋了,这需要我们的rand函数,值得注意的是srand是rand的随机生成器,我们只需要一个生成器,放在main函数里即可。在此之前不要忘记包含头文件<stdlib.h>与<time.h>

void game()
{
    //设置二维数组
    char board[ROW][COL];
    //初始化棋盘
    init(board, ROW, COL);
    //打印棋盘
    print(board, ROW, COL);
    printf("--------游戏开始——---———\n");
    printf("\n");
    //人机对弈
    int tmp = rand() % 2;        //0为玩家先 1为电脑先
    if (0 == tmp)       
    {
       玩家下
       电脑下
    }
    else            
    {
        电脑下
        玩家下
    }
}

这里我们只需要用if判断随机值就可以知道谁先下棋了

5.玩家下棋

我们在写玩家下棋的时候,应该站在用户的角度去看问题比如说用户看3*3数组坐标的时候不会从下标0开始,这就意味着我们在编写玩家下棋函数的时候需要用到x-1,y-1。而且我们在写的时候要考虑到用户输入坐标错误,输入已经有棋子的坐标,这个时候我们可以用循环来解决,一旦输入正常坐标就break跳出循环。

void playerA(char board[ROW][COL], int row, int col)
{
    printf("到你的回合了\n");
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("请输入你要下的坐标: ");
        scanf("%d %d", &x, &y);
        if (x > 0 && x <= row && y > 0 && y <= col)
        {
            if (board[x - 1][y - 1] == ' ')
            {
                board[x - 1][y - 1] = '*';
                break;
            }
            else
                printf("坐标被占用,请重新选择\n");
        }
        else
        {
            printf("输入值越界,请输入3*3坐标\n");
        }
    }
}

6.电脑下棋

ok,到我们的重头戏了。我们先来思考如何将电脑变得跟我们人一样,我们电脑需要知道自己下一步能不能直接取胜,即我们的进攻算法,倘若不能取胜,我们则需要判断玩家是否下一步就可以取得胜利,倘若是,我们就需要去堵玩家的棋子,即我们的防守算法。以上2算法都不满足的话,我们的电脑则可以肆无忌惮的下棋了。

具体实现,我们需要一个变量来判断是否需要进攻。需要的时候返回1,即需要进攻。反之就返回0,即不需要进攻,可以随机下棋。我们的防守算法也一样。 当我们的进攻在防守的判断之前,并且都返回是0的话就可以进行下面的随机下棋。

6.1随机算法

void playerB(char board[ROW][COL], int row, int col)
{
    int x = 0;
    int y = 0;
    printf("电脑下棋\n");
    while (1)
    {
        x = rand() % row;
        y = rand() % col;
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}

6.2进攻算法

此算法有点长,还望耐心看完,其实无非就是电脑判断3行3列以及2对角线中是否有自己可以直接一步取胜的位置,有则直接下棋,无则返回0,再判断我们的防守算法,值得注意的是我们的判断3个条件不要连等,连等只会从左至右依次判断,真为1假为0,可能会影响结果

//电脑进攻函数 q=0随机下 q=1进攻
int attack(char board[ROW][COL], int row, int col)
{
    int q = 0;
    int i = 0;
    //判断行是否有机会
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][0] == '#' && board[i][2] == ' ')
        {
            board[i][2] = '#';
            q = 1;
            return q;
        }
        if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' ')
        {
            board[i][1] = '#';
            q = 1;
            return q;
        }
        if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
        {
            board[i][0] = '#';
            q = 1;
            return q;
        }
    }
    //判断列是否有机会
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[0][i] == '#' && board[2][i] == ' ')
        {
            board[2][i] = '#';
            q = 1;
            return q;
        }
        if (board[0][i] == board[2][i] && board[0][i] == '#' && board[1][i] == ' ')
        {
            board[1][i] = '#';
            q = 1;
            return q;
        }
        if (board[1][i] == board[2][i] && board[1][i] == '#' && board[0][i] == ' ')
        {
            board[0][i] = '#';
            q = 1;
            return q;
        }
    }
    //判断正对角线是否有机会
    if (board[0][0] == board[1][1] && board[0][0] == '#' && board[2][2] == ' ')
    {
        board[2][2] = '#';
        q = 1;
        return q;
    }
    if (board[0][0] == board[2][2] && board[0][0] == '#' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][2] == board[1][1] && board[2][2] == '#' && board[0][0] == ' ')
    {
        board[0][0] = '#';
        q = 1;
        return q;
    }
    //判断反对角线是否有机会
    if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' ')
    {
        board[2][0] = '#';
        q = 1;
        return q;
    }
    if (board[0][2] == board[2][0] && board[0][2] == '#' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][0] == board[1][1] && board[2][0] == '#' && board[0][2] == ' ')
    {
        board[0][2] = '#';
        q = 1;
        return q;
    }
    return q;            //不需要进攻
}

6.3防守算法

接下来就是我们的防守算法,在写我们的进攻算法的时候,是占在电脑是否要去直接取胜角度上的。而在我们的防守算法中核心是去堵玩家的棋。

//电脑防守函数
int defense(char board[ROW][COL], int row, int col)
{
    int q = 0;
    int i = 0;
    //判断行是否有机会
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][0] == '*' && board[i][2] == ' ')
        {
            board[i][2] = '#';
            q = 1;
            return q;
        }
        if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' ')
        {
            board[i][1] = '#';
            q = 1;
            return q;
        }
        if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
        {
            board[i][0] = '#';
            q = 1;
            return q;
        }
    }
    //判断列是否有机会
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[0][i] == '*' && board[2][i] == ' ')
        {
            board[2][i] = '#';
            q = 1;
            return q;
        }
        if (board[0][i] == board[2][i] && board[0][i] == '*' && board[1][i] == ' ')
        {
            board[1][i] = '#';
            q = 1;
            return q;
        }
        if (board[1][i] == board[2][i] && board[1][i] == '*' && board[0][i] == ' ')
        {
            board[0][i] = '#';
            q = 1;
            return q;
        }
    }
    //判断正对角线是否有机会
    if (board[0][0] == board[1][1] && board[0][0] == '*' && board[2][2] == ' ')
    {
        board[2][2] = '#';
        q = 1;
        return q;
    }
    if (board[0][0] == board[2][2] && board[0][0] == '*' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][2] == board[1][1] && board[2][2] == '*' && board[0][0] == ' ')
    {
        board[0][0] = '#';
        q = 1;
        return q;
    }
    //判断反对角线是否有机会
    if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' ')
    {
        board[2][0] = '#';
        q = 1;
        return q;
    }
    if (board[0][2] == board[2][0] && board[0][2] == '*' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][0] == board[1][1] && board[2][0] == '*' && board[0][2] == ' ')
    {
        board[0][2] = '#';
        q = 1;
        return q;
    }
    return q;        //不需要防守
}

7.判断输赢

我们的玩家和电脑每一次下棋后都要用判断输赢算法来判断是否结束了,念此我们需要设定返回值,与之前一样,只需要判断3行3列2对角线即可

’#‘ 电脑胜利
’*‘ 玩家胜利
’Q‘ 平局
’C‘ 继续

为什么要设定这些字符返回值?

因为我们设定字符返回值后,可以在判断输赢里直接返回当前一个棋子,就知道谁赢了(电脑和玩家执不同棋子),更方便我们写判断算法

ok,我们胜利和平局都知道,那么继续呢?这就需要我们的判断棋盘是否排满了,没有则继续,详情看我们的IsFull函数

//判断输赢
//*为玩家
//#为电脑
//Q为平局
//C为继续
char judge(char board[ROW][COL], int row, int col)
{
    int i = 0;
    //判断行
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
        {
            return board[i][0];
        }
    }
    //判断列
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
        {
            return board[0][i];
        }
    }
    //判断对角线
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
    {
        return board[0][0];
    }
    if (board[0][2] == board[1][1] && board[2][1] && board[0][2] != ' ')
    {
        return board[0][2];
    }
    //判断棋盘是否满了
    if (IsFull(board, row, col))
    {
        return 'Q';
    }
    else
        return 'C';
}

8.判断棋盘是否排满

int IsFull(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')
                return 0;
        }
    }
    return 1;
}

值得注意的是这里的返回0与1是判断输赢中if的执行条件。

9.函数整合逻辑

其实在真正写代码的时候,我们应该是边写框架边构建函数。而不是先写函数再写框架。这里只是方便教学。

ok,我们调用我们的game函数的时候,映入眼帘的应该是先把你棋盘打印出来,不然没有棋盘怎么玩?当老八的资格都没有了。打印棋盘后就是游戏开始的地方了。

先用随机数判断谁先下,如这里0表示玩家下,1表示电脑下。用if else语句就可以完成

倘若玩家下就调用我们的玩家下棋函数,再打印出来

倘若电脑下就要调用进攻函数判断是否要进攻,不需要进攻,就调用防守函数,判断是否需要防守。如果2者都不需要就随机下棋。这一步用if else也可以完美解决

值得注意的是,玩家和电脑下棋是个循环直到比赛结束,玩家和电脑每下一步都要判断是否可以赢,倘若不是返回C就继续,一旦返回其他就直接break跳出,去总结是谁win或是否平局

int ret = 0;
void game()
{
    //设置二维数组
    char board[ROW][COL];
    //初始化棋盘
    init(board, ROW, COL);
    //打印棋盘
    print(board, ROW, COL);
    printf("--------游戏开始——---———\n");
    printf("\n");
    //人机对弈
    int tmp = rand() % 2;
    if (0 == tmp)        //玩家下棋
    {
        while (1)
        {
            //玩家下棋+判断
            playerA(board, ROW, COL);
            print(board, ROW, COL);
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
            //电脑下棋+判断
            int a = attack(board, ROW, COL);
            if (0 == a)
            {
                int d = defense(board, ROW, COL);
                if (0 == d)
                {
                    playerB(board, ROW, COL);
                    print(board, ROW, COL);
                }
                else
                {
                    print(board, ROW, COL);
                }
            }
            else
            {
                print(board, ROW, COL);
            }
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
        }
    }
    else            //电脑下
    {
        while (1)
        {
            int a = attack(board, ROW, COL);
            if (0 == a)
            {
                int d = defense(board, ROW, COL);
                if (0 == d)
                {
                    playerB(board, ROW, COL);
                    print(board, ROW, COL);
                }
                else
                {
                    print(board, ROW, COL);
                }
            }
            else
            {
                print(board, ROW, COL);
            }
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
            //玩家下棋+判断
            playerA(board, ROW, COL);
            print(board, ROW, COL);
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
        }
    }

    if ('*' == ret)
    {
        printf("你侥幸获胜了\n");
        printf("准备下一把\n");
    }
    else if ('#' == ret)
    {
        printf("你居然打不赢电脑\n");
        printf("准备下一把\n");
    }
    else if ('Q' == ret)
        printf("平局\n");
}

完整代码

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)
//头文件的包含
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
//全局变量
#define ROW 3
#define COL 3

//函数的声明
//菜单
void menu();
//游戏模块
void game();
//初始化棋盘
void init(char board[ROW][COL], int row, int col);
//打印棋盘
void print(char board[ROW][COL], int row, int col);
//玩家A下棋
void playerA(char board[ROW][COL], int row, int col);
//玩家B下棋
void playerB(char board[ROW][COL], int row, int col);
//判断输赢
char judge(char board[ROW][COL], int row, int col);
//判断棋盘是否满
int IsFull(char board[ROW][COL], int row, int col);
//电脑进攻函数
int attack(char boatd[ROW][COL], int row, int col);
//电脑防守函数
int defense(char board[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)
#include "game.h"

int ret = 0;
void game()
{
    //设置二维数组
    char board[ROW][COL];
    //初始化棋盘
    init(board, ROW, COL);
    //打印棋盘
    print(board, ROW, COL);
    printf("--------游戏开始——---———\n");
    printf("\n");
    //人机对弈
    int tmp = rand() % 2;
    if (0 == tmp)        //玩家下棋
    {
        while (1)
        {
            //玩家下棋+判断
            playerA(board, ROW, COL);
            print(board, ROW, COL);
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
            //电脑下棋+判断
            int a = attack(board, ROW, COL);
            if (0 == a)
            {
                int d = defense(board, ROW, COL);
                if (0 == d)
                {
                    playerB(board, ROW, COL);
                    print(board, ROW, COL);
                }
                else
                {
                    print(board, ROW, COL);
                }
            }
            else
            {
                print(board, ROW, COL);
            }
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
        }
    }
    else            //电脑下
    {
        while (1)
        {
            int a = attack(board, ROW, COL);
            if (0 == a)
            {
                int d = defense(board, ROW, COL);
                if (0 == d)
                {
                    playerB(board, ROW, COL);
                    print(board, ROW, COL);
                }
                else
                {
                    print(board, ROW, COL);
                }
            }
            else
            {
                print(board, ROW, COL);
            }
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
            //玩家下棋+判断
            playerA(board, ROW, COL);
            print(board, ROW, COL);
            ret = judge(board, ROW, COL);
            if (ret != 'C')
            {
                break;
            }
        }
    }

    if ('*' == ret)
    {
        printf("你侥幸获胜了\n");
        printf("准备下一把\n");
    }
    else if ('#' == ret)
    {
        printf("你居然打不赢电脑\n");
        printf("准备下一把\n");
    }
    else if ('Q' == ret)
        printf("平局\n");
}

//初始化棋盘
void init(char board[ROW][COL], int row, int col)
{
    /*int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            board[i][j] = ' ';
        }
    }*/
    //初始化一块空间,首元素地址知道了,初始为什么呢?初始化多少字节呢?
    memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}

//打印棋盘
void print(char board[ROW][COL], int row, int col)
{
    int i = 0;
    for (i = 1; i <= 3; i++)
    {
        printf("%d   ", i);
    }
    printf("\n");
    for (i = 0; i < row; i++)
    {
        int j = 0;
        //数据的打印
        for (j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if (j < col - 1)
                printf("|"); //1个数据打印完后,打印|
        }
        printf("%d", i + 1);
        printf("\n");
        //分割行的打印
        if (i < row - 1)
        {
            for (j = 0; j < col; j++)
            {
                printf("___");
                if (j < col - 1)
                    printf("|");
            }
        }
        printf("\n");
    }
}

//pA下棋
void playerA(char board[ROW][COL], int row, int col)
{
    printf("到你的回合了\n");
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("请输入你要下的坐标: ");
        scanf("%d %d", &x, &y);
        if (x > 0 && x <= row && y > 0 && y <= col)
        {
            if (board[x - 1][y - 1] == ' ')
            {
                board[x - 1][y - 1] = '*';
                break;
            }
            else
                printf("坐标被占用,请重新选择\n");
        }
        else
        {
            printf("输入值越界,请输入3*3坐标\n");
        }
    }
}

//pB下棋
void playerB(char board[ROW][COL], int row, int col)
{
    int x = 0;
    int y = 0;
    printf("电脑下棋\n");
    while (1)
    {
        x = rand() % row;
        y = rand() % col;
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}

//判断输赢
//*为玩家
//#为电脑
//Q为平局
//C为继续
char judge(char board[ROW][COL], int row, int col)
{
    int i = 0;
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
        {
            return board[i][0];
        }
    }
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
        {
            return board[0][i];
        }
    }
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
    {
        return board[0][0];
    }
    if (board[0][2] == board[1][1] && board[2][1] && board[0][2] != ' ')
    {
        return board[0][2];
    }
    if (IsFull(board, row, col))
    {
        return 'Q';
    }
    else
        return 'C';
}

//判断棋盘是否满
int IsFull(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')
                return 0;
        }
    }
    return 1;
}

//电脑进攻函数 q=0随机下 q=1进攻
int attack(char board[ROW][COL], int row, int col)
{
    int q = 0;
    int i = 0;
    //判断行是否有机会
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][0] == '#' && board[i][2] == ' ')
        {
            board[i][2] = '#';
            q = 1;
            return q;
        }
        if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' ')
        {
            board[i][1] = '#';
            q = 1;
            return q;
        }
        if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
        {
            board[i][0] = '#';
            q = 1;
            return q;
        }
    }
    //判端列是否有机会
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[0][i] == '#' && board[2][i] == ' ')
        {
            board[2][i] = '#';
            q = 1;
            return q;
        }
        if (board[0][i] == board[2][i] && board[0][i] == '#' && board[1][i] == ' ')
        {
            board[1][i] = '#';
            q = 1;
            return q;
        }
        if (board[1][i] == board[2][i] && board[1][i] == '#' && board[0][i] == ' ')
        {
            board[0][i] = '#';
            q = 1;
            return q;
        }
    }
    //判断正对角线是否有机会
    if (board[0][0] == board[1][1] && board[0][0] == '#' && board[2][2] == ' ')
    {
        board[2][2] = '#';
        q = 1;
        return q;
    }
    if (board[0][0] == board[2][2] && board[0][0] == '#' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][2] == board[1][1] && board[2][2] == '#' && board[0][0] == ' ')
    {
        board[0][0] = '#';
        q = 1;
        return q;
    }
    //判断反对角线是否有机会
    if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' ')
    {
        board[2][0] = '#';
        q = 1;
        return q;
    }
    if (board[0][2] == board[2][0] && board[0][2] == '#' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][0] == board[1][1] && board[2][0] == '#' && board[0][2] == ' ')
    {
        board[0][2] = '#';
        q = 1;
        return q;
    }
    return q;            //不需要进攻
}

//电脑防守函数
int defense(char board[ROW][COL], int row, int col)
{
    int q = 0;
    int i = 0;
    //判断行是否有机会
    for (i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][0] == '*' && board[i][2] == ' ')
        {
            board[i][2] = '#';
            q = 1;
            return q;
        }
        if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' ')
        {
            board[i][1] = '#';
            q = 1;
            return q;
        }
        if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
        {
            board[i][0] = '#';
            q = 1;
            return q;
        }
    }
    //判端列是否有机会
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[0][i] == '*' && board[2][i] == ' ')
        {
            board[2][i] = '#';
            q = 1;
            return q;
        }
        if (board[0][i] == board[2][i] && board[0][i] == '*' && board[1][i] == ' ')
        {
            board[1][i] = '#';
            q = 1;
            return q;
        }
        if (board[1][i] == board[2][i] && board[1][i] == '*' && board[0][i] == ' ')
        {
            board[0][i] = '#';
            q = 1;
            return q;
        }
    }
    //判断正对角线是否有机会
    if (board[0][0] == board[1][1] && board[0][0] == '*' && board[2][2] == ' ')
    {
        board[2][2] = '#';
        q = 1;
        return q;
    }
    if (board[0][0] == board[2][2] && board[0][0] == '*' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][2] == board[1][1] && board[2][2] == '*' && board[0][0] == ' ')
    {
        board[0][0] = '#';
        q = 1;
        return q;
    }
    //判断反对角线是否有机会
    if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' ')
    {
        board[2][0] = '#';
        q = 1;
        return q;
    }
    if (board[0][2] == board[2][0] && board[0][2] == '*' && board[1][1] == ' ')
    {
        board[1][1] = '#';
        q = 1;
        return q;
    }
    if (board[2][0] == board[1][1] && board[2][0] == '*' && board[0][2] == ' ')
    {
        board[0][2] = '#';
        q = 1;
        return q;
    }
    return q;        //不需要防守
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)
#include "game.h" //自己的文件用""

void menu()
{
    printf("*******************\n");
    printf("***** 1 start *****\n");
    printf("***** 0 quit  *****\n");
    printf("*******************\n");
}

int main()
{
    int num = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("\n请根据菜单选择一个数(1/0): ");
        scanf("%d", &num);
        switch (num)
        {
        case 1:
            printf("下面是棋盘\n");
            game();
            break;
        case 0:
            printf("quit this game...\n");
            break;
        default:
            printf("please chose one again\n");
            break;
        }
    } while (num);
    return 0;
}

完结撒花

ok,其实我们会了3子棋后,实现N子棋就更加轻而易举了,无非就是在全局变量里更改行列数,修改一下判断算法和电脑算法即可,重要的不是程序跑出来了,而是思考的过程。相信大家的智慧看完后肯定可以写出更优秀的N子棋来。

到这里就结束了,感谢看到此处,如果对你有帮助的话麻烦直接走3连。
  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值