我正在研究一种涉及Beetle存储在一个对象中的一堆对象的游戏HashMap.每个甲虫都有一个位置,它也可以有一个目标id,它是哈希中另一个甲虫的关键.如果甲虫有目标,则每次游戏循环执行时都需要移动到目标.
我无法执行目标当前位置的查找,因为您不能同时拥有可变且不可变的借位.我明白了,但任何想法如何重组我的具体案例?
我想我只是陷入了几乎任何其他语言的容易程度,我无法看到惯用的Rust方式来做到这一点.这是一个非常小但完整的例子:
use std::collections::HashMap;
type Beetles = HashMap<i32, Beetle>;
struct Beetle {
x: f32,
y: f32,
target_id: i32,
}
impl Beetle {
fn new() -> Beetle {
Beetle {
x: 0.0,
y: 0.0,
target_id: -1,
}
}
}
fn main() {
let mut beetles: Beetles = HashMap::new();
beetles.insert(0, Beetle::new());
beetles.insert(1, Beetle::new());
set_target(&mut beetles, 0, 1);
move_toward_target(&mut beetles, 0);
}
fn set_target(beetles: &mut Beetles, subject_id: i32, target_id: i32) {
if let Some(subject) = beetles.get_mut(&subject_id) {
subject.target_id = target_id;
}
}
fn move_toward_target(beetles: &mut Beetles, beetle_id: i32) {
if let Some(subject) = beetles.get_mut(&beetle_id) {
if let Some(target) = beetles.get(&subject.target_id) {
// update subject position to move closer to target...
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过对主题执行双重查找来解决您的特定问题。首先,从哈希映射中不可改变地借用来收集更新主题所需的信息。然后最终通过从哈希映射中可变地借用所收集的信息来更新主题:
fn move_toward_target(beetles: &mut Beetles, beetle_id: i32) {
if let Some(subject_target_id) = beetles.get(&beetle_id).map(|b| b.target_id) {
let mut target_xy = None; // example
if let Some(target) = beetles.get(&subject_target_id) {
// collect information about target relevant for updating subject
target_xy = Some((target.x, target.y)) // example
}
let subject = beetles.get_mut(&beetle_id).unwrap();
// update subject using collected information about target
if let Some((target_x, target_y)) = target_xy{ // example
subject.x = target_x;
subject.y = target_y;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然而,您将来可能会遇到与甲虫类似且更复杂的问题,因为甲虫是您的中心游戏对象,您可能希望在您的程序中的多个位置同时可变和不可变地引用它们。代码。因此,将甲虫包装在 s 中是有意义的std::cell::RefCell,它在运行时动态检查借用规则。这为您在哈希映射中引用甲虫时提供了很大的灵活性:
fn main() {
let mut beetles: Beetles = HashMap::new();
beetles.insert(0, RefCell::new(Beetle::new()));
beetles.insert(1, RefCell::new(Beetle::new()));
set_target(&mut beetles, 0, 1);
move_toward_target(&mut beetles, 0);
}
fn set_target(beetles: &mut Beetles, subject_id: i32, target_id: i32) {
if let Some(mut subject) = beetles.get_mut(&subject_id).map(|b| b.borrow_mut()) {
subject.target_id = target_id;
}
}
fn move_toward_target(beetles: &mut Beetles, beetle_id: i32) {
if let Some(mut subject) = beetles.get(&beetle_id).map(|b| b.borrow_mut()) {
if let Some(target) = beetles.get(&subject.target_id).map(|b| b.borrow()) {
//example for updating subject based on target
subject.x = target.x;
subject.y = target.y;
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新Beetles类型:
type Beetles = HashMap<i32, RefCell<Beetle>>;
Run Code Online (Sandbox Code Playgroud)