五子棋(C语言实现)

目录

构思

1、主程序

2、初始化

3、游戏菜单

4、打印棋盘

6、玩家下棋

7、判断输赢

 8、功能整合

人机下棋

完整版: 

game.h

game.c

text.c

 测试功能代码


构思

五子棋不必多介绍了,大家小时候都玩过哈。

我们要通过程序实现这个小游戏,大体上的构思得有:

游戏流程:运行游戏>>打印棋盘>>下棋>>判断输赢

由此,我们声明如下函数、棋盘数组和回合数 (用于双人下棋时下不同棋子的判断)。

将这些都放在我创建的头文件game.h中方便其他文件使用: 

#include 
#include 

int map[19][19];//棋盘
int flag;//回合数

//初始化棋盘
void init();

//游戏菜单
void menuView();

//打印棋盘
void gameView_ShowMap();

//玩家下棋
int playerMove(int x, int y);

//判断输赢
int isWin(int x, int y);

//判断输赢
void winView();

1、主程序

先进行游戏下棋,后进行判断输赢,比较符合do—while的特点。 

int main()
{
    int input = 0;
    do
    {
        menuView();
        printf("请选择:");
        scanf("%d", &input);
        switch (input) {
        case 1:
            gameView();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误,请重新选择.\n");
            break;
        }
    } while (input);
    return 0;
}
  • 首先打印菜单,提示玩家进行选择开始游戏。
  • 通过输入变量input的值,判断是否进行游戏,
  • 值为1则调用gameView函数进行游戏,0则结束游戏。
  • gameView函数对各种功能函数进行整合。

在此之前先将各种功能函数进行实现,最后将它们放入gameView整合。 

2、初始化

void init() {
    for (int i = 0; i < 19; i++) {
        for (int j = 0; j < 19; j++) {
            map[i][j] = 0;
        }
    }
    flag = 0;
}
  • 将棋盘每个格子初始化为0。
  • 回合数初始化为0。

3、游戏菜单

void menuView() {
    printf("*************************\n");
    printf("*****   1. play    ******\n");
    printf("*****   0. exit    ******\n");
    printf("*************************\n");
}

4、打印棋盘

这里我选择设计了棋盘格和横纵坐标,我们可以根据需要自行设计。 

void gameView_ShowMap() {
    int i, j;
    printf("   ");
    for (i = 0; i < 19; i++) {//打印横坐标
        printf("%3d ",i);
    }
    printf("\n   ");
    for (i = 0; i < 19; i++) {
        printf("+---");
    }
    printf("+\n");

    for (i = 0; i < 19; i++) {
        
        printf("%2d |", i);//每行输出前都先打印纵坐标

        for (j = 0; j < 19; j++) {
            printf(" %d ", map[i][j]);//打印棋子
            if (j < 18)
                printf("|");
        }
        printf("|\n");

        if(i<18)
            printf("   |");
        if(i==18)
            printf("   +");
        for (j = 0; j < 19; j++) {
            printf("---");
            if (j < 18)
                printf("+");
        }
        printf("+\n");
    }
}

效果如下: 

五子棋(C语言实现)_第1张图片

6、玩家下棋

int playerMove(int x, int y) {
    if (x >= 0 && x < 19 && y >= 0 && y < 19) {
        if (map[x][y] == 0) {
            if (flag % 2 == 0)
                map[x][y] = 1;//下黑子
            else
                map[x][y] = 2;//下白子
            //落子成功
            return 1;
        }
        else {
            //该位置已有棋子
            return 0;
        }
    }
    else {
        //坐标不合法
        return -1;
    }
}
  • 首先判断下棋位置是否在棋盘0到18的横纵坐标内,如果不在函数返回值-1,
  • 如果在棋盘内,则进行下棋。
  • 棋盘每个格子初始值为0,判断当前格子的值为0才可以下棋,否则返回值为0。
  • 回合数flag初始值为0,当flag为偶数下黑子>>1,奇数下白子>>2,成功下棋返回值为1。

7、判断输赢

