C语言实现五子棋(n子棋)

news2024/11/26 10:27:28

五子棋的历史背景:

五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。

五子棋容易上手,老少皆宜,而且趣味横生,引人入胜。它不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。


不难看出,五子棋是我们中华民族发明的,我们必须了解他,作为程序员,我们更加要懂得如何把五子棋的代码给敲出来,我研究了一天了,调试了无数次,修改了无数错误,到最后运行成功的那一刹那,我就很开心,就想以博客的形式分享给大家!

一.设计过程步骤

ps:整个五子棋一共有三个文件,200多行代码,不复杂,多琢磨,很好懂,分为text.c,game.h,game.c文件,在最后会给出完整代码。

1.初始化二维数组

为了数组里面存放的每个数是我们想初始化的,我们初始化一个二维数组(方阵的格式,即 n*n)用来存放棋子,里面的元素可以按照我们的意愿来初始化;在此代码中将数组中每个元素初始化为一个空格。

#define ROW 5
#define COL 5
void InitBoard(char board[ROW][COL], int row, int col)
{
    int i = 0; 
    int j = 0;
    for (i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COL; j++)
        {
            board[i][j] = ' ';
        }
    }
}

2.构造一个棋盘

在初始化一个数组后的基础上我们来构造一个棋盘,使得整个代码的结构更加清晰,可读性高。

#define ROW 5
#define COL 5
void DisplayBoard(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++)
        {
            printf(" %c ", board[i][j]);//注意:%c的左右是有两个空格的
            if (j < col -1)//最后一列不打印|,也就是打印4个|,只是为了美观,不加也行,见下图
                printf("|");
        }
        printf("\n");
        if (i < row - 1)//最后一行不进行打印---和|,见下图
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                printf("---");
                if (j < col - 1)//和上面一样,见下图
                printf("|");
            }
            printf("\n");
        }
        
    }
}

3.玩家走法

//玩家
void PlayerMove(char board[ROW][COL], int row, int col)
{
    int x = 0;
    int y = 0;
    printf("玩家走:>");
    while (1)
    {
        printf("请输入下棋的坐标\n");
        scanf_s("%d %d", &x, &y);
        //判断坐标的合法性
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //下棋
            //坐标是否被占用
            if (' ' == board[x - 1][y - 1])            //等号量变也可以调换,我这样写要是出错那编译器会提示错误,如果换过来的话那就不会提示错误了,这样找bug可能会很难受
//如果是空格的话,这个位置就是空的,可以下棋
            {
                board[x - 1][y - 1] ='*';
                break;
            }
            else
            {
                printf("坐标被占用,请重新输入\n");

            }
        }
        else
        {
            printf("坐标非法,请重新选择\n");
        }
    }
}

4.电脑随机下棋

//电脑
void ComputerMove(char board[ROW][COL], int row, int col)
{        
    printf("电脑走:>\n");
    while (1)
    {
        int x = rand() % ROW;//rand是根据系统的情况来自动生成一个随机数
        int y = rand() % COL;
        //判断占用
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}

5.判断是否能分出胜负

//判断游戏是否有输赢
char IsWin(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][2] == board[i][3] 
            && board[i][3] == board[i][4] && board[i][1] != ' ')
        {
            return board[i][1];
        }
    }    
        //判断五列每一列的元素是否相等
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] == board[3][i] 
            && board[3][i] == board[4][i] && board[1][i] != ' ')
        {
            return board[i][1];
        }
    }
        //判断\对角线元素是否相等
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&&
 board[2][2] == board[3][3]&&board[3][3] == board[4][4] && board[1][1]!=' ')
    {
        return board[1][1];
    }
    //判断/对角线元素是否相等
    if ( board[4][0]== board[3][1] && board[3][1] == board[2][2]&& 
board[2][2] == board[1][3] &&board[1][3] == board[0][4] && board[1][1]!=' ')
    {
        return board[1][1];
    }

6.判断是否平局

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;
}

//判断平局
    //如果棋盘满了则返回1,不满返回0
    int ret = IsFull(board, row, col);
    if (ret == 1)
    {
        return 'Q';
    }
    return 'C';

以下是game.h文件的代码

#pragma once
//头文件的包含
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//符号定义
#define ROW 5
#define COL 5

//函数声明
//初始化棋盘的
 void InitBoard(char board[ROW][COL], int row, int col);
 //打印棋盘的函数
 void DisplayBoard(char board[ROW][COL], int row, int col);
 //玩家下棋
 void PlayerMove(char board[ROW][COL], int row, int col);
 //电脑下棋
 void ComputerMove(char board[ROW][COL], int row, int col);
 char IsWin(char board[ROW][COL], int row, int col);

