Rust小练习,编写井字棋

在这里插入图片描述

画叉画圈的游戏通常指的是 井字棋(Tic-Tac-Toe),是一个简单的两人游戏,规则如下:

游戏规则

  1. 棋盘:游戏在一个3x3的方格上进行。
  2. 玩家:有两个玩家,一个用“X”表示,另一个用“O”表示。
  3. 目标:玩家轮流在空格中填入自己的标记,目标是先在横向、纵向或斜向上连续放置三个相同的标记。
  4. 胜利条件:一旦有玩家先形成连续的三个标记,该玩家获胜。如果所有格子都填满且没有玩家获胜,则游戏平局。

示例棋盘

 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!("该位置已经被占用,请选择其他位置!");
        }
    }
}

代码说明

  1. 枚举和结构体

    • Player 枚举表示玩家,可能是 XO
    • Game 结构体表示游戏状态,包括棋盘和当前玩家。
  2. 游戏初始化

    • new() 方法创建一个新的游戏实例,初始化棋盘为空(None)并将当前玩家设置为 X
  3. 打印棋盘

    • print_board() 方法将棋盘的状态输出到终端,未占用的位置显示为 .,玩家的标记分别显示为 XO
  4. 玩家移动

    • player_move() 方法接受行和列参数,并在指定位置放置当前玩家的标记。若该位置已被占用则返回 false
  5. 胜利条件检查

    • check_winner() 方法检查当前棋盘是否有玩家获胜。它检查每行、每列和两个对角线。
  6. 切换玩家

    • switch_player() 方法在两个玩家之间切换。
  7. 平局检查

    • is_draw() 方法检查棋盘是否已满且没有获胜者,若是则返回 true
  8. 主循环

    • main 函数中,程序不断循环,直到游戏结束。
    • 每次循环打印当前棋盘,接收玩家输入,进行移动,检查胜利或平局,并切换玩家。

运行程序

  1. 依赖:这个程序不需要额外的依赖。
  2. 编译和运行:使用 Rust 工具链编译和运行程序。确保你已经安装了 Rust 环境。
    cargo run
    

总结

这个简单的井字棋游戏示例展示了如何使用 Rust 进行基本的输入处理、游戏状态管理和胜利条件检查。你可以在此基础上进行扩展,例如增加图形界面、实现更复杂的 AI 玩家或优化游戏体验。希望这个示例对你有帮助!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot基于微信小程序的企业考勤系统设计与实现

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图文章目录 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对各种需求进行规范而严格是十分有…

单链表的建立

步骤&#xff1a; 1.初始化一个单链表 2.每次取一个数据元素&#xff0c;插到表头或者表尾 尾插法建立单链表 头插法建立单链表: 养成好习惯&#xff0c;只要是初始化单链表&#xff0c;都先把头指针指向NULL。 重要应用&#xff1a;单链表的逆置 头插法&#xff0c;尾插…

C++笔记之类三种的继承方式

C++笔记之类三种的继承方式 code review! 文章目录 C++笔记之类三种的继承方式1.《C++ Primer Plus》(第6版)中文版Page 5502.C++类继承方式与能否隐式向上转换的关系1.《C++ Primer Plus》(第6版)中文版Page 550 除基类私有成员变量外(基类公有成员变量和保护成员变量):…

Java 虚拟机实战(基础篇 1万字)

此笔记来自于黑马程序员 基础篇 初识 JVM(Java Virtual Machine) 什么是 JVM JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行 Java 字节码文件 JVM 的功能 翻译成字节码 即时编译 Java语言如果不做任何优化&#xff0c;性能不如C、C等语言。Java 支持跨…

【Linux】-权限

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;深入代码世界&#xff0c;了解掌握 Linux 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ​ 一、权限的概念 在Linux 中&…

“新物种”即将上线,极氪MIX是近几年最“好玩”的新车?

像极氪MIX这样有创意的新能源车 除了概念车外&#xff0c;市面上真的很少能看到类似的量产车 别致可爱的造型、新颖的对开门设计、百变的空间布局 同时兼顾了MPV大空间以及SUV的操控乐趣和通过性 妥妥的“新物种” A级车车长D级车轴距&#xff0c;配合隐藏式双B柱电动对开…

【uniapp+Typescript】300行代码手撸了一个多端图片比较组件

今天刚新鲜出炉的。DCloud市场上的看了下&#xff0c;都不好用&#xff0c;于是自己撸了个。基于unibestccframe框架。 用户图片对比&#xff0c;支持滑块拖动对比、图片放大缩小、下载这些基本功能。 左右对比模式还没写&#xff0c;等什么时候想弄了&#xff0c;再来更新。…

