Rust小练习,编写井字棋
画叉画圈的游戏通常指的是 井字棋(Tic-Tac-Toe),是一个简单的两人游戏,规则如下:
游戏规则
- 棋盘:游戏在一个3x3的方格上进行。
- 玩家:有两个玩家,一个用“X”表示,另一个用“O”表示。
- 目标:玩家轮流在空格中填入自己的标记,目标是先在横向、纵向或斜向上连续放置三个相同的标记。
- 胜利条件:一旦有玩家先形成连续的三个标记,该玩家获胜。如果所有格子都填满且没有玩家获胜,则游戏平局。
示例棋盘
X | O | X
-----------O | X | O
-----------O | | X
在这个示例中,标记“X”在右列形成了三个相同的标记,因此“X”获胜。
游戏策略
虽然井字棋的规则简单,但为了增加趣味性,玩家可以在游戏中使用不同的策略,例如:
- 尽量占据中心位置,以便于创建更多的胜利路径。
- 阻止对手形成连续的三个标记。
井字棋游戏Rust示例实现代码
下面是一个简单的用 Rust 编写的井字棋(Tic-Tac-Toe)游戏示例。这个示例包括基本的游戏逻辑、玩家输入处理以及胜利条件的判断。
use std::io;#[derive(Clone, Copy, PartialEq)]
enum Player {X,O,
}#[derive(Clone)]
struct Game {board: [[Option<Player>; 3]; 3],current_player: Player,
}impl Game {fn new() -> Self {Game {board: [[None; 3]; 3],current_player: Player::X,}}// 打印棋盘fn print_board(&self) {for row in &self.board {for cell in row {let display = match cell {Some(Player::X) => " X ",Some(Player::O) => " O ",None => " . ",};print!("{}", display);}println!();}}// 玩家移动fn player_move(&mut self, row: usize, col: usize) -> bool {if self.board[row][col].is_none() {self.board[row][col] = Some(self.current_player);true} else {false}}// 检查胜利条件fn check_winner(&self) -> Option<Player> {// 检查行for row in 0..3 {if self.board[row][0].is_some()&& self.board[row][0] == self.board[row][1]&& self.board[row][1] == self.board[row][2]{return self.board[row][0];}}// 检查列for col in 0..3 {if self.board[0][col].is_some()&& self.board[0][col] == self.board[1][col]&& self.board[1][col] == self.board[2][col]{return self.board[0][col];}}// 检查对角线if self.board[0][0].is_some()&& self.board[0][0] == self.board[1][1]&& self.board[1][1] == self.board[2][2]{return self.board[0][0];}if self.board[0][2].is_some()&& self.board[0][2] == self.board[1][1]&& self.board[1][1] == self.board[2][0]{return self.board[0][2];}None}// 切换玩家fn switch_player(&mut self) {self.current_player = match self.current_player {Player::X => Player::O,Player::O => Player::X,};}// 检查平局fn is_draw(&self) -> bool {self.board.iter().all(|row| row.iter().all(|&cell| cell.is_some()))}
}fn main() {let mut game = Game::new();loop {game.print_board();println!("玩家 {:?},请输入行和列 (0-2) 用空格分隔:",game.current_player);let mut input = String::new();io::stdin().read_line(&mut input).unwrap();let coords: Vec<usize> = input.trim().split_whitespace().filter_map(|s| s.parse().ok()).collect();if coords.len() != 2 {println!("请输入两个数字!");continue;}let (row, col) = (coords[0], coords[1]);if row >= 3 || col >= 3 {println!("行和列必须在 0 到 2 之间!");continue;}if game.player_move(row, col) {if let Some(winner) = game.check_winner() {game.print_board();println!("玩家 {:?} 获胜!", winner);break;}if game.is_draw() {game.print_board();println!("游戏平局!");break;}game.switch_player();} else {println!("该位置已经被占用,请选择其他位置!");}}
}
代码说明
-
枚举和结构体:
Player
枚举表示玩家,可能是X
或O
。Game
结构体表示游戏状态,包括棋盘和当前玩家。
-
游戏初始化:
new()
方法创建一个新的游戏实例,初始化棋盘为空(None
)并将当前玩家设置为X
。
-
打印棋盘:
print_board()
方法将棋盘的状态输出到终端,未占用的位置显示为.
,玩家的标记分别显示为X
或O
。
-
玩家移动:
player_move()
方法接受行和列参数,并在指定位置放置当前玩家的标记。若该位置已被占用则返回false
。
-
胜利条件检查:
check_winner()
方法检查当前棋盘是否有玩家获胜。它检查每行、每列和两个对角线。
-
切换玩家:
switch_player()
方法在两个玩家之间切换。
-
平局检查:
is_draw()
方法检查棋盘是否已满且没有获胜者,若是则返回true
。
-
主循环:
- 在
main
函数中,程序不断循环,直到游戏结束。 - 每次循环打印当前棋盘,接收玩家输入,进行移动,检查胜利或平局,并切换玩家。
- 在
运行程序
- 依赖:这个程序不需要额外的依赖。
- 编译和运行:使用 Rust 工具链编译和运行程序。确保你已经安装了 Rust 环境。
cargo run
总结
这个简单的井字棋游戏示例展示了如何使用 Rust 进行基本的输入处理、游戏状态管理和胜利条件检查。你可以在此基础上进行扩展,例如增加图形界面、实现更复杂的 AI 玩家或优化游戏体验。希望这个示例对你有帮助!
相关文章:

