《如何使用C语言去下三子棋?》

目录

一、环境配置

二、功能模块

        1.打印菜单

2.初始化并打印棋盘

3、行棋 

        3.1玩家行棋

        3.2电脑行棋

4、判断是否和棋 

5.判赢

三、代码实现

        1、test.c文件

        2、game.c文件

        3、game.h文件


一、环境配置

        本游戏用到三个文件,分别是两个源文件test.c  game.c 和一个头文件game.h。

        主函数main()在test.c文件中,游戏实现所需要的函数在test.c中被引用,而函数的实现主要是在game.c文件中完成。game.h文件中包含了程序所需的所有头文件并且包括对实现游戏功能的所有函数的声明。

        之所以使用3个文件是因为,三子棋的实现需要多个模块的相互串联,多个文件各司其职,这样可以更好的处理各个模块间的逻辑,这样也增加了代码的可读性,而且还利于调试。

二、功能模块

1.打印菜单

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

  运行结果: 

 玩家选择(1/0)决定是否进入游戏。

 2.初始化并打印棋盘

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] = ' ';}}
}
/* 通过创建一个char类型的二维数组对其进行初始化 */
char board[ ][ ] = { 0 };       
void DisplayBoard(char board[ROW][COL], int row, int col)
{int i = 0;int j;for (i = 0; i < row; i++){j = 0; for ( j; j < col; j++) //打印   |   |   {printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");j = 0;for ( j; j < col; j++)//打印---|---|---{if (i < row - 1){printf("---");if (j < col - 1){printf("|");}}}printf("\n");}
}

 运行结果:

 其中,上述棋盘的大小可以根据用户需求自行调整。

 棋盘大小调整方式:在game.h文件中,对宏的定义进行更改即可完成棋盘大小的修改。

#define ROW 3
#define COL 3

3、行棋 

3.1玩家行棋

void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家走:>\n");while (1){printf("请输入下棋的坐标:>");scanf("%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("坐标非法,请重新输入!");}}
}

3.2电脑行棋

void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑走:>");while (1){//生成随机坐标int x = rand() % row;int y = rand() % col;//下棋//判断坐标是否被占用if (board[x][y] == ' '){printf("%d %d\n", x + 1, y + 1);//输出电脑下棋的坐标board[x][y] = '#';//电脑使用#下棋break;}}
}

         电脑和玩家每走一步棋,都会打印出新的棋盘,以便于玩家观察空子的位置。

4、判断是否和棋 

int IfFull(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;//棋盘满了
}

        在game.c文件中通过IfFull函数实现对棋盘上空位的判断,防止一个位置多次下棋。

        如果棋盘所有格子都下完之前,还没有分出胜负 ,则代表和棋,以上代码为判断棋盘上面是否有空格子。

5.判赢

char IfWin(char board[ROW][COL], int row, int col)
{//判断行for (int i = 0; i < row; i++){for (int j = 2; j < col; j++){if (board[i][j - 2] == board[i][j - 1] && board[i][j - 1] == board[i][j] && board[i][j] != ' '){return board[i][j];}}}//判断列for (int j = 0; j < col; j++){for (int i = 2; i < row; i++){if (board[i - 2][j] == board[i - 1][j] && board[i - 1][j] == board[i][j] && board[i][j] != ' '){return board[i][j];}}}//判断右交叉for (int i = 2; i < row; i++){for (int j = 2; j < col; j++){if (board[i - 2][j - 2] == board[i - 1][j - 1] && board[i - 1][j - 1] == board[i][j] && board[i][j] != ' '){return board[i][j];}}}//判断左交叉for (int i = 1; i < row - 1; i++){for (int j = 1; j < col - 1; j++){if (board[i - 1][j + 1] == board[i][j] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' '){return board[i][j];}}}//判断平局int full = IfFull(board, row, col);if (full == 1){return 'Q';}//游戏继续return 'C';
}

        每下一步棋,都会对棋盘的每行、每列、左交叉、右交叉做出判断,看是否有三个一样的旗子相连,如果有代表下棋者获胜,否则继续下棋,直至下满棋盘。

        return board[ i ][ j ] ;的奥妙之处就在于,无论是玩家获胜还是电脑获胜都会返回与其相同的棋子,不需要再重新进行判断取胜的棋子是哪一方,如果返回'*',证明玩家获胜,game()函数得到'*',判定玩家获胜,输出:“玩家获胜!”;如果返回'#',证明电脑获胜,game()函数得到'#',判定电脑获胜,输出:“电脑获胜!”

        如果通过IfFull()函数判断棋盘已经下满,就会给test.c文件中的game()函数中返回'Q’,game()函数得到'Q'便知道二者微分胜负,输出:和局。

        否则,return ’C',game()函数得到‘C’,游戏继续。

三、代码实现

1、test.c文件

