昨日の続きやる。
choose being attackedがリスピンファイターも殴れるバグに気付いたが、ちょっと待って。
ふふふいわし - Behind Coleus
for &entity in &player2_fzone.cards {
if let Ok*1 = query.get(entity) {
available_cards.push(entity);
if let SpinCondition::Spin = spincondition {
// スピンしている場合
if let Some(fighter) = fighter {
println!(
"{}: {} (Fゾーン)[パワー: {}]",
available_cards.len(),
card.name,
fighter.power
);
} else {
println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
}
}
}
}
これで、fzoneな時点でリストに追加しちゃってるから、条件分岐の中に入れればいいと思う。リスピンしてればいいから、
for &entity in &player2_fzone.cards {
if let Ok*2 = query.get(entity) {
if let SpinCondition::Spin = spincondition {
available_cards.push(entity);
// スピンしている場合
if let Some(fighter) = fighter {
println!(
"{}: {} (Fゾーン)[パワー: {}]",
available_cards.len(),
card.name,
fighter.power
);
} else {
println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
}
}
}
}

デバグ中にさらなるバグ、選択肢の数が決まってない系のやつで、0を触るとバグる問題を忘れてはいけないな。

なおっつぁーただ、
println!("Select a card by number (1-{}):", cards_in_fzone.len());
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
if let Ok(selected_index) = input.trim().parse::<usize>() {
if selected_index > 0 && selected_index <= cards_in_fzone.len() {
let selected_entity = cards_in_fzone[selected_index - 1];
if let Ok*3 = query.get(selected_entity) {
withdraw_event_writer.send(Withdraw {
id: selected_entity,
});
println!(" {} を撤退するファイターとして選択しました", card.name); // カード名を表示
}
println!("You selected card with Entity ID: {:?}", selected_entity);
} else {
println!("Invalid selection.");
}
} else {
println!("Please enter a valid number.");
}
println!("Select a card by number (1-{}):", cards_in_fzone.len());
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
// Trim whitespace and attempt to parse the input
match input.trim().parse::<usize>() {
Ok(selected_index) => {
if selected_index > 0 && selected_index <= cards_in_fzone.len() {
let selected_entity = cards_in_fzone[selected_index - 1];
if let Ok*4 = query.get(selected_entity) {
withdraw_event_writer.send(Withdraw {
id: selected_entity,
});
println!("{} を撤退するファイターとして選択しました", card.name); // カード名を表示
}
println!("You selected card with Entity ID: {:?}", selected_entity);
break; // 有効な選択が行われたらループを抜ける
} else {
println!(
"Invalid selection. Please enter a number between 1 and {}.",
cards_in_fzone.len()
);
}
}
Err(_) => {
println!("Please enter a valid number.");
}
}
}
デバグはループ構文にして、まともな値を入力するまで帰れないようにした。
また、0を押せば戻れるようにする。
pub fn pick_fighter_to_withdraw(
query: Query<(Entity, &Card, &Location), With<Player1>>,
mut withdraw_event_writer: EventWriter<Withdraw>,
mut pick_fighter_to_withdraw_event_reader: EventReader<PickFighterToWithdraw>,
mut withdraw_management_event_writer: EventWriter<WithdrawManagement>,
) {
for event in pick_fighter_to_withdraw_event_reader.read() {
let mut cards_in_fzone = Vec::new();
println!("Fゾーンにあるあなたのカードは:");
for (entity, card, location) in query.iter() {
if let Location::FZone = location {
cards_in_fzone.push(entity); // エンティティIDを保存
println!("{}: {}[{}]", cards_in_fzone.len(), card.name, card.energy); // 番号を振って表示
}
if cards_in_fzone.is_empty() {
println!("No cards in hand.");
return;
}
println!("Select a card by number (1-{}):", cards_in_fzone.len());
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
// Trim whitespace and attempt to parse the input
match input.trim().parse::<usize>() {
Ok(selected_index) => {
if selected_index == 0 {
// 0が選択された場合
withdraw_management_event_writer.send(WithdrawManagement);
println!("Withdraw management initiated.");
break; // ループを抜ける
}
if selected_index > 0 && selected_index <= cards_in_fzone.len() {
let selected_entity = cards_in_fzone[selected_index - 1];
if let Ok*5 = query.get(selected_entity) {
withdraw_event_writer.send(Withdraw {
id: selected_entity,
});
println!("{} を撤退するファイターとして選択しました", card.name); // カード名を表示
}
println!("You selected card with Entity ID: {:?}", selected_entity);
break; // 有効な選択が行われたらループを抜ける
} else {
println!(
"Invalid selection. Please enter a number between 1 and {}.",
cards_in_fzone.len()
);
}
}
Err(_) => {
println!("Please enter a valid number.");
}
}
}
}
}
}
pub fn pick_fighter_to_withdraw_opponent(
query: Query<(Entity, &Card, &Location), With<Player2>>,
mut withdraw_event_writer: EventWriter<Withdraw>,
mut pick_fighter_to_withdraw_event_reader: EventReader<PickFighterToWithdraw>,
mut withdraw_management_event_writer: EventWriter<WithdrawManagement>,
) {
for event in pick_fighter_to_withdraw_event_reader.read() {
let mut cards_in_fzone = Vec::new();
println!("Fゾーンにあるあなたのカードは:");
for (entity, card, location) in query.iter() {
if let Location::FZone = location {
cards_in_fzone.push(entity); // エンティティIDを保存
println!("{}: {}[{}]", cards_in_fzone.len(), card.name, card.energy); // 番号を振って表示
}
if cards_in_fzone.is_empty() {
println!("No cards in hand.");
return;
}
println!("Select a card by number (1-{}):", cards_in_fzone.len());
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
// Trim whitespace and attempt to parse the input
match input.trim().parse::<usize>() {
Ok(selected_index) => {
if selected_index == 0 {
// 0が選択された場合
withdraw_management_event_writer.send(WithdrawManagement);
println!("Withdraw management initiated.");
break; // ループを抜ける
}
if selected_index > 0 && selected_index <= cards_in_fzone.len() {
let selected_entity = cards_in_fzone[selected_index - 1];
if let Ok*6 = query.get(selected_entity) {
withdraw_event_writer.send(Withdraw {
id: selected_entity,
});
println!("{} を撤退するファイターとして選択しました", card.name); // カード名を表示
}
println!("You selected card with Entity ID: {:?}", selected_entity);
break; // 有効な選択が行われたらループを抜ける
} else {
println!(
"Invalid selection. Please enter a number between 1 and {}.",
cards_in_fzone.len()
);
}
}
Err(_) => {
println!("Please enter a valid number.");
}
}
}
}
}
}
このようにした。ただ、fzoneのチェックの{}が大きな範囲をつけすぎた。