Rust小练习,编写井字棋
画叉画圈的游戏通常指的是 井字棋(Tic-Tac-Toe),是一个简单的两人游戏,规则如下: 游戏规则 棋盘:游戏在一个3x3的方格上进行。玩家:有两个玩家,一个用“X”表示,另一个…...
RabbitMQ 入门(八)SpringAMQP消息转换器
一、消息转换器 Spring会把你发送的消息序列化为字节发送给MQ,接收消息的时候,还会把字节反序列化为Java对象。 只不过,默认情况下Spring采用的序列化方式是JDK序列化。众所周知,JDK序列化存在下列问题: - 数…...

【C++】一文带你深入理解C++异常机制
⭐️个人主页:小羊 ⭐️所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言一、C语言处理错误的方式二、C异常三、异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范 四、自定义异…...
Qt之QObject
简介 QObject是qt中所有对象的基类,也是信号槽的基础 结构 #mermaid-svg-mpp2FHEcRCzUK75S {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mpp2FHEcRCzUK75S .error-icon{fill:#552222;}#mermaid-svg-…...

鸿蒙到底是不是纯血?到底能不能走向世界?
关注卢松松,会经常给你分享一些我的经验和观点。 2016年5月鸿蒙系统开始立项。 2018年美国开始经济战争,其中一项就是制裁华为,不让华为用安卓。 2019年8月9日华为正式发布鸿蒙系统。问题就出在这里,大家可以仔细看。 安卓一…...

【Android】MVP架构
MVP架构简介 MVP(Model-View-Presenter)是一种常见的软件架构模式,尤其在Android应用开发中被广泛使用。它将应用程序分为三层:Model、View 和 Presenter,以实现职责分离,提高代码的可维护性和可测试性。 …...
Web服务器之Nginx
Nginx(发音为Engine X)是一款开源的高性能HTTP和反向代理服务器,同时也提供了IMAP/POP3/SMTP服务。由伊戈尔赛索耶夫(Igor Sysoev)为俄罗斯访问量第二的Rambler.ru站点开发,Nginx自发布以来,凭借…...