int isWin(int x, int y) {
    int i, j;
    for (i = 0; i < 19; i++) {
        for (j = 0; j < 19; j++) {
            if (map[i][j] == 0) {
                continue;
            }
                
            //横着连成五子
            if (j < 15)
                if (map[i][j] == map[i][j + 1] && map[i][j] == map[i][j + 2]
                    && map[i][j] == map[i][j + 3] && map[i][j] == map[i][j + 4])
                    return map[i][j];

            //竖着连成五子
            if (i < 15)
                if (map[i][j] == map[i + 1][j] && map[i][j] == map[i + 2][j]
                    && map[i][j] == map[i + 3][j] && map[i][j] == map[i + 4][j])
                    return map[i][j];

            //左斜着连成五子-> " \ "
            if (i < 15 && j < 15)
                if (map[i][j] == map[i + 1][j + 1] && map[i][j] == map[i + 2][j + 2]
                    && map[i][j] == map[i + 3][j + 3] && map[i][j] == map[i + 4][j + 4])
                    return map[i][j];

            //右斜着连成五子-> " / "
            if (i < 15 && j > 4)
                if (map[i][j] == map[i + 1][j - 1] && map[i][j] == map[i + 2][j - 2]
                    && map[i][j] == map[i + 3][j - 3] && map[i][j] == map[i + 4][j - 4])
                    return map[i][j];

            
        }
    }
    return 0;
}
  • i < 15 用于确保在检查垂直和左斜方向的连续五子时,起始位置 (i, j) 之后至少还有4个位置。因为五子连成一线需要五个连续的位置,所以确保从当前位置开始往下检查的时候不会超出数组的边界。

  • j < 15 用于确保在检查水平和左斜方向的连续五子时,起始位置 (i, j) 之后至少还有4个位置。同样,这是为了确保从当前位置开始往右检查的时候不会超出数组的边界。

  • j > 4 用于确保在检查右斜方向的连续五子时,起始位置 (i, j) 之前至少还有4个位置。这是为了确保从当前位置开始往左检查的时候不会超出数组的边界。

 8、功能整合

void gameView()
{
    init();
    int x = 0, y = 0;
    int ret = 0;//辅助判断坐标是否合法
    while (1) {
        gameView_ShowMap();

        printf("请输入要下棋的坐标:");
        scanf("%d %d", &x, &y);

        if (playerMove(x, y) == 0) {
            printf("\n!!!该坐标已被占用!!!\n");
            Sleep(2000);
            continue;
        }
        else if (playerMove(x, y) == -1) {
            printf("\n!!!请输入合法坐标!!!\n");
            Sleep(2000);
            continue;
        }
        else {
            flag++;//切换回合
        }

        if (isWin(x, y) == 0) {
            continue;
        }
           
        else if (isWin(x, y) == 1) {
            printf("黑子获胜\n");
            break;
        }

        else if (isWin(x, y) == 2) {
            printf("白子获胜\n");
            break;
        }
    }

}
  •  这里的Sleep函数需要头文件#include ,使用该函数暂停两秒,防止continue后下次循环打印的棋盘将提示信息挡住。
  • 下棋坐标不合法打印提示信息后,进入下次循环重新输入。
  • 成功下棋则flag自增,切换回合。
  • 每次下棋后都要判断输赢,有人赢了则停止循环,否则继续下棋。
  • (其实应该从下棋次数第五次开始判断输赢更合理,读者可以自行添加判断)

人机下棋

想要实现人机下棋可以看看我这篇文章《三子棋》 ,里面实现了人机下棋,读者可以自行模仿改进,实现其功能的重要函数可以在这篇文章中学习 rand&srand函数 。 

完整版: 

game.h

#include 
#include 
int map[19][19];//棋盘
int flag;//回合数

//初始化
void init();

//游戏菜单
void menuView();

//打印棋盘
void gameView_ShowMap();

//玩家下棋
int playerMove(int x, int y);

//判断输赢
int isWin(int x, int y);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"


void init() {
    for (int i = 0; i < 19; i++) {
        for (int j = 0; j < 19; j++) {
            map[i][j] = 0;
        }
    }
    flag = 1;
}


int isWin(int x, int y) {
    int i, j;
    for (i = 0; i < 19; i++) {
        for (j = 0; j < 19; j++) {
            if (map[i][j] == 0) {
                continue;
            }
                
            //横着连成五子
            if (j < 15)
                if (map[i][j] == map[i][j + 1] && map[i][j] == map[i][j + 2]
                    && map[i][j] == map[i][j + 3] && map[i][j] == map[i][j + 4])
                    return map[i][j];

            //竖着连成五子
            if (i < 15)
                if (map[i][j] == map[i + 1][j] && map[i][j] == map[i + 2][j]
                    && map[i][j] == map[i + 3][j] && map[i][j] == map[i + 4][j])
                    return map[i][j];

            //左斜着连成五子-> " \ "
            if (i < 15 && j < 15)
                if (map[i][j] == map[i + 1][j + 1] && map[i][j] == map[i + 2][j + 2]
                    && map[i][j] == map[i + 3][j + 3] && map[i][j] == map[i + 4][j + 4])
                    return map[i][j];

            //右斜着连成五子-> " / "
            if (i < 15 && j > 4)
                if (map[i][j] == map[i + 1][j - 1] && map[i][j] == map[i + 2][j - 2]
                    && map[i][j] == map[i + 3][j - 3] && map[i][j] == map[i + 4][j - 4])
                    return map[i][j];

            
        }
    }
    return 0;
}