#include"game.h"
char ret = 0;//ret用来存放比赛结果
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);//玩家 电脑 走旗while (1){//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL); //打印玩家的每一步走棋//判断玩家是否赢得游戏ret = IfWin(board, ROW, COL);//玩家赢了*  电脑赢了#  平局Q  游戏继续Cif (ret != 'C')break;//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL); //打印电脑的每一步走棋//判断电脑是否赢得游戏ret = IfWin(board, ROW, COL);if (ret != 'C')break;}if (ret == '*'){printf("%c玩家获胜!\n", ret);}else if (ret == '#'){printf("%c电脑获胜!\n", ret);}else {printf("%c     平局!\n", ret);}DisplayBoard(board, ROW, COL);
}int main()
{int input = 0;srand((unsigned int)time(NULL));//配合rand()函数生成随机值,因为只需要调用一次所以放到main()函数中do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:printf("三子棋游戏\n");game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);return 0;
}

2、game.c文件

#include"game.h"//初始化棋盘的函数
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;for (i = 0; i < row; i++){j = 0; for ( j; j < col; j++) //打印   |   |   {printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");j = 0;for ( j; j < col; j++)//打印---|---|---{if (i < row - 1){printf("---");if (j < col - 1){printf("|");}}}printf("\n");}
}//玩家下棋的函数
void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家走:>\n");while (1){printf("请输入下棋的坐标:>");scanf("%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("坐标非法,请重新输入!");}}
}//电脑下棋的函数
void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑走:>");while (1){//生成随机坐标int x = rand() % row;int y = rand() % col;//下棋//判断坐标是否被占用if (board[x][y] == ' '){printf("%d %d\n", x + 1, y + 1);//输出电脑下棋的坐标board[x][y] = '#';//电脑使用#下棋break;}}
}//判断棋盘是否已经满了的函数
int IfFull(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 IfWin(char board[ROW][COL], int row, int col)
{//判断行for (int i = 0; i < row; i++){for (int j = 2; j < col; j++){if (board[i][j - 2] == board[i][j - 1] && board[i][j - 1] == board[i][j] && board[i][j] != ' '){return board[i][j];}}}//判断列for (int j = 0; j < col; j++){for (int i = 2; i < row; i++){if (board[i - 2][j] == board[i - 1][j] && board[i - 1][j] == board[i][j] && board[i][j] != ' '){return board[i][j];}}}//判断右交叉for (int i = 2; i < row; i++){for (int j = 2; j < col; j++){if (board[i - 2][j - 2] == board[i - 1][j - 1] && board[i - 1][j - 1] == board[i][j] && board[i][j] != ' '){return board[i][j];}}}//判断左交叉for (int i = 1; i < row - 1; i++){for (int j = 1; j < col - 1; j++){if (board[i - 1][j + 1] == board[i][j] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' '){return board[i][j];}}}//判断平局int full = IfFull(board, row, col);if (full == 1){return 'Q';}//游戏继续return 'C';
}

3、game.h文件

//头文件的包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>//符号的定义
#define ROW 3
#define COL 3//函数的声明//初始化棋盘函数
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);
//判断游戏结果  玩家赢了*  电脑赢了#  平局Q  游戏继续C
char IfWin(char board[ROW][COL], int row, int col);
//判断棋盘是否已经下满
int IfFull(char board[ROW][COL], int row, int col);


感谢你的阅读,希望对你有所帮助~

欢迎批评指正,共同进步!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络原理】TCP 协议中比较重要的一些特性(三)

目录 1、拥塞控制 2、延时应答 3、捎带应答 4、面向字节流 5、异常情况处理 5.1、其中一方出现了进程崩溃 5.2、其中一方出现关机&#xff08;正常流程的关机&#xff09; 5.3、其中一方出现断电&#xff08;直接拔电源&#xff0c;也是关机&#xff0c;更突然的关机&am…

计算机网络 |内网穿透

其实内网穿透&#xff0c;也挺好玩的&#xff0c;如果在大学的时候&#xff0c;那个时候讲计算机网络的老师能横向延展&#xff0c;估计课也会更有趣不少&#xff0c;本来计算机网络这门课就是计算机课程中可玩性最搞的。 只能说&#xff0c;怪可惜的 回到正题&#xff0c;内网…

SQL-Labs靶场“32-33”关通关教程

君衍. 一、32关 GET单引号闭合宽字节注入1、源码分析2、宽字节注入原理3、联合查询注入4、updatexml报错注入5、floor报错注入 二、33关 GET单引号addslashes逃逸注入1、源码分析2、联合查询注入3、updatexml报错注入4、floor报错注入 SQL-Labs靶场通关教程&#xff1a; SQL注入…

GaN HEMTs在电力电子应用中的交叉耦合与基板电容分析与建模

来源&#xff1a;Analysis and Modeling of Cross-Coupling and Substrate Capacitances in GaN HEMTs for Power-Electronic Applications&#xff08; TED 17年&#xff09; 摘要 本文提出了一种考虑了基板电容与场板之间交叉耦合效应的场板AlGaN/GaN高电子迁移率晶体管(HE…

zookeeper快速入门二:zookeeper基本概念

本文是zookeeper系列之快速入门中的第二篇&#xff0c;欢迎大家观看与指出不足。 目录 一、zookeeper的存储结构 二、什么是znode 三、znode节点的四种类型 四、权限控制ACL&#xff08;Access Control List&#xff09; 五、事件监听watcher 一、zookeeper的存储结构 z…

