微调器板条箱有一个枚举,其中包含大量可能的微调器。
这是枚举(跳过除顶部和底部4之外的所有值):
pub enum Spinners {
Dots,
Dots2,
Dots3,
Dots4,
...
Shark,
Dqpb,
Weather,
Christmas,
}
新微调器易于创建:
extern crate spinners;
use spinners::{Spinner, Spinners};
use std::thread::sleep;
use std::time::Duration;
fn main() {
let sp = Spinner::new(Spinners::Dots9, "Waiting for 3 seconds".into());
sleep(Duration::from_secs(3));
sp.stop();
}
但是,我希望随机选择一个微调器,这是行不通的:
let spinner_enum = rng.choose(Spinners).unwrap_or(&Spinners::Dots9);
因为:
error[E0423]: expected value, found enum `Spinners`
let spinner_enum = rng.choose(Spinners).unwrap_or(&Spinners::Dots9);
^^^^^^^^ not a value
如何随机选择枚举值,并使用该值显示随机微调器?
在将来的这里,我们可能会使用strum\u宏::FromRepr和EnumCount:https://docs.rs/strum_macros/0.24.0/strum_macros/derive.FromRepr.html
use strum::EnumCount;
use strum_macros::{EnumCount, FromRepr};
#[derive(FromRepr, Debug, PartialEq, EnumCount)]
enum Spinners{ Dots, Dots2, ... }
let randomInteger = 0; //Worst RNG ever!
assert_eq!(Some(Spinners::Dots), Spinners::from_repr(randomInteger));
let spinner_enum =
Spinners::from_repr(rng.gen_range(0..Spinners::COUNT))
.unwrap_or(&Spinners::Dots9);
计数由EnumCount自动创建和分配。from\U repr在数字与变量不对应时返回None,例如可能太高,或者您为一个或多个变量指定了数字,从而留下了间隙。
编辑:微调器板条箱可能无法与FromRepr一起使用,因为它需要注释枚举的定义,而据我所知,除非修改代码,否则无法使用;如果您这样做了,请发布拉取请求!但如果您已经定义了自己的枚举,那么Bob就是您的叔叔。
既然Shepmaster问了我,我可以建议另外两个选择。
不幸的是。选择(微调器)无法工作,因为无法迭代枚举值;请参阅:在Rust中,是否有方法遍历枚举的值?
您大概可以使用strum的EnumIter
来允许迭代。在Rand 0.4和0.5中,select
不支持迭代器,但您可以将所有选项收集到Vec
中,或者枚举并匹配索引。在Rand 0.6中,将有一个支持迭代器的select
变体,尽管它可能会很慢(取决于我们是否可以针对ExactSizeIterator
s对其进行优化)。
use rand::prelude::*;
#[derive(EnumIter)]
enum Spinner { ... }
let mut rng = thread_rng();
let options = Spinner::iter().collect::<Vec<_>>();
let choice = rng.choose(&options);
// or:
let index = rng.gen_range(0, MAX);
let choice = Spinner::iter().enumerate().filter(|(i, _)| i == index).map(|(_, x)| x).next().unwrap();
// with Rand 0.6, though this may be slow:
let choice = Spinner::iter().choose(&mut rng);
// collecting may be faster; in Rand 0.6 this becomes:
let choice = Spinner::iter().collect::<Vec<_>>().choose(&mut rng);
另一种选择是将num的FromPrimitive
trait与num-派生一起使用:
#[derive(FromPrimitive)]
enum Spinner { ... }
let choice = Spinner::from_u32(rng.gen_range(0, MAX)).unwrap();
与Rust中的大多数抽象一样,随机值生成由特征提供支持。实现任何特定类型的特征都是一样的,唯一的区别是特征的方法和类型。
使用您的枚举作为类型参数来实现分发
。您还需要选择特定类型的分发;Standard
是一个很好的默认选择。然后使用任何方法生成一个值,例如rand::随机
:
use rand::{
distributions::{Distribution, Standard},
Rng,
}; // 0.8.0
#[derive(Debug)]
enum Spinner {
One,
Two,
Three,
}
impl Distribution<Spinner> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Spinner {
// match rng.gen_range(0, 3) { // rand 0.5, 0.6, 0.7
match rng.gen_range(0..=2) { // rand 0.8
0 => Spinner::One,
1 => Spinner::Two,
_ => Spinner::Three,
}
}
}
fn main() {
let spinner: Spinner = rand::random();
println!("{:?}", spinner);
}
为枚举实现Rand
,然后使用任何方法生成值,例如Rng::gen
:
extern crate rand; // 0.4.2
use rand::{Rand, Rng};
#[derive(Debug)]
enum Spinner {
One,
Two,
Three,
}
impl Rand for Spinner {
fn rand<R: Rng>(rng: &mut R) -> Self {
match rng.gen_range(0, 3) {
0 => Spinner::One,
1 => Spinner::Two,
_ => Spinner::Three,
}
}
}
fn main() {
let mut rng = rand::thread_rng();
let spinner: Spinner = rng.gen();
println!("{:?}", spinner);
}
rand\U派生板条箱可以消除对某些样板的需要,但rand 0.5不存在。
extern crate rand;
#[macro_use]
extern crate rand_derive;
use rand::Rng;
#[derive(Debug, Rand)]
enum Spinner {
One,
Two,
Three,
}
fn main() {
let mut rng = rand::thread_rng();
let spinner: Spinner = rng.gen();
println!("{:?}", spinner);
}
由于您不控制枚举,因此您必须将某些内容复制到代码中才能引用它。您可以创建枚举数组并从中选择
:
use rand::seq::SliceRandom; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
fn main() {
let mut rng = rand::thread_rng();
let spinners = [
another_crate::Spinner::One,
another_crate::Spinner::Two,
another_crate::Spinner::Three,
];
let spinner = spinners.choose(&mut rng).unwrap();
println!("{:?}", spinner);
}
您可以在本地复制整个枚举,为此实现Rand,然后使用一个方法将其转换回其他crates表示。
use rand::{
distributions::{Distribution, Standard},
Rng,
}; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
enum Spinner {
One,
Two,
Three,
}
impl From<Spinner> for another_crate::Spinner {
fn from(other: Spinner) -> another_crate::Spinner {
match other {
Spinner::One => another_crate::Spinner::One,
Spinner::Two => another_crate::Spinner::Two,
Spinner::Three => another_crate::Spinner::Three,
}
}
}
impl Distribution<Spinner> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Spinner {
match rng.gen_range(0..=2) {
0 => Spinner::One,
1 => Spinner::Two,
_ => Spinner::Three,
}
}
}
fn main() {
let spinner = another_crate::Spinner::from(rand::random::<Spinner>());
println!("{:?}", spinner);
}
您可以计算纺纱机的数量并进行匹配:
use rand::Rng; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
fn rando<R: Rng>(mut rng: R) -> another_crate::Spinner {
match rng.gen_range(0..=2) {
0 => another_crate::Spinner::One,
1 => another_crate::Spinner::Two,
_ => another_crate::Spinner::Three,
}
}
fn main() {
let mut rng = rand::thread_rng();
let spinner = rando(&mut rng);
println!("{:?}", spinner);
}
您可以实现一个新类型并实现该类型的随机生成:
use rand::{distributions::Standard, prelude::*}; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
struct RandoSpinner(another_crate::Spinner);
impl Distribution<RandoSpinner> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> RandoSpinner {
RandoSpinner(match rng.gen_range(0..=2) {
0 => another_crate::Spinner::One,
1 => another_crate::Spinner::Two,
_ => another_crate::Spinner::Three,
})
}
}
fn main() {
let RandoSpinner(spinner) = rand::random();
println!("{:?}", spinner);
}
另见:
我需要java JAVA CODE中此解决方案的delphi解决方案
我的问题很简单。我有以下几点: 如何从该枚举中选择随机元素?我试着解决这个问题,但没有成功。
问题内容: 如果我有这样的枚举: 随机挑选一个的最佳方法是什么?它不需要是生产质量的防弹产品,但是相当均匀的分配将是不错的选择。 我可以做这样的事情 但是有更好的方法吗?我觉得这是之前已解决的问题。 问题答案: 我唯一建议的是缓存结果,因为每个调用都会复制一个数组。另外,不要每次都创建一个。保持一个。除此之外,您在做什么都很好。所以:
如果我有这样的枚举: 随机挑选的最佳方式是什么?它不需要是生产质量的防弹产品,但一个相当均匀的分布将是很好的。 我可以做这样的事 但是有没有更好的方法呢?我觉得这是以前解决过的问题。
我正在编写一个二十一点游戏。我有一个所有可用牌类型的枚举。交易时,我想使用Random从枚举中随机选择一张牌给玩家。如何使用整数值对应枚举值?或者,我如何为该枚举的变量随机选择枚举值? 纸牌Enun:
我正在尝试从以下枚举中筛选,以根据随机机会选择其中一个值。 目前,我正在使用此代码选择一个值。 还有我的随机效用函数 目前,大多数情况下,它将准确地选择一个没有问题的层值。然而,大约在的时候,我会得到一个索引arrayoutofbounds。 我知道这是因为枚举中的机会分散到很远的地方(因为如果我向枚举添加更多值,机会不会像它们那样分散,那么就不会发生此异常)。 如何修复此错误?或者有更好的方法