【大模型实战篇】大模型分词算法Unigram及代码示例
1. 算法原理介绍 与 BPE 分词(参考《BPE原理及代码示例》)和 WordPiece 分词(参考《WordPiece原理及代码示例》)不同,Unigram 分词方法【1】是从一个包含足够多字符串或词元的初始集合开始,迭代地删除其中的…...
Dockerfile搭建ELK
使用 Dockerfile 安装 ELK 一、引言 ELK Stack(Elasticsearch, Logstash, Kibana)是一种流行的日志管理和分析解决方案。它允许用户实时搜索、分析和可视化日志数据。通过 Docker,可以方便地部署 ELK ,快速获取一个功能齐全的日…...
在合规的地方怎么用EACO地球链兑换交换价值?
地球链EACO(EarthChain,简称$E)是一种虚拟数字资产。 目前在中国大陆,虚拟资产相关业务活动属于金融活动,包括虚拟资产的交易、兑换等操作,因此应该谨慎去寻求如何用它来交换价值。 虚拟资产交易炒作活动&…...

VS无法安装Win10SDK_10.0.2200,快捷方法
Visual Studio无法安装Win10SDK_10.0.2200,我在安装VS2019、2022提示,软件就不能编译。 因为之前安装过VS软件,重新安装软件提示“无法安装”。 原因 之前安装在D盘,现在没有D盘了 说明 因为电脑第一次安装VS,会自动安…...
github多个账号配置多个SSH秘钥
背景 对于有多个github账号的同学,需要配置多个ssh秘钥分别管理多个账号。 方法 1、生成多个SSH秘钥 # 为第一个 GitHub 账号生成密钥 ssh-keygen -t ed25519 -C "your_email_1example.com" -f ~/.ssh/id_ed25519_github_work# 为第二个 GitHub 账号生…...
静态/动态代理详解,一次性看完再也不会搞不清!
代理官方原文翻译: 给其他对象提供一个代理或者占位符,来控制对这个对象的访问。 代理最核心的思想: 在客户端和目标对象之间创建一个“中介”,用于保护目标对象和增强目标对象 静态代理: 该代理对象需要我们手动…...

Webserver(2)GCC
目录 安装GCCVScode远程连接到虚拟机编写代码gcc编译过程gcc与g的区别Xftp连接虚拟机上传文件 安装GCC sudo apt install gcc g查看版本是7.5 touch test.c创建代码 但是在虚拟机中写代码很不方便 VScode远程连接到虚拟机编写代码 gcc test.c -o app在虚拟机中用gcc编译的…...

mac电脑设置chrome浏览器语言切换为日语英语等不生效问题
在chrome中设置了语言,并且已经置顶了,但是不生效,在windows上直接有设置当前语言为chrome显示语言,但是mac上没有。 解决办法 在系统里面有一个单独给chrome设置语言的: 单独给它设定成指定的语言,然后重…...

Python中的人工智能框架与实例
在人工智能(AI)领域,Python因其简洁的语法、丰富的库和强大的社区支持,成为了最受欢迎的编程语言之一。本文将详细介绍Python中的人工智能框架,并通过具体实例展示如何使用这些框架来实现不同的人工智能应用。 一、Python中的人工智能框架 …...

论文阅读(二十六):Dual Attention Network for Scene Segmentation
文章目录 1.Introduction3.DANet3.1Position Attention Module3.2Channel Attention Module 论文:Dual Attention Network for Scene Segmentation 论文链接:Dual Attention Network for Scene Segmentation 代码链接:Github 1.Intr…...

Stack和Queue(3)
Stack和Queue(3) priority_queue的模拟实现 priority_queue.h #include <vector>namespace soobin {template<class T, class Container vector<T>>class priority_queue{public://强制生成默认构造priority_queue() default;temp…...

怎样把学生的成绩单独告知家长?
期中考试季的到来让校园里的气氛似乎也变得紧张起来。家长们开始频繁地联系老师,希望了解孩子的表现;孩子们则在考试后,绞尽脑汁地想出各种理由,以期在成绩不理想时能减轻家长的失望。老师们更是忙得不可开交,不仅要批…...
vue3父组件控制子组件表单验证及获取子组件数值方法
1、关键部分的代码如下,我努力交代清楚了,希望能让大家看懂。 <template><KeepAlive><component ref"comp" :is"compNames[steps[compIndex].comp]" /></KeepAlive><el-button click"prevBtn"…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...