以下是text.c文件的代码

#include"game.h"
void menu()
{
    printf("*******************************\n");
    printf("*********  1.play  ************\n");
    printf("*********  0.exit  ************\n");
    printf("*******************************\n");

}
void game()
{
    //储存数据--二维数组
    char board[ROW][COL];
    //初始化棋盘为空格
    InitBoard(board, ROW, COL);
    //打印棋盘--本质打印数组的内容
    DisplayBoard(board,ROW,COL);
    char ret = 0;
    while (1)
    {
        //玩家下棋
        PlayerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        //判断玩家是否赢
        ret = IsWin(board, ROW, COL);
        if (ret != 'C')
            break;
        //电脑下棋
        ComputerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        ret = IsWin(board, ROW, COL);
        if (ret =! 'C')
            break;
    }
    if (ret == '*')
        printf("玩家胜利\n");
    else if (ret == '#')
        printf("电脑胜利\n");
    else
        printf("平局\n");
    DisplayBoard(board, ROW, COL);

}
int main()
{
    srand((unsigned int) time(NULL));
    int input = 0;
    do
    {
        menu();
        printf("请选择:>");
        scanf_s("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误,重新选择\n");
            break;
        }
    } while (input);
    return 0;
}

二.完整代码:

game.h文件

#pragma once
//头文件的包含
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//符号定义
#define ROW 5
#define COL 5

//函数声明
//初始化棋盘的
 void InitBoard(char board[ROW][COL], int row, int col);
 //打印棋盘的函数
 void DisplayBoard(char board[ROW][COL], int row, int col);
 //玩家下棋
 void PlayerMove(char board[ROW][COL], int row, int col);
 //电脑下棋
 void ComputerMove(char board[ROW][COL], int row, int col);
 char IsWin(char board[ROW][COL], int row, int col);

game.c文件

#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
    int i = 0; 
    int j = 0;
    for (i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COL; j++)
        {
            board[i][j] = ' ';
        }
    }

}

void DisplayBoard(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++)
        {
            printf(" %c ", board[i][j]);
            if (j < col -1)
                printf("|");
        }
        printf("\n");
        if (i < row - 1)
        {
            int j = 0;
            for (j = 0; j < col; j++)
            {
                printf("---");
                if (j < col - 1)
                printf("|");
            }
            printf("\n");
        }
            //printf("---|---|---\n");
    }
}
//玩家
void PlayerMove(char board[ROW][COL], int row, int col)
{
    int x = 0;
    int y = 0;
    printf("玩家走:>");
    while (1)
    {
        printf("请输入下棋的坐标\n");
        scanf_s("%d %d", &x, &y);
        //判断坐标的合法性
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //下棋
            //坐标是否被占用
            if (' ' == board[x - 1][y - 1])
            {
                board[x - 1][y - 1] ='*';
                break;
            }
            else
            {
                printf("坐标被占用,请重新输入\n");

            }
        }
        else
        {
            printf("坐标非法,请重新选择\n");
        }
    }
}
//电脑
void ComputerMove(char board[ROW][COL], int row, int col)
{        
    printf("电脑走:>\n");
    while (1)
    {
        int x = rand() % ROW;
        int y = rand() % COL;
        //判断占用
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}
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;
}
//判断游戏是否有输赢
char IsWin(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][2] == board[i][3] 
            && board[i][3] == board[i][4] && board[i][1] != ' ')
        {
            return board[i][1];
        }
    }    
        //判断五列
    for (i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] == board[3][i] 
            && board[3][i] == board[4][i] && board[1][i] != ' ')
        {
            return board[i][1];
        }
    }
        //判断\对角线
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&& board[2][2] == board[3][3] 
        &&board[3][3] == board[4][4] && board[1][1]!=' ')
    {
        return board[1][1];
    }
    //判断/对角线
    if ( board[4][0]== board[3][1] && board[3][1] == board[2][2]&& board[2][2] == board[1][3] 
        &&board[1][3] == board[0][4] && board[1][1]!=' ')
    {
        return board[1][1];
    }
    //判断平局
    //如果棋盘满了则返回1,不满返回0
    int ret = IsFull(board, row, col);
    if (ret == 1)
    {
        return 'Q';
    }
    return 'C';


}

以下是text.c文件:

