三子棋游戏(基础版)

我们用 C 语言代码实现了一个简单的控制台版三子棋游戏,代码分为三个部分,分别是头文件game.h中定义的函数声明以及两个源文件game.ctest.cgame.c文件。

1.头文件(game.h)部分

首先包含了<stdio.h>(用于标准输入输出操作,像printfscanf函数的使用)、<stdlib.h>(包含了如randsrand等函数,用于生成随机数以及内存分配等相关操作)和<time.h>(获取时间相关信息,用于初始化随机数生成器)这几个常用的标准库头文件。

接着通过#define定义了ROWCOL两个宏常量,都赋值为 3,代表三子棋棋盘的行数和列数。

最后声明了五个函数,这些函数分别用于初始化棋盘、打印棋盘、玩家下棋、电脑下棋以及判断游戏的输赢状态,它们的具体实现在game.c文件中。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 3
#define COL 3//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);//打印棋盘
void DispalyBoard(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);//'X'表示玩家获胜
//'O'表示电脑获胜
//'Q'表示平局
//'C'表示游戏未结束
char IsWin(char board[ROW][COL], int row, int col);

2.源文件(game.c)部分

(InitBoard函数)

这个函数的作用是初始化棋盘,通过两层嵌套的for循环遍历整个二维字符数组(即棋盘),将每个元素都设置为空字符' ',表示棋盘初始状态下各个格子都是空白的,没有棋子。

(DispalyBoard函数)

该函数用于在控制台打印出三子棋棋盘的样子。它通过两层循环来实现,外层循环控制行数,内层循环在每行中先打印出每个格子对应的字符(棋子符号或者空白),并且在格子之间用|进行分隔,每一行数据打印完后,若不是最后一行,还会打印出一行分割线(由---|组成),这样就能清晰地展示出棋盘的布局和当前棋子的放置情况。

(PlayerMove函数)

这个函数实现了玩家下棋的操作逻辑。首先提示玩家输入下棋的坐标,然后通过while循环不断接收玩家输入的坐标,并进行合法性检查:一是检查坐标是否在棋盘的有效范围内(1 到rowcol之间),二是检查输入坐标对应的格子是否为空(没有被其他棋子占据),只有当坐标合法且对应格子为空时,才会将玩家的棋子(用'X'表示)放置到该格子中,随后跳出循环;如果坐标不合法或者格子已被占用,则会相应地提示玩家重新输入。

(ComputerMove函数)

该函数用于实现电脑下棋的操作逻辑。首先会提示 “电脑下棋:>”,然后通过while循环不断生成随机坐标(利用rand函数生成 0 到row - 1以及 0 到col - 1范围内的随机数作为棋盘的行列索引),接着检查该随机坐标对应的格子是否为空,如果为空,就将电脑的棋子(用'O'表示)放置到该格子中,然后跳出循环;这样电脑就能随机地在棋盘上的空白格子中放置棋子了。需要注意的是,这里使用rand函数前一般需要在main函数中通过srand((unsigned int)time(NULL));初始化随机数生成器,以保证每次游戏电脑下棋的随机性。

(IsFull函数)

这个函数用于判断棋盘是否已满,也就是判断棋盘上是否还有空白的格子。通过两层嵌套的for循环遍历整个棋盘,如果发现有任意一个格子的值为' '(即空白),就返回 0,表示棋盘未满;如果整个棋盘遍历完都没有发现空白格子,那就返回 1,表示棋盘已满。

(IsWin函数)

此函数用于判断游戏的输赢状态。它首先按照行、列、对角线的顺序来检查是否有一方的棋子连成了三子一线的情况:

在检查行时,通过外层循环遍历每一行,然后比较该行的三个格子的棋子是否相同且不为空白,如果满足条件,就返回该行棋子对应的字符('X'或者'O'),表示该行对应的玩家或电脑获胜。

检查列的逻辑类似,通过内层循环遍历每一列,比较每列三个格子的棋子情况来判断是否有一方获胜。

对于对角线,分别检查两条对角线上的格子棋子是否相同且不为空白来确定是否有一方获胜。

如果经过上述检查都没有发现有一方获胜,那么接着调用IsFull函数来判断棋盘是否已满,如果已满则返回'Q',表示平局;如果棋盘未满,则返回'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 (j = 0;j < col;j++){board[i][j] = ' ';}}
}void DispalyBoard(char board[ROW][COL], int row, int col)
{int i = 0;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("|");}printf("\n");//打印分割信息if (i < row - 1){int j = 0;for (j = 0;j < col;j++){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] = 'X';break;}else{printf("坐标被占用,请选择其他位置\n");}}else{printf("坐标非法,请重新输入\n");}}
}void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋:>\n");int x = 0;int y = 0;while (1){x = rand() % row;//0~2y = rand() % col;//0~2if (board[x][y] == ' '){board[x][y] = 'O';break;}}}//判断棋盘状态,返回值含义://'X'表示玩家获胜//'O'表示电脑获胜//'Q'表示平局//'C'表示游戏未结束//满了就返回1
//不满就返回0
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][1] != ' '){return board[i][1];}}//列int j = 0;for (j = 0;j< col;j++){if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j]!= ' '){return board[1][j];}}//对角线if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}//没有人赢,判断平局if (IsFull(board, row, col)){return 'Q';}//游戏继续return 'C';}

