我不明白如何编写trait来生成某个范围内的Point。
我尝试使用rand::Rng
为Point结构体生成随机值(用于扫雷舰中的坐标)。
我使用这个网站Generate Random Values - Rust Cookbook,它很好地为简单的数据类型的范围工作。此外,与点工作的例子。
有人能提供代码的例子和一些关于统一点结构的特点的解释吗?
use rand::Rng;
use rand::distributions::{Distribution, Uniform};
fn main() {
let width: u8 = 15; let height: u8 = 15;
let mine_count: u8 = 40;
let mut rng = rand::thread_rng();
let ranger = Uniform::from(0..width);
for _i in 0..=mine_count{
let rand_point: Point = ranger.sample(&mut rng);
println!("Random Point: {:?}", rand_point);
}
}
#[derive(Debug)]
struct Point {
x: u8,
y: u8,
}
impl Distribution<Point> for Uniform<Point> {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}
Compiling my-project v0.1.0 (/home/runner/SyntaxTest)
error[E0277]: the trait bound `Point: SampleUniform` is not satisfied
--> src/main.rs:56:30
|
56 | impl Distribution<Point> for Uniform<Point> {
| ^^^^^^^^^^^^^^ the trait `SampleUniform` is not implemented for `Point`
note: required by a bound in `Uniform`
--> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/src/distributions/uniform.rs:179:23
|
179 | pub struct Uniform<X: SampleUniform>(X::Sampler);
| ^^^^^^^^^^^^^ required by this bound in `Uniform`
error[E0277]: the trait bound `Point: SampleUniform` is not satisfied
--> src/main.rs:57:30
|
57 | fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
| ^^^^^ the trait `SampleUniform` is not implemented for `Point`
note: required by a bound in `Uniform`
--> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/src/distributions/uniform.rs:179:23
|
179 | pub struct Uniform<X: SampleUniform>(X::Sampler);
| ^^^^^^^^^^^^^ required by this bound in `Uniform`
2条答案
按热度按时间ncecgwcz1#
这里的问题是你的代码没有点分布的概念,如果你看Uniform结构体的签名,它的泛型必须实现
SampleUniform
特征,根据文档,SampleUniform
特征定义了采样器类型,应该使用它来生成随机分布,所以,当你写这个:当调用
Uniform::from(0..width)
时,您同时也为u8值定义了一个采样器,这并不是您最终想要的,您想要的(根据代码判断)是生成一个min之间的点的随机分布,比如Point { x:0,y:0 }和一个最大值,最大值可以是另一个点,但也可以定义为一个范围、一个增量、一个区域等。我们的想法是能够编写如下内容:其中
Point::default()
是原点。为了解决你的问题,你需要能够告诉兰德crate你要求的点的分布是什么意思。为了保持你的代码原样,你可以这样重写它:注意,您不再需要实现
Distribution
trait,因为Uniform::from
只要求您的结构体实现SampleUniform
。这里的技巧是Point中的每个字段都需要从值的分布中生成,既然可以使用
UniformInt::<u8>...
来生成这些分布,那么您所需要的只是一个附属结构体,它可以作为这些分布的占位符。注意,现在当你调用
ranger.sample()
时,你实际上是在做两个调用,一个调用x.sample,一个调用y. sample。这将产生一个简洁的API,您可以像以前一样使用ranger而无需任何修改。另一个解决方案是保留u8分布并通过以下操作创建随机点:
这样你就不需要实现任何东西,但是也不那么有趣。希望这能有所帮助。
eit6fx6z2#
您希望为
Uniform<u8>
而不是Uniform<Point>
实现Distribution<Point>
:Playground