#include"game.h"
void menu()
{
    printf("*******************************\n");
    printf("*********  1.play  ************\n");
    printf("*********  0.exit  ************\n");
    printf("*******************************\n");

}
void game()
{
    //储存数据--二维数组
    char board[ROW][COL];
    //初始化棋盘为空格
    InitBoard(board, ROW, COL);
    //打印棋盘--本质打印数组的内容
    DisplayBoard(board,ROW,COL);
    char ret = 0;
    while (1)
    {
        //玩家下棋
        PlayerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        //判断玩家是否赢
        ret = IsWin(board, ROW, COL);
        if (ret != 'C')
            break;
        //电脑下棋
        ComputerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        ret = IsWin(board, ROW, COL);
        if (ret =! 'C')
            break;
    }
    if (ret == '*')
        printf("玩家胜利\n");
    else if (ret == '#')
        printf("电脑胜利\n");
    else
        printf("平局\n");
    DisplayBoard(board, ROW, COL);

}
int main()
{
    srand((unsigned int) time(NULL));
    int input = 0;
    do
    {
        menu();
        printf("请选择:>");
        scanf_s("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误,重新选择\n");
            break;
        }
    } while (input);
    return 0;
}

最后,大家有问题可以指出来,关个注,点个赞,评个论,我们一起进步!

2023.02.09

From:努力进大厂的新青年

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

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

相关文章

c/c++开发,无可避免的文件访问开发案例

一、缓存文件系统 ANSI C标准中的C语言库提供了fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等标准函数&#xff0c;这些函数在不同的操作系统中应该调用不同的内核API&#xff0c;从而支持开发者跨平台实现对文件的访问。 在Lin…

【九宫格坐标排列 Objective-C语言】

一、这个案例做好之后的效果如图: 1.这个下载是可以点击的,当你点击之后,弹出一个框,过一会儿,框框自动消失,这里变成“已安装” 2.那么,我现在先问大家一句话:大家认为在这一个应用里面,它包含几个控件, 3个,哪3个:一个是图片框,一个是Label,一个是按钮, 这…

python学习笔记-查看数据结构、均值、中位数、分位数、众数、离中趋势(标准差、方差、求和、偏态系数、风险系数)正态分布pdf、cdf、ppf

①引入pandas包&#xff0c;命名为pd。 import pandas as pd ②读入HR.csv数据 dfpd.read_csv(“./data/HR.csv”) ③查看是什么结构 type(df) ④查看单个类别satisfaction_level的数据结构 type(df[“satisfaction_level”]) ⑤查看均值的数据结构 type(df.mean()) …

运行Whisper笔记(1)

最近chatGPT很火&#xff0c;就去逛了一下openai的github项目。发现了这个项目。 这个项目可以识别视频中的音频&#xff0c;转换出字幕。 带着一颗好奇的心就尝试自己去部署玩一玩 跟着这篇文章一步步来进行安装&#xff0c;并且跟着这篇文章解决途中遇到的问题。 途中还会遇…

男,26岁,做了一年多的自动化测试,最近在纠结要不要转行,求指点。?

最近一个粉丝在后台问我&#xff0c;啊大佬我现在26了&#xff0c;做了做了一年多的自动化测试&#xff0c;最近在纠结要不要转行&#xff0c;求指点。首选做IT这条路&#xff0c;就是很普通的技术蓝领。对于大部分来说干一辈子问题不大&#xff0c;但是发不了什么财。如果你在…

第015天:将APP发布到应用商店(完结)

应用已经开发出来了&#xff0c;下一步我们需要思考推广方面的工作。那么如何才能让更多的用户知 道并使用我们的应用程序呢&#xff1f;在手机领域&#xff0c;最常见的做法就是将程序发布到某个应用商店中&#xff0c;这 样用户就可以通过商店找到我们的应用程序&#xff0c;…

前端修行 - 与后端配合的那些事情

最近总结一下个人作为前端&#xff0c;与后端、测试、以及产品经理、UI设计之间配合的那些事情&#xff0c;想到哪里说到哪里 1 关于正确认识项目研发一号位都是后端的这个事情 项目研发一号位&#xff0c;在有的公司可能会叫做SDM&#xff08;software development manger&am…

springboot 接入websocket实现定时推送消息到客户端

目录说明代码实现说明 如标题&#xff0c;举例需求场景&#xff1a; 前端与后端websocket连接上后&#xff0c;多用户登录&#xff0c;后端根据不同用户定时发消息给前端用于展示 代码实现 1、 <dependency><groupId>org.springframework.boot</groupId>…

vit-pytorch实现 MobileViT注意力可视化

项目链接 https://github.com/lucidrains/vit-pytorch 注意一下参数设置&#xff1a; Parameters image_size: int. Image size. If you have rectangular images, make sure your image size is the maximum of the width and heightpatch_size: int. Number of patches. im…