直したので、ファイター選択をやり直していく。
攻撃ファイターの選択、攻撃先の選択、ガードの選択この3つで、選択肢の数が不定の入力が必要になる。
その際に、loopして必要な情報がえられるまでやるようにする。
ガードはやり直さない予定なので、そのままイベントを記述した。
pub fn select_attacker(
player1_fzone: ResMut<Player1FZone>,
query: Query<(Entity, &Card, &Fighter, &Location, &SpinCondition), With<Player1>>, // Fighterコンポーネントを追加
mut commands: Commands,
mut attack_event_writer: EventWriter<Attack>,
mut select_attacker_event_reader: EventReader<SelectAttacker>,
mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
) {
for _event in select_attacker_event_reader.read() {
let mut available_fighters = Vec::new();
println!("Fゾーンにある攻撃可能なあなたのファイターは:");
for &entity in &player1_fzone.cards {
if let Ok*7 = query.get(entity) {
if !fighter.summoned_sick {
if let SpinCondition::ReSpin = spincondition {
available_fighters.push(entity);
println!(
"{}: {}[{}]",
available_fighters.len(),
card.name,
fighter.power
); // 召喚酔いでない場合
}
}
}
}
if available_fighters.is_empty() {
println!("召喚酔いしていないファイターがFゾーンにありません。");
main_phase_management_event_writer.send(MainPhaseManagement);
}
println!(
"ファイターを選択してください (1-{} または 0で戻る):",
available_fighters.len()
);
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
if let Ok(selected_index) = input.trim().parse::<usize>() {
if selected_index == 0 {
// 0を選択した場合、管理フェーズに戻る
main_phase_management_event_writer.send(MainPhaseManagement);
break; // ループを抜ける
} else if selected_index > 0 && selected_index <= available_fighters.len() {
let selected_entity = available_fighters[selected_index - 1];
if let Ok*8 = query.get(selected_entity) {
attack_event_writer.send(Attack {
attacker_id: selected_entity,
});
println!("{} を攻撃するファイターとして選択しました", card.name); // カード名を表示
commands.entity(selected_entity).insert(SpinCondition::Spin);
}
break; // 有効な選択が行われたらループを抜ける
} else {
println!("無効な選択です。もう一度入力してください。");
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
pub fn choose_card_being_attacked(
player2_szone: ResMut<Player2SZone>,
player2_fzone: ResMut<Player2FZone>,
query: Query<(Entity, &Card, Option<&Fighter>, &SpinCondition), With<Player2>>, // Fighterコンポーネントを追加
mut commands: Commands,
mut being_attacked_event_writer: EventWriter<BeingAttacked>,
mut attack_event_reader: EventReader<Attack>,
mut choose_guard_event_writer: EventWriter<ChooseGuard>,
mut select_attacker_event_writer: EventWriter<SelectAttacker>,
) {
for event in attack_event_reader.read() {
let mut available_cards = Vec::new();
// Sゾーンのカードをリストアップ
for &entity in &player2_szone.cards {
if let Ok*9 = query.get(entity) {
available_cards.push(entity);
if let Some(fighter) = fighter_option {
println!(
"{}: {} (Sゾーン)[パワー: {}]",
available_cards.len(),
card.name,
fighter.power
);
} else {
println!("{}: {} (Sゾーン)", available_cards.len(), card.name);
}
}
}
// Fゾーンのスピン中のカードをリストアップ
for &entity in &player2_fzone.cards {
if let Ok*10 = query.get(entity) {
if let SpinCondition::Spin = spincondition {
available_cards.push(entity);
// スピンしている場合
if let Some(fighter) = fighter {
println!(
"{}: {} (Fゾーン)[パワー: {}]",
available_cards.len(),
card.name,
fighter.power
);
} else {
println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
}
}
}
}
if available_cards.is_empty() {
println!("攻撃対象となるカードがありません。");
return;
}
println!("攻撃対象を選択してください (1-{}):", available_cards.len());
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
if let Ok(selected_index) = input.trim().parse::<usize>() {
if selected_index == 0 {
// 0が選択された場合、操作をキャンセル
println!("攻撃をキャンセルしました。攻撃ファイターをリスピンしました。");
commands.entity(event.attacker_id).insert(SpinCondition::ReSpin);
select_attacker_event_writer.send(SelectAttacker);
return; // メソッドを終了
} else if selected_index > 0 && selected_index <= available_cards.len() {
let selected_entity = available_cards[selected_index - 1];
if let Ok*11 = query.get(selected_entity) {
choose_guard_event_writer.send(ChooseGuard {
attacked_card_id: selected_entity,
attacker_id: event.attacker_id,
});
println!("{} を攻撃対象として選択しました", card.name); // カード名を表示
}
break; // 有効な選択が行われたらループを抜ける
} else {
println!("無効な選択です。もう一度入力してください。");
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
pub fn choose_guard(
query: Query<(Entity, &Card, &SpinCondition, &Fighter), (With<Player2>, With<Guard>)>,
player2_fzone: ResMut<Player2FZone>,
mut choose_guard_eventreader: EventReader<ChooseGuard>,
mut attack_fzone_event_writer: EventWriter<AttackFZone>,
mut being_attacked_event_writer: EventWriter<BeingAttacked>,
mut commands: Commands,
) {
for event in choose_guard_eventreader.read() {
let mut has_respin = false;
// player2_fzone に含まれるエンティティをループ
let mut available_guards = Vec::new();
for &entity in &player2_fzone.cards {
if let Ok*12 = query.get(entity) {
if let SpinCondition::ReSpin = spincondition {
available_guards.push(entity);
println!(
"{}: {}[{}]",
available_guards.len(),
card.name,
fighter.power
); // 召喚酔いでない場合
}
}
}
if available_guards.is_empty() {
println!("ガードはありません");
being_attacked_event_writer.send(BeingAttacked {
attacker_id: event.attacker_id,
attacked_card_id: event.attacked_card_id,
});
} else {
println!(
"ガードファイターを選んでいます。 (1-{})[0]でガードをやめる",
available_guards.len()
);
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
if let Ok(selected_index) = input.trim().parse::<usize>() {
if selected_index == 0 {
// 攻撃をやめる場合
println!("ガードされませんでした");
being_attacked_event_writer.send(BeingAttacked {
attacked_card_id: event.attacked_card_id,
attacker_id: event.attacker_id,
});
}
if selected_index > 0 && selected_index <= available_guards.len() {
let selected_entity = available_guards[selected_index - 1];
if let Ok*13 = query.get(selected_entity) {
attack_fzone_event_writer.send(AttackFZone {
attacked_card_id: selected_entity,
attacker_id: event.attacker_id,
});
println!("{} にガードされました", card.name); // カード名を表示
commands.entity(selected_entity).insert(SpinCondition::Spin);
println!("{}はスピンしました", card.name);
}
} else {
println!("ガードされませんでした");
being_attacked_event_writer.send(BeingAttacked {
attacked_card_id: event.attacked_card_id,
attacker_id: event.attacker_id,
});
}
} else {
println!("有効な番号を入力してください。");
}
}
}
}
これよく考えたら、攻撃対象選んでからスピンでよかったと思う。

OKそうあとで、run_ifつけないと、ゲームオーバーしても、処理が続行されちゃうのがあるね。
忘れる前にじゃんけん
fn get_user_input() -> String {
let mut input = String::new();
print!("> ");
io::stdout().flush().unwrap(); // 出力をフラッシュしてプロンプトを表示
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
input.trim().to_string()
}
fn determine_winner(player1_choice: &str, player2_choice: &str) -> u32 {
let player1_hand = match player1_choice {
"1" => "グー",
"2" => "チョキ",
"3" => "パー",
_ => {
println!("無効な選択です。Player 1の選択を無効とします。");
return 0; // 無効な場合はゼロを返す
}
};
let player2_hand = match player2_choice {
"1" => "グー",
"2" => "チョキ",
"3" => "パー",
_ => {
println!("無効な選択です。Player 2の選択を無効とします。");
return 0; // 無効な場合はゼロを返す
}
};
let outcomes: HashMap<&str, &str> = [("グー", "チョキ"), ("チョキ", "パー"), ("パー", "グー")]
.cloned()
.collect();
if player1_hand == player2_hand {
println!("あいこです。もう一度選んでください。");
// あいこの場合、再度入力を受け付ける
let new_player1_choice = get_user_input();
let new_player2_choice = get_user_input();
return determine_winner(&new_player1_choice, &new_player2_choice); // 再帰的に呼び出し
} else if outcomes.get(player1_hand).unwrap() == &player2_hand {
println!("Player 1の勝ちです!");
return 1; // Player 1 の勝ち
} else {
println!("Player 2の勝ちです!");
return 2; // Player 2 の勝ち
}
}
fn decide_turn(winner: u32) -> (u32, u32) {
let winner_choice = if winner == 1 {
println!("Player 1: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
get_user_input()
} else {
println!("Player 2: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
get_user_input()
};
match winner_choice.as_str() {
"1" => {
println!("勝者は先行を選びました。");
(winner, 3 - winner) // 1が勝者ならturn_playerはwinner、non_turn_playerは対戦相手
}
"2" => {
println!("勝者は後攻を選びました。");
(3 - winner, winner) // 2が勝者ならnon_turn_playerはwinner
}
_ => {
println!("無効な選択肢です。");
(0, 0) // 無効な場合はゼロを返す
}
}
}
fn janken() -> (u32, u32) {
println!(
"じゃんけんをします。Player 1: 1: グー、2: チョキ、3: パー のいずれかを選択してください。"
);
let player1_choice = get_user_input();
println!("Player 2: 1: グー、2: チョキ、3: パー のいずれかを選択してください。");
let player2_choice = get_user_input();
let winner = determine_winner(&player1_choice, &player2_choice);
// ターンプレイヤーと非ターンプレイヤーを決定
let (turn_player, non_turn_player) = decide_turn(winner);
(turn_player, non_turn_player) // ターンプレイヤーと非ターンプレイヤーを返す
}
これも、123以外を入力するとやり直すようにする。
fn get_user_input(prompt: &str) -> String {
let mut input = String::new();
loop {
print!("{}", prompt);
io::stdout().flush().unwrap(); // 出力をフラッシュしてプロンプトを表示
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
let trimmed_input = input.trim().to_string();
// 入力が1, 2, 3のいずれかであることを確認
if trimmed_input == "1" || trimmed_input == "2" || trimmed_input == "3" {
return trimmed_input; // 有効な入力を返す
} else {
println!("無効な選択です。1, 2, または 3 を選んでください。");
input.clear(); // 入力をクリアして再度プロンプトを表示
}
}
}
fn determine_winner(player1_choice: &str, player2_choice: &str) -> u32 {
let player1_hand = match player1_choice {
"1" => "グー",
"2" => "チョキ",
"3" => "パー",
_ => {
println!("無効な選択です。Player 1の選択を無効とします。");
return 0; // 無効な場合はゼロを返す
}
};
let player2_hand = match player2_choice {
"1" => "グー",
"2" => "チョキ",
"3" => "パー",
_ => {
println!("無効な選択です。Player 2の選択を無効とします。");
return 0; // 無効な場合はゼロを返す
}
};
let outcomes: HashMap<&str, &str> = [("グー", "チョキ"), ("チョキ", "パー"), ("パー", "グー")]
.cloned()
.collect();
if player1_hand == player2_hand {
println!("あいこです。もう一度選んでください。");
// あいこの場合、再度入力を受け付ける
let new_player1_choice = get_user_input("Player 1の選択> ");
let new_player2_choice = get_user_input("Player 2の選択> ");
return determine_winner(&new_player1_choice, &new_player2_choice); // 再帰的に呼び出し
} else if outcomes.get(player1_hand).unwrap() == &player2_hand {
println!("Player 1の勝ちです!");
return 1; // Player 1 の勝ち
} else {
println!("Player 2の勝ちです!");
return 2; // Player 2 の勝ち
}
}
fn decide_turn(winner: u32) -> (u32, u32) {
let winner_choice = if winner == 1 {
println!("Player 1: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
get_user_input("")
} else {
println!("Player 2: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
get_user_input("")
};
match winner_choice.as_str() {
"1" => {
println!("勝者は先行を選びました。");
(winner, 3 - winner) // 1が勝者ならturn_playerはwinner、non_turn_playerは対戦相手
}
"2" => {
println!("勝者は後攻を選びました。");
(3 - winner, winner) // 2が勝者ならnon_turn_playerはwinner
}
_ => {
println!("無効な選択肢です。");
(0, 0) // 無効な場合はゼロを返す
}
}
}
fn janken() -> (u32, u32) {
println!(
"じゃんけんをします。Player 1: 1: グー、2: チョキ、3: パー のいずれかを選択してください。"
);
let player1_choice = get_user_input("Player 1の選択> ");
println!("Player 2: 1: グー、2: チョキ、3: パー のいずれかを選択してください。");
let player2_choice = get_user_input("Player 2の選択> ");
let winner = determine_winner(&player1_choice, &player2_choice);
// ターンプレイヤーと非ターンプレイヤーを決定
let (turn_player, non_turn_player) = decide_turn(winner);
(turn_player, non_turn_player) // ターンプレイヤーと非ターンプレイヤーを返す
}
こういう風に直した。

そしたら、こんなエラーが出た。
先行後攻は、入力すべき数字が違うから分けないとだめだわ。
fn get_turn_choice(prompt: &str) -> String {
let mut input = String::new();
loop {
print!("{}", prompt);
io::stdout().flush().unwrap(); // 出力をフラッシュしてプロンプトを表示
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
let trimmed_input = input.trim().to_string();
// 入力が1または2であることを確認
if trimmed_input == "1" || trimmed_input == "2" {
return trimmed_input; // 有効な入力を返す
} else {
println!("無効な選択です。1または2を選んでください。");
input.clear(); // 入力をクリアして再度プロンプトを表示
}
}
}
同様だけど、1と2だけ受け付ける入力関数を作った。
OKだね。
いくらルールブックを読んでも上手くかけない参考文献は、もうChaatGPTに書いていただきました。
chatgpt.com