化繁为简,使用 ADManager Plus 简化账户生命周期管理

在 IT 环境中&#xff0c;编排指的是对工作流、应用程序和系统的协调管理&#xff0c;旨在通过简化流程来优化业务性能。IT 管理员可以通过编排&#xff0c;从单个控制台自动执行一系列任务&#xff0c;例如预配账户帐户、数据库管理、事件处理、应用程序和云资源管理。编排对支…

第23章 - Elasticsearch 洞悉你的查询:如何在上线前发现潜在问题!

文章目录 1. 前言2. Profile API - 查询优化2.1 Profile API 简单介绍2.2 查询结果图形化2.3 Profile 注意事项 3. Explain API - 解释查询 1. 前言 在第 21 章中&#xff0c;我介绍了 Elasticsearch 的读优化&#xff0c;但你是否曾疑惑&#xff1a;如何在上线前判断查询的耗…

springboot基于Java的民宿山庄农家乐系统设计与实现

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图文章目录 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 当今社会已经步入了科学技术进步和经济社会快速发展的新时期&#xff0c;国际信息和学术交流也不…

Mojo在Windows上详细安装步骤

Mojo官方文档是基于Linux写的&#xff0c;在Windows上基于WSLUbuntu安装还有些细节问题需要注意&#xff0c;完整安装步骤整理如下&#xff1a; 1.Windows版本必须是Windows10以上&#xff0c;而且版本≥1903&#xff0c;或者内部版本≥18362&#xff0c;若不满足&#xff0c;…

渗透测试实战—教育攻防演练中突破网络隔离

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…

【redis】热点key问题

【redis】热点key问题 【一】什么是热点key问题【二】什么样的key被称为热key【三】热点Key问题的危害【四】如何监控发现热点key【五】热点Key的解决方案【1】使用二级缓存【2】将热key分散到不同的服务器中【3】热key拆分【4】将核心/非核心业务做Redis的隔离 【六】业界已有…

C语言指针(1)

指针一句话就是存储地址的一个变量&#xff0c;当你想要拿到一个地址就需要用到&运算符。 如果要拿数组的地址就不用&运算符&#xff0c;因为数组名就是数组首元素的地址。 int main() {int pa0;int* p&pa;int arr[3]{1,2,3};int* qarr;printf("%d",*p)…

【linux】线程 (三)

13. 常见锁概念 &#xff08;一&#xff09;了解死锁 死锁是指在一组进程中的各个进程均占有不会释放的资源&#xff0c;但因互相申请被其他进程占有的&#xff0c;且不释放的资源&#xff0c;而处于的一种永久等待状态 &#xff08;二&#xff09;死锁四个必要条件 互斥条件…

基准线markLine的值超过坐标轴范围导致markline不显示

解决问题&#xff1a;动态设置yAxis的max值&#xff08;解决基准线不在y轴范围&#xff09; yAxis: [{name: 单位&#xff1a;千,...yAxis,nameTextStyle:{...yAxis.nameTextStyle,padding: [0,26,0,24]},paddingLeft:24,paddingRight:26},{name: 单位&#xff1a;百分比,...yA…

Java开发中知识点整理

正则表达式 测试网址 List<?> List<List<Object>> dataList (List<List<Object>>) httpResponseBody.getData();for (List<Object> data : dataList) {DataSourceEntity dataSource new DataSourceEntity(dataSourceEntity);dataSou…

【二刷hot100】day 4

终于有时间刷刷力扣&#xff0c;求实习中。。。。 目录 1.最大子数组和 2.合并区间 3.轮转数组 4.除自身以外数组的乘积 1.最大子数组和 class Solution {public int maxSubArray(int[] nums) {//就是说可以转换为计算左边的最大值&#xff0c;加上中间的值&#xff0c…

Git的原理和使用(六)

本文主要讲解企业级开发模型 1. 引入 交付软件的流程&#xff1a;开发->测试->发布上线 上面三个过程可以详细划分为一下过程&#xff1a;规划、编码、构建、测试、发 布、部署和维护 最初&#xff0c;程序⽐较简单&#xff0c;⼯作量不⼤&#xff0c;程序员⼀个⼈可以完…

一文详解“位运算“在算法中的应用

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 位运算的相关介绍&#xff08;重要&#xff09; 136. 只出现一次的数字 191.位1的个数 461. 汉明距离 260. 只出现一…