git:详解git rebase命令

背景 今天无意中打开 git 官网&#xff0c;发现 git 命令还是很多的&#xff0c;然而我们常用的就那几个&#xff0c;今天来学习一个也不怎么常用的命令 rebase 官网链接 都说学一个东西最好的方式就是读他的 官方文档&#xff0c;这里我读了一遍&#xff0c;把一些核心的地…

读书思考:步步惊心的《技术陷阱》

《技术陷阱》这本书450页&#xff0c;43万字之巨&#xff0c;信息量密密麻麻&#xff0c;采集的资料极其丰富&#xff0c;复习了一遍大停滞、大分流、大平衡、大逆转时代&#xff0c;并展望未来。看完了有很多想法&#xff0c;随手写了下来&#xff0c;希望不是蹭热点。&#x…

vue 最详细教学篇(一)

文章目录前言前景Vue 的长期技术支持 (LTS)、终止支持 (EOL) 及其延长版服务学习vue 要掌握那些技能-为什么学习 vue走进vueHello World 起手提示&#xff1a;示例&#xff1a;示例解析编辑器 VSCodevsCode 插件正式使用 vue.js要使用 vue 就绕不开生命周期 下面是生命周期图&a…

全国青少年编程等级考试scratch一级真题2022年9月(含题库答题软件账号)

青少年编程等级考试scratch真题答题考试系统请点击电子学会-全国青少年编程等级考试真题Scratch一级&#xff08;2019年3月&#xff09;在线答题_程序猿下山的博客-CSDN博客_小航答题助手1点击绿旗&#xff0c;下列哪个选项可以实现播放马叫声并在声音全部播放完后&#xff0c;…

Java常见数据结构的排序与遍历(包括数组,List,Map)

数组遍历与排序 数组定义 //定义 int a[] new int[5]int[] a new int[5];//带初始值定义 int b[] {1,2,3,4,5};赋值 //定义时赋值 int b[] {1,2,3,4,5};//引用赋值 a[6] 1 a[9] 9 //未赋值为空取值 //通过下表取值&#xff0c;从0开始 b[1] 1 b[2] 2遍历 Test p…

C语言操作符详解 一针见血!

目录算数操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号表达式下标引用、函数调用和结构成员表达式求值11.1 隐式类型转换算数操作符&#x1f4ad; 注意/ 除法 --得到的是商% 取模&#xff08;取余&#xff09;--得到的是余数如果除法操作符…

CentOS 根路径下各个目录的作用及介绍

前言 很多小伙伴刚刚开始接触Linux系统时肯定和我一样&#xff0c;都很懵&#xff0c;黑黢黢的界面&#xff0c;一个个目录&#xff0c;没有图形化界面&#xff0c;看着难受&#xff0c;多接触了一些后会好受一些&#xff0c;不过&#xff0c;对各个目录的了解肯定也很基础&am…

若依框架---PageHelper分页(十)

在前几天的文章中&#xff0c;我们介绍了PageHelper的分页方法&#xff0c;研读代码定位到了ExecutorUtil.pageQuery(...)方法&#xff0c;并阅读到了其中的部分代码。 今天我们将看到重要的SQL修改代码。 getPageSql 我们接着看代码&#xff1a; if (!dialect.beforePage(…

2023爬虫学习笔记 -- 批量爬取图片

一、目标网址http://img.itlun.cn/uploads/allimg/180703/1-1PF3160531-lp.jpg二、右击图片获取图片地址http://img.itlun.cn/uploads/allimg/180703/1-1PF3160531-lp.jpg三、以二进制形式返回响应数据响应requests.get(网页,headers头) 响应内容响应.content四、存储二进制数据…

SpringBoot整合Mybatis的核心原理

0. 前言&#xff1a;1. 自动配置类MybatisAutoConfiguration&#xff1a;1.1. SqlSessionFactory的生成&#xff1a;1.2. Mapper的扫描和代理生成&#xff1a;1.2.1. MapperScannerConfigurer1.2.2. MapperFactoryBean1.2.3. getMapper生成代理对象2. 小结&#xff1a;0. 前言&…

Vue2仿网易云风格音乐播放器(附源码)

Vue2仿网易云风格音乐播放器1、整体效果2、使用技术3、实现内容4、源码5、使用图片1、整体效果 2、使用技术 使用了HTML5 CSS3进行页面布局及美化使用Vue2进行数据渲染与页面交互使用Axios发送http请求获取数据 3、实现内容 实现了搜索歌曲功能&#xff0c;输入歌手或歌曲关…