2.源文件(test.c)部分

(menu函数)

这个函数很简单,就是在控制台打印出游戏的菜单,显示了两个选项,分别是1.play用于开始游戏和0.exit用于退出游戏,使玩家能清晰地看到可操作的选择。

(game函数)

game函数实现了一局三子棋游戏的完整流程。首先定义了一个字符变量ret用于记录游戏的输赢状态,以及一个二维字符数组board来表示棋盘,接着调用InitBoard函数初始化棋盘,并通过DispalyBoard函数显示初始棋盘。然后进入一个while循环,在循环中先让玩家下棋(调用PlayerMove函数),之后调用IsWin函数判断此时游戏是否有输赢结果,如果游戏未结束(返回值为'C'),则显示当前棋盘状态(再次调用DispalyBoard函数),接着让电脑下棋(调用ComputerMove函数),同样再判断游戏输赢情况,如此反复,直到游戏有了输赢或者平局的结果(IsWin函数返回值不为'C'),最后根据ret的值输出相应的游戏结果(玩家赢、电脑赢或者平局),并再次显示棋盘。

(main函数)

main函数是整个程序的入口点。首先通过srand((unsigned int)time(NULL));初始化随机数生成器,确保电脑下棋的随机性。然后进入一个do-while循环,在循环中先调用menu函数显示游戏菜单,接着让用户输入选择,根据用户输入的不同选项(通过switch语句判断),如果输入1则调用game函数开始一局游戏,如果输入0则退出游戏,其他输入则提示选择错误,循环继续,直到用户选择退出游戏为止,最后返回 0 表示程序正常结束。

