【C语言篇】“三子棋”

news/2025/2/4 19:43:33 标签: c语言, 开发语言, 游戏

一、游戏介绍

          三子棋,英文名为 Tic - Tac - Toe,是一款简单而经典的棋类游戏游戏在一个 3×3 的棋盘上进行,两名玩家轮流在棋盘的空位上放置自己的棋子(通常用 '*' 和 '#' 表示),率先在横、竖或斜方向上连成三个相同棋子的玩家获胜。如果棋盘被填满且没有玩家获胜,则游戏平局                 

二、程序设计思路

(一)棋盘的表示

      使用一个二维字符数组 board[3][3] 来表示棋盘,数组的每个元素对应棋盘上的一个位置。初始时,棋盘上的每个位置都用空格字符 ' ' 表示空位。

(二)游戏流程控制

  1. 初始化棋盘:将棋盘上的每个位置都设置为空位。
  2. 打印棋盘:   在每次玩家下棋后,将当前的棋盘状态打印出来,方便玩家查看。
  3. 玩家下棋:   轮流让两个玩家输入下棋的位置,检查位置是否合法(是否为空位),如果合法则在相应位置放置玩家的棋子。
  4. 判断胜负:   在每次玩家下棋后,检查是否有玩家获胜或者游戏是否平局。
  5. 游戏结束:   如果有玩家获胜或者游戏平局,打印相应的结果并结束游戏

 三、代码实现

  游戏逻辑:

解析游戏逻辑:

先创建棋盘,对棋盘初始化为‘ ’(空格),接下来就进入游戏环节,玩家先下棋,下完棋判断输赢,如果返回值为“C”就继续,反之胜负已定,跳出循环,对返回值进行判断,如果是*玩家赢,#电脑赢,!平局,这个时候整个游戏的逻辑就完了,下面的菜单啥的都很普通,我就不讲解了

如何生成随机数:

在三子棋游戏中,若涉及电脑下棋,其坐标通常是随机生成的。在 C 语言里,rand函数可用于生成随机数。然而,它生成的是一种 “伪随机数”,这是因为rand()括号内的种子默认值为 1。若不手动给种子赋值,每次运行程序时,种子始终为 1,那么生成的随机数序列也会是一样的。这是由于随机数的生成会随着种子的变化而变化。

为解决这一问题,我们引入srand函数,它是初始化随机数生成器。只要srand函数的种子不断变化,rand函数生成的随机数序列也会相应地不断变化。

在实际程序中,通常会使用程序运行的时间作为种子,因为时间是时刻在变化的。C 语言提供了time函数来获取当前时间。time函数会返回自 1970 年 1 月 1 日 0 时 0 分 0 秒起至程序当前运行时刻的差值,单位为秒,返回值类型为time_t。当time函数的参数为NULL时,它仅返回这个时间差值,该差值也被称为 “时间戳”。通过srand((unsigned int)time(NULL))这样的语句(因为srand的参数是unsigned int 类型,所以我们将time的返回类型强转为无符号整型),就能以当前时间作为随机数生成器的种子,使得每次程序运行时rand生成的随机数都不同,从而实现电脑下棋坐标的随机化

在程序中srand((unsigned int)time(NULL))一般放在程序开头合适的位置,比如main函数开头,且只调用一次来设置种子,后续多次调用rand生成不同随机数。否则如果在程序中多次调用srand((unsigned int)time(NULL))可能达不到预期随机效果(因为短时间内时间戳变化不大,可能生成相近随机数序列)

棋盘的初始化:

棋盘的打印:

玩家下棋:

 如果要正确访问棋盘中的每个位置的话,理应是用下标访问,但是玩游戏的人可不知道有下标这样的说法,他们只知道数学中的行和列,所以在判断断这个位置有没有棋时,给玩家输入的坐标-1,刚好对应了数组中的下标

电脑下棋:

 判断输赢:

 判断获胜的情况有三种:某一行棋子相同、某一列棋子相同以及两条对角线上的棋子相同

 如果满足其中某一个条件,就返回第一个位置的棋,这个时候就和解析逻辑那块对应着了

判断平局:

只要棋盘上还有一个空的位置,就没有结束,如果棋盘下满了还没有决出胜负,那就是平局

如果判断输赢那块的判断没有一个满足,就返回C,继续游戏

完整代码:

test.c:

game.h :

game.c :

通过以上代码实现了一个简单的三子棋游戏。这个小游戏不仅帮助我们巩固了 C 语言中数组、循环、条件判断等基础知识,还让我们对游戏编程的基本流程有了一定的了解。你可以进一步对游戏进行扩展,比如添加电脑对战模式、优化界面等,以提升游戏的趣味性和可玩性 


http://www.niftyadmin.cn/n/5841774.html

相关文章

通信方式、点对点通信、集合通信

文章目录 从硬件PCIE、NVLINK、RDMA原理到通信NCCL、MPI原理!通信实现方式:机器内通信、机器间通信通信实现方式:通讯协调通信实现方式:机器内通信:PCIe通信实现方式:机器内通信:NVLink通信实现…

Rust枚举(Enum)完全指南:用类型安全表达多样性

枚举(Enum)是Rust类型系统的核心特性之一,它不仅能够表示简单的选项集合,还能携带复杂数据,配合模式匹配实现强大的逻辑控制。本文将通过具体示例,深入解析Rust枚举的完整用法。 一、基础枚举定义 1.1 简单…

Java | CompletableFuture详解

关注:CodingTechWork CompletableFuture 概述 介绍 CompletableFuture是 Java 8 引入的一个非常强大的类,属于 java.util.concurrent 包。它是用于异步编程的一个工具,可以帮助我们更方便地处理并发任务。与传统的线程池或 Future 对比&…

Vue-data数据对象

目录 一、Vue中的data数据对象是什么?二、data支持的数据类型有哪些? 一、Vue中的data数据对象是什么? Vue中用到的数据定义在data中。 二、data支持的数据类型有哪些? data中可以写复杂类型的数据,渲染复杂类型数据…

PyQt4学习笔记1】使用QWidget创建窗口

目录 一、创建一个简单的 QWidget 窗口 二、设置窗口属性 1. 设置窗口标题 2. 设置背景颜色 3. 设置窗口大小和位置 4. 设置窗口模式 5. 关闭窗口 6. QWidget 及其子控件的样式 三、添加控件到 QWidget 1. 添加按钮 2. 添加标签 3. 添加文本框 4. 控件布局管理 四、自定义样式 …

【协议详解】卫星通信5G IoT NTN SIB32-NB 信令详解

一、SIB32信令概述 低轨卫星的移动性会导致地面用户设备覆盖不连续,为了解决这一问题,3GPP引入了SystemInformationBlockType32(SIB32)信令,为非连续覆盖预测提供卫星辅助信息。地面设备可以基于SIB32信令中的信息&am…

嵌入式硬件篇---HAL库内外部时钟主频锁相环分频器

文章目录 前言第一部分:STM32-HAL库HAL库编程优势1.抽象层2.易于上手3.代码可读性4.跨平台性5.维护和升级6.中间件支持 劣势1.性能2.灵活性3.代码大小4.复杂性 直接寄存器操作编程优势1.性能2.灵活性3.代码大小4.学习深度 劣势1.复杂性2.可读性3.可维护性4.跨平台性…

stm32小白成长为高手的学习步骤和方法

我们假定大家已经对STM32的书籍或者文档有一定的理解。如不理解,请立即阅读STM32的文档,以获取最基本的知识点。STM32单片机自学教程 这篇博文也是一篇不错的入门教程,初学者可以看看,讲的真心不错。 英文好的同学&#xf…