【Java系列】OOM 时,JVM 堆栈信息保存和分析

一、前言 在日常开发中&#xff0c;即使代码写得再谨慎&#xff0c;免不了还是会发生各种意外的事件&#xff0c;比如服务器内存突然飙高&#xff0c;又或者发生内存溢出(OOM)。当发生这种情况时&#xff0c;我们怎么去排查&#xff0c;怎么去分析原因呢&#xff1f; 一般遇到…

MySQL8空间索引失效

发现问题 表结构如下&#xff0c;boundary字段建立空间索引 CREATE TABLE area (id int(11) NOT NULL COMMENT 行政区划编码,pid int(11) NOT NULL COMMENT 上级编码,deep int(11) NOT NULL COMMENT 深度,name varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_…

深入理解RAG:检索与生成的融合

原文地址&#xff1a;https://dev.to/portkey/understanding-rag-a-deeper-dive-into-the-fusion-of-retrieval-and-generation-1l4b 深入理解RAG:检索与生成的融合 检索增强生成(RAG)模型代表了检索系统和生成模型两大不同但互补组件完美结合的杰作。通过无缝集成相关信息检…

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem 从这一章开始讲负反馈Control系统和小信号建模. 13.2 The Feedback Theorem 首先介绍 Middlebrook’s Feedback Theorem 考虑下面负反馈系统 传输函数 Guo/ui G ( s ) u o u i G ∞ T 1 T G…

观察者模式的理解和引用

1.前言 在之前的H5小游戏中&#xff0c;对于长连接发送的不同类型数据包的处理&#xff0c;是通过switch语句进行处理的&#xff0c;于是在自己的代码中出现了大量的case分支&#xff0c;不方便进行维护和后期的版本迭代。于是在老师的指导下&#xff0c;开始寻求使用观察者模…

2.26回顾章节主体线索脉络,课程要求(评分)

3)翻译程序、汇编程序、编译程序、解释程序有什么差别&#xff1f;各自的特性是什么&#xff1f; 翻译程序是指把高级语言源程序翻译成机器语言程序&#xff08;目标代码&#xff09;的软件。 翻译程序有两种&#xff1a;一种是编译程序&#xff0c;它将高级语言源程序一次全部…

idea Springboot 在线考试管理系统开发mysql数据库web结构java编程计算机网页

一、源码特点 springboot 在线考试管理系统是一套完善的完整信息系统&#xff0c;结合mvc框架和bootstrap完成本系统springboot spring mybatis &#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有…

【ESP32接入国产大模型之MiniMax】

1. MiniMax 讲解视频&#xff1a; ESP32接入语言大模型之MiniMax MM智能助理是一款由MiniMax自研的&#xff0c;没有调用其他产品的接口的大型语言模型。MiniMax是一家中国科技公司&#xff0c;一直致力于进行大模型相关的研究。 随着人工智能技术的不断发展&#xff0c;自然语…

AI - 支持向量机算法

&#x1f9e8;概念 支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种强大的机器学习算法&#xff0c;主要用于解决二分类问题。 SVM的核心思想是找到一个超平面&#xff0c;这个超平面能够最好地将数据分为两类&#xff0c;即在保证分类准确的情况下&am…

C/C++火柴棍等式

有n根(n<24)火柴棍&#xff0c;你可以拼出多少个形如“ABC"的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零&#xff0c;则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示: 依次需要用到的火柴棍数目为6 2 5 5 4 5 6 3 7 6 。 如果是初学者可能会这么写。 …

音频的录制及播放

在终端安装好pip install pyaudio&#xff0c;在pycharm中敲入录音的代码&#xff0c;然后点击运行可以在10s内进行录音&#xff0c;录音后的音频会保存在与录音代码同一路径项目中&#xff0c;然后再新建项目敲入播放的代码&#xff0c;点击运行&#xff0c;会把录入的录音进行…

PHP+golang开源办公系统CRM管理系统

基于ThinkPHP6 Layui MySQL的企业办公系统。集成系统设置、人事管理、消息管理、审批管理、日常办公、客户管理、合同管理、项目管理、财务管理、电销接口集成、在线签章等模块。系统简约&#xff0c;易于功能扩展&#xff0c;方便二次开发。 服务器运行环境要求 PHP > 7.…

32程序结构学习

初始化代码 void LED_GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure;/*开启GPIOC的外设时钟*/RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); /*选择要控制的GPIOC引脚*/ GPIO_InitStructur…

【管理咨询宝藏40】内部报告:电力市场建设现状、挑战及思考

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏40】内部报告&#xff1a;电力市场建设现状、挑战及思考 【格式】PDF版本 【关键词】战略规划、行业分析、管理咨询 【文件核心观点】 - 各类主…

App的测试,和传统软件测试有哪些区别?增加哪些方面的测试用例

从上图可知&#xff0c;测试人员所测项目占比中&#xff0c;App测试占比是最高的。 这就意味着学习期间&#xff0c;我们要花最多的精力去学App的各类测试。也意味着我们找工作前&#xff0c;就得知道&#xff0c;App的测试点是什么&#xff0c;App功能我们得会测试&#xff0…