int playerMove(int x, int y) {
    if (x >= 0 && x < 19 && y >= 0 && y < 19) {
        if (map[x][y] == 0) {
            if (flag % 2 == 0)
                map[x][y] = 1;//下黑子
            else
                map[x][y] = 2;//下白子
            //落子成功
            return 1;
        }
        else {
            //该位置已有棋子
            return 0;
        }
    }
    else {
        //坐标不合法
        return -1;
    }
}


void menuView() {
    printf("*************************\n");
    printf("*****   1. play    ******\n");
    printf("*****   0. exit    ******\n");
    printf("*************************\n");
}


void gameView_ShowMap() {
    int i, j;
    printf("   ");
    for (i = 0; i < 19; i++) {//打印横坐标
        printf("%3d ",i);
    }
    printf("\n   ");
    for (i = 0; i < 19; i++) {
        printf("+---");
    }
    printf("+\n");

    for (i = 0; i < 19; i++) {
        
        printf("%2d |", i);//每行输出前先都打印纵坐标

        for (j = 0; j < 19; j++) {
            printf(" %d ", map[i][j]);
            if (j < 18)
                printf("|");
        }
        printf("|\n");

        if(i<18)
            printf("   |");
        if(i==18)
            printf("   +");
        for (j = 0; j < 19; j++) {
            printf("---");
            if (j < 18)
                printf("+");
        }
        printf("+\n");
    }
}

text.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void gameView()
{
    init();
    int x = 0, y = 0;
    int ret = 0;//辅助判断坐标是否合法
    while (1) {
        gameView_ShowMap();

        printf("请输入要下棋的坐标:");
        scanf("%d %d", &x, &y);

        if (playerMove(x, y) == 0) {
            printf("\n!!!该坐标已被占用!!!\n");
            Sleep(2000);
            continue;
        }
        else if (playerMove(x, y) == -1) {
            printf("\n!!!请输入合法坐标!!!\n");
            Sleep(2000);
            continue;
        }
        else {
            flag++;//切换回合
        }

        if (isWin(x, y) == 0) {
            continue;
        }
           
        else if (isWin(x, y) == 1) {
            printf("黑子获胜\n");
            break;
        }

        else if (isWin(x, y) == 2) {
            printf("白子获胜\n");
            break;
        }
    }

}

int main()
{
    int input = 0;
    do
    {
        menuView();
        printf("请选择:");
        scanf("%d", &input);
        switch (input) {
        case 1:
            gameView();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误,请重新选择.\n");
            break;
        }
    } while (input);
    return 0;
}

 测试功能代码

此代码可以替换int main主函数,用于测试函数功能是否正确,可以减少自行下棋测试时间 

成功运行输出如下:

五子棋(C语言实现)_第2张图片

int main()
{
    int testflag = 0;
    //init测试代码
    
    init();
    if (flag != 0) {
        printf("init()错误");
        exit(0);
    }
    for (int i = 0; i < 19; i++) {
        for (int j = 0; j < 19; j++) {
            if (map[i][j]) {
                printf("init()错误");
                exit(0);
            }
        }
    }
    printf("init()测试成功\n");
    testflag++;
    

    //playerMove测试代码
    
    int result = 1;
    result &= playerMove(2, 2);
    result &= playerMove(2, 3);
    result &= playerMove(2, 4);
    result &= playerMove(2, 5);
    if (result != 1 || (map[2][2] && map[2][3] && map[2][4] && map[2][5]) != 1) {
        printf("playerMove()错误");
        exit(0);
    }
    flag = 1;
    result &= playerMove(2, 5);
    if (result != 0 || map[2][5] != 1) {
        printf("playerMove()错误");
        exit(0);
    }
    printf("playerMove()测试成功\n");
    testflag++;
    

    //isWin测试代码
    
    playerMove(2, 1);
    if (isWin(2, 1)) {
        printf("isWin()错误");
        exit(0);
    }
    playerMove(1, 0);
    playerMove(3, 2);
    playerMove(4, 3);
    playerMove(5, 4);
    if (isWin(1, 0) != 2) {
        printf("isWin()错误");
        exit(0);
    }
    printf("isWin()测试成功\n");
    testflag++;
    

    if (testflag == 3) {
        printf("service代码测试成功\n");
    }
    return 0;
}

你可能感兴趣的:(详解C语言,c语言,算法,开发语言,数据结构)