私は小さな戦略ゲームを書いていますが、循環リンクリストの実装に問題があります。安全な錆で循環リンクリストを作成できません。安全でないバージョンがクラッシュする
ゲームには、ゲームが終了するまで、1つずつラウンドしてアクションを取っている複数の人が含まれます。しかし、これは、各要素が次のプレイヤーへの参照を持つプレーヤーである循環リンクリストを使用することによって行うことができます。構造は次のようである:
#[derive(Debug, Clone)]
struct Player {
name: String,
killed: bool,
next: Option<Box<Player>>,
}
私はまた、現在のアクティブプレイヤーへのポインタをしたいし、それの状態を変更することができるが、私は錆は私が同じオブジェクトに2つの可変の参照を持ってすることはできませんだと思います各プレイヤーはすでに次のプレイヤーへの変更可能な参照を持っているからです。
私が思いついたのは、以前のプレーヤーが所有していて、現在のプレーヤーを指しているBox
への簡単な変更可能な参照を使用できるということです。エラーは可変性についてもですが、私はそれを修正する方法が分からない
fn main() {
let mut p3: Player = Player {
name: "C".to_string(),
killed: false,
next: None,
};
let mut p2: Player = Player {
name: "B".to_string(),
killed: false,
next: Some(unsafe { Box::from_raw(&mut p3) }),
};
let mut p1: Player = Player {
name: "A".to_string(),
killed: false,
next: Some(unsafe { Box::from_raw(&mut p2) }),
};
p3.next = Some(unsafe { Box::from_raw(&mut p1) });
println!("GAME STARTED!");
let mut current_player = p3.next.as_mut().unwrap();
let mut count = 0;
while count < 10 {
println!("Player to kill/save {}", current_player.name);
(*current_player).killed = !(*current_player).killed;
println!("Player {} is killed: {}",
(*current_player).name,
(*current_player).killed);
current_player = (*current_player).next.as_mut().unwrap();
count = count + 1
}
println!("End!");
}
:私は、問題が発生したシンプルな主な機能を書きました。循環リンクリストと現在のプレーヤーへのポインタを使用するのではなく、Rustでアイデアを実装するより良い方法があるのだろうかと思います。たぶん別の構造に切り替えるべきでしょうか?
エラーメッセージは、ここで最初の数行はかなり長いですされています。私はBox
の不変の参照を返しますas_ref()
へas_mut()
方法を変更し、行をコメントした場合
error: cannot borrow `current_player` (via `current_player.name`) as immutable because `current_player` is also borrowed as mutable (via `current_player.next`) [E0502]
println!("Player to kill/save {}", current_player.name);
^~~~~~~~~~~~~~~~~~~
note: mutable borrow occurs here (via `current_player.next`)
current_player = (*current_player).next.as_mut().unwrap();
^~~~~~~~~~~~~~~~~~~~~~
note: mutable borrow ends here
}
// (*current_player).killed = !(*current_player).killed;
プログラムは正常にビルドできますが、終了時に不明なランタイムエラーが発生します。それがなぜ起こるかわからない。 ( - 一意Box
によって所有されているものとするT
Box<T>
と同じ)さび&mut
において
GAME STARTED!
Player to kill/save A
Player A is killed: false
Player to kill/save B
Player B is killed: false
......
Player to kill/save C
Player C is killed: false
Player to kill/save A
Player A is killed: false
End!
error: An unknown error occurred
私は、 '' Iterator :: cycle'](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.cycle)を 'のVec'で使うことができます。手動でインデックスをインクリメントしてラッピングするのではなく、 –
@ChrisEmersonそれは素晴らしい考えです!残念ながら、 'itterator :: cycle'を可変イテレータで使用することはできません:' std :: slice :: IterMut <...>:std :: clone :: Clone is not'。そうしないと、複数の可変参照を同時に取得することができます。ベクトルを 'RefCell'に変更し、 'borrow_mut'を実行することができます。 –
Shepmaster
@Shepmaster @Chris 'cycle'を' kill'に 'Cell'に変更するもう一つの方法です。これは 'RefCell'よりも簡単です。 –
krdln