ms_toollib/
lib.rs

1//! # 扫雷算法工具箱
2//! 基于Rust语言,提供扫雷游戏相关算法的高效、内存安全的实现,并发布到各个平台。目前包括[crates.io](https://crates.io/crates/ms_toollib)、[pypi.org](https://pypi.org/project/ms-toollib/)、[npmjs.com](https://www.npmjs.com/package/ms-toollib)这三个平台。Python、Rust、Javascript、Typescript的用户可以流畅地使用相应的功能,C、C++的用户也可以使用。安装、使用这些工具箱需要有对应语言的基本的知识。项目地址在[ms_toollib](https://github.com/eee555/ms_toollib)。以下是快速入门。
3//! ## 特殊名词解释
4//! 注意:只包含本工具箱的文档中特有的名词解释。读者需具备“扫雷术语”等前置知识。
5//! 1. “游戏局面”
6//!    - 变量名为`game_board: Vec<Vec>`
7//!    - 类型
8//!      - Python:`list[list[int]]`
9//!      - Javascript、Typescript:`Array(Array())`
10//!      - C:`struct Board { struct Row *rows; size_t n_row; }; struct Row { int32_t *cells; size_t n_column; }`
11//!      - C++:`std::vector<int32_t>`
12//!    - 值的含义
13//!      - `0`代表空
14//!      - `1`到`8`代表数字1到8
15//!      - `10`代表未打开
16//!      - `11`代表算法认为是雷(百分百正确),或玩家在游戏中标的雷(玩家认为这是雷,但玩家可能犯错)
17//!      - `12`代表算法已经确定该位置不是雷,但玩家暂时还没点开,模样仍然是未打开的样子
18//!      - `14`表示踩到了雷游戏失败以后显示的标错的雷对应叉雷
19//!      - `15`表示踩到了雷游戏失败了对应红雷
20//!      - `16`表示背景不透明的白雷,失败后显示出来的其他的雷
21//!      - `18`表示局面中,由于双击的高亮,导致看起来像0的格子
22//!    - 第一个索引是行,第二个索引是列。例如:高级中,`game_board[0][0]`代表最左上角位置,`game_board[15][29]`代表最右下角位置。
23//!    - **注意**:游戏局面中`11`的作用类似于游戏时的标雷,但是区别在于,玩家标出的雷可能是错误的,而算法的判断一定是正确的。这两种情况都用同一个数字表示。通俗地讲,因为算法需要保证百分百的正确性,所以玩家标出来的雷,算法一个也不相信,这意味着这两种含义不可能同时出现。
24//! 1. “真实局面”或“局面”
25//!    - 变量名为`board: Vec<Vec>`
26//!    - 值的含义
27//!      - `0`代表空
28//!      - `1`到`8`代表数字1到8
29//!      - `-1`代表雷
30//! 1. 游戏局面和局面的区别
31//!    - 游戏局面是游戏时玩家看见的局面,随鼠标的点击操作而变化。
32//!    - 真实局面是可以看见雷的实际局面,不会随操作而变化。
33//! 1. “矩阵”
34//!    判雷的本质是求解带有0-1约束的非齐次线性欠定方程组。
35//!    在线性代数方程`Ax=b`中:
36//!    - 矩阵A的变量名为`matrix_a`,代表系数矩阵
37//!    - 矩阵x的变量名为`matrix_x`,代表未知量矩阵
38//!    - 矩阵b的变量名为`matrix_b`,代表常数矩阵
39//!    - 变量后加上`s`代表分段;加上`ses`代表分块且分段
40//! 1. “分块”
41//!    计算概率时,假如把整个局面全列成一个方程式,那么,方程中的变量数等于空的边缘的格子数。一般数目较大不易求解,需要使用分块技巧来加速。
42//!    直观地看,游戏局面中,贯通上下两边的空可以把游戏局面分成两块;复杂的空可以把游戏局面分割成更多块。因此计算概率时,可以独立讨论被空分割成的若干块的情况(即系数矩阵可以分块),最后汇总计算出最终结果。
43//! 1. “分段”
44//!    仅仅分块还是不够,一些块的边缘仍然很长。但是在块的边缘,未知格往往是两两相邻的(而不是多个未知格互相相邻,即无向图的割点很多),而且其中部分未知格往往是可以简单求出的。只要求出这些未知格并代入原方程,就可以把大方程分割成小方程(即系数矩阵为分块对角矩阵),从而加速求解。
45//! ## 函数签名说明
46//! Rust是一门强类型的语言,其函数签名反映了诸多信息。以下为不熟悉本语言的开发人员提供简要的说明。
47//! - 变量名+冒号+格式:表明参数的格式。例如`i32`代表有符号4字节的整数、`u8`代表无符号1字节的整数;`Vec<>`代表内存分配在堆上的可变长度的向量。
48//! - `mut`:代表这个参数是可变的。例如`pub fn mark_board(board: &mut Vec<Vec<i32>>)`中,会对传入的局面直接修改。如果不带`mut`,则不会修改。
49//! ## API命名原则
50//! 约定如下原则:
51//! - 原则1:为方便开发人员使用,本工具箱在所有平台所有的api都是相同的。
52//! - 原则2:所有平台的版本号原则上相同,如果不相同,代表还未更新到。
53//! - 原则3:结构体和类名均使用大驼峰命名法(CamelCase)、方法名和函数名均使用蛇形命名法(snake_case亦称下划线命名法)。
54//! ## 项目背景
55//! [ms_toollib](https://github.com/eee555/ms_toollib)工具箱的设计绝不是纸上谈兵,是由[元扫雷](https://github.com/eee555/Solvable-Minesweeper)(亦称黑猫扫雷)项目的算法部分拆分而来,算法经过实际使用验证,具有深厚的项目背景。
56//! ## 安全性
57//! 本工具箱不直接提供机扫(机器扫雷)相关工具;同时,不提倡纯粹机扫相关的研究,尤其不提倡那些通过机扫模拟人类扫雷的研究;使用机扫的录像攻击排名网站的审查体系是严格禁止的,任何相关尝试都是不道德的!
58
59// cargo doc --features rs --no-deps --open
60// cargo build --release --features py
61// cargo bench
62// cargo publish --features rs
63// 需要换成官方的源,不能用镜像
64// cargo yank --vers 0.0.1
65mod utils;
66#[cfg(any(feature = "js"))]
67pub use utils::get_random_int;
68pub use utils::{
69    cal_all_solution, cal_bbbv, cal_board_numbers, cal_cell_nums, cal_isl, cal_op,
70    cal_table_minenum_recursion, combine, is_good_chording, laymine, laymine_op, refresh_board,
71    refresh_matrix, refresh_matrixs, refresh_matrixses, unsolvable_structure,
72};
73
74mod miscellaneous;
75
76mod algorithms;
77#[cfg(any(feature = "py", feature = "rs"))]
78pub use algorithms::{laymine_solvable_thread, sample_bbbvs_exp, obr_board};
79
80#[cfg(any(feature = "py", feature = "rs"))]
81#[deprecated]
82pub use {
83    algorithms::sample_bbbvs_exp as sample_3BVs_exp,
84    algorithms::obr_board as OBR_board,
85};
86
87pub use algorithms::{
88    cal_probability_cells_is_op, cal_probability, cal_probability_onboard,
89    get_all_not_and_is_mine_on_board, is_able_to_solve, is_guess_while_needless, is_solvable,
90    laymine_solvable, laymine_solvable_adjust, mark_board, solve_direct, solve_enumerate,
91    solve_minus, try_solve,
92};
93// #[cfg(any(feature = "rs"))]
94// pub use algorithms::{mark_board, solve_direct, solve_enumerate, solve_minus};
95
96mod board;
97pub use board::{Board, GameBoard};
98
99pub mod videos;
100pub use videos::{
101    valid_time_period, AvfVideo, BaseVideo, EvfVideo, GameBoardState, MinesweeperBoard, MouseState,
102    MvfVideo, RmvVideo,
103};
104
105mod big_number;
106
107#[cfg(any(feature = "py", feature = "rs"))]
108mod obr;
109#[cfg(any(feature = "py", feature = "rs"))]
110pub use obr::ImageBoard;
111
112// #[cfg(any(feature = "py", feature = "rs"))]
113mod safe_board;
114#[cfg(any(feature = "py", feature = "rs"))]
115pub use crate::safe_board::SafeBoard;
116#[cfg(any(feature = "py", feature = "rs"))]
117pub use crate::safe_board::SafeBoardRow;
118
119
120// 最大枚举长度限制。超过这个长度,概率计算不准。全雷网的高级没有发现超出此限制的。
121const ENUM_LIMIT: usize = 55;