#include"game.h"void menu()
{printf("****************************************\n");printf("************    1.play    **************\n");printf("************    0.exit    **************\n");printf("****************************************\n");
}void game()
{char ret = 0;char board[ROW][COL] = { 0 };//初始化棋盘的函数InitBoard(board, ROW, COL);DispalyBoard(board, ROW, COL);//下棋while (1){PlayerMove(board, ROW, COL);//判断输赢ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}//显示棋盘DispalyBoard(board, ROW, COL);ComputerMove(board, ROW, COL);//判断输赢ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}//显示棋盘DispalyBoard(board, ROW, COL);}if (ret == 'X'){printf("玩家赢了\n");}else if (ret == 'O'){printf("电脑赢了\n");}else{printf("平局\n");}DispalyBoard(board, ROW, COL);} int main()
{srand((unsigned int)time(NULL));//设置随机数生成起点的int input = 0;do{menu();//打印菜单printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}

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

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

相关文章

使用Chat-LangChain模块创建一个与用户交流的机器人

当然&#xff01;要使用Chat-LangChain模块创建一个与用户交流的机器人&#xff0c;你需要安装并配置一些Python库。以下是一个基本的步骤指南和示例代码&#xff0c;帮助你快速上手。 安装依赖库 首先&#xff0c;你需要安装langchain库&#xff0c;它是一个高级框架&#x…

嵌入式驱动开发详解20(IIO驱动架构)

文章目录 前言IIO子系统简介主要结构体主要API函数 IIO子系统实现SPI框架IIO框架IIO通道详解通道结构体分析通道命名分析icm20608设备通道实现 读取函数写入函数 测试测试效果命令行读取应用程序读取 后续参考文献 前言 IIO 全称是 Industrial I/O&#xff0c;翻译过来就是工业…

Linux 网络维护相关命令简介

目录 零. 概要一. ping二. ip命令2.1 ip address2.2 ip route2.3 ip neighbour 三. traceroute四. DNS查询4.1 nslookup4.2 dig 五. ss 查看网络连接状态 零. 概要 ⏹在Linux系统中有2套用于网络管理的工具集 net-tools 早期网络管理的主要工具集&#xff0c;缺乏对 IPv6、网…

Jenkins持续集成部署——jenkins安装

前言 Jenkins 是一个开源的自动化服务器&#xff0c;主要用于持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;。它为软件开发团队提供了一个易于使用的平台来自动化构建、测试和部署应用程序的过程。 Jenkins 主要功能 1. 持续集成 (CI) 自动构建…

PYG - Cora数据集加载 (自动加载+手动实现)

本文从Cora的例子来展示PYG如何加载图数据集。 Cora 是一个小型的有标注的图数据集&#xff0c;包含以下内容&#xff1a; data.x&#xff1a;2708 个节点&#xff08;即 2708 篇论文&#xff09;&#xff0c;每个节点有 1433 个特征&#xff0c;形状为 (2708, 1433)。data.ed…

《 火星人 》

题目描述 人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言&#xff0c;但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的&#xff0c;首先&#xff0c;火星人把一个非常大的数字告诉人类科学家&#xff0c;科学家破解这…

机器学习基础算法 (二)-逻辑回归

python 环境的配置参考 从零开始&#xff1a;Python 环境搭建与工具配置 逻辑回归是一种用于解决二分类问题的机器学习算法&#xff0c;它可以预测输入数据属于某个类别的概率。本文将详细介绍逻辑回归的原理、Python 实现、模型评估和调优&#xff0c;并结合垃圾邮件分类案例进…

BiTCN-BiGRU基于双向时间卷积网络结合双向门控循环单元的数据多特征分类预测(多输入单输出)

Matlab实现BiTCN-BiGRU基于双向时间卷积网络结合双向门控循环单元的数据多特征分类预测&#xff08;多输入单输出&#xff09; 目录 Matlab实现BiTCN-BiGRU基于双向时间卷积网络结合双向门控循环单元的数据多特征分类预测&#xff08;多输入单输出&#xff09;分类效果基本描述…

云备份项目--工具类编写

4. 文件工具类的设计 4.1 整体的类 该类实现对文件进行操作 FileUtil.hpp如下 /* 该类实现对文件进行操作 */ #pragma once #include <iostream> #include <string> #include <fstream> #include <vector> #include <sys/types.h> #include …

51c大模型~合集94

我自己的原文哦~ https://blog.51cto.com/whaosoft/12897659 #D(R,O) Grasp 重塑跨智能体灵巧手抓取&#xff0c;NUS邵林团队提出全新交互式表征&#xff0c;斩获CoRL Workshop最佳机器人论文奖 本文的作者均来自新加坡国立大学 LinS Lab。本文的共同第一作者为上海交通大…

【大学英语】英语范文十八篇,书信,议论文,材料分析

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…

一起学Git【第一节:Git的安装】

Git是什么&#xff1f; Git是什么&#xff1f;相信大家点击进来已经有了初步的认识&#xff0c;这里就简单的进行介绍。 Git是一个开源的分布式版本控制系统&#xff0c;由Linus Torvalds创建&#xff0c;用于有效、高速地处理从小到大的项目版本管理。Git是目前世界上最流行…

消息队列 Kafka 架构组件及其特性

Kafka 人们通常有时会将 Kafka 中的 Topic 比作队列&#xff1b; 在 Kafka 中&#xff0c;数据是以主题&#xff08;Topic&#xff09;的形式组织的&#xff0c;每个 Topic 可以被分为多个分区&#xff08;Partition&#xff09;。每个 Partition 是一个有序的、不可变的消息…

《Mycat核心技术》第06章:Mycat问题处理总结

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

【day11】面向对象编程进阶(继承)

概述 本文深入探讨面向对象编程的核心概念&#xff0c;包括继承、方法重写、this和super关键字的使用&#xff0c;以及抽象类和方法的定义与实现。通过本文的学习&#xff0c;你将能够&#xff1a; 理解继承的优势。掌握继承的使用方法。了解继承后成员变量和成员方法的访问特…

随手记:小程序兼容后台的wangEditor富文本配置链接

场景&#xff1a; 在后台配置wangEditor富文本&#xff0c;可以文字配置链接&#xff0c;图片配置链接&#xff0c;产生的json格式为&#xff1a; 例子&#xff1a; <h1><a href"https://uniapp.dcloud.net.cn/" target"_blank"><span sty…

6.8 Newman自动化运行Postman测试集

欢迎大家订阅【软件测试】 专栏&#xff0c;开启你的软件测试学习之旅&#xff01; 文章目录 1 安装Node.js2 安装Newman3 使用Newman运行Postman测试集3.1 导出Postman集合3.2 使用Newman运行集合3.3 Newman常用参数3.4 Newman报告格式 4 使用定时任务自动化执行脚本4.1 编写B…

工具环境 | 工具准备

搭建一套验证环境需要的工具如下&#xff1a; 虚拟机&#xff1a;推荐virtualbox ubuntu VM好用&#xff0c;但是免费的好像木有了&#xff0c;ubuntu界面版更加容易上手。 网上找安装教程即可&#xff0c;注意实现文件共享、复制粘贴等功能。 EDA&#xff1a;VCS Veridi 工…

计算机网络之王道考研读书笔记-2

第 2 章 物理层 2.1 通信基础 2.1.1 基本概念 1.数据、信号与码元 通信的目的是传输信息。数据是指传送信息的实体。信号则是数据的电气或电磁表现&#xff0c;是数据在传输过程中的存在形式。码元是数字通信中数字信号的计量单位&#xff0c;这个时长内的信号称为 k 进制码…

ROS2学习配套C++知识

第3章 订阅和发布——话题通信探索 3.3.1 发布速度控制海龟画圆 std::bind cstd::bind绑定成员函数时&#xff0c;需要加上作用域以及取址符号 因为不会将成员函数隐式的转换成指针&#xff0c;因此需要加&符号&#xff1b; 后面的第一个参数必须跟具体对象&#xff0c;c…