我和我的家人一起玩 Mancala 玩得很開心,我真的很喜歡它的簡單規則,但有幾個問題,比如“最高分是多少”。我認為在 Rust 中實作這將是一個有趣的小專案,但我被困住了,需要幫助。
如何玩曼卡拉有很多規則。我想實作這個版本:https://www.youtube.com/watch?v=-A-djjimCcM。了解游戲規則可以讓我更容易理解我的問題,但可能并不需要得到它。
這是 Mancala 板的樣子:
| |04|04|04|04|04|04| |
|00|-----------------|00|
| |04|04|04|04|04|04| |
每個數字代表一個洞。較大方框中左右兩側的數字代表“曼卡拉”。曼卡拉基本上是一個你計算分數的洞。你右邊的那個是你自己的mancala,左邊那個是你對手的mancala。這些數字代表該特定孔中的彈珠數量。
在游戲中,您可以選擇一個洞,拿走所有的彈珠,然后在每個下一個洞/曼卡拉中放一顆彈珠,直到彈珠用完。你跳過對手的曼卡拉。這就是我正在努力解決的問題。
這就是我試圖解決它的方法:Mancala 板是一個結構,它有四個存盤孔的陣列。一個用于球員側面的每個洞,一個用于他們的曼卡拉。我想將這些孔中的三個陣列鏈接在一??起并回圈,這樣我就可以在這些孔上運行相關函式(跳過對手的曼卡拉)。這是我的代碼:
pub const STARTING_MARBLES: i8 = 4;
pub const NO_OF_HOLES_OF_EACH_PLAYER: usize = 6;
// There can be two players
#[derive(Debug, Copy, Clone)]
pub enum Player {
A,
B,
}
// A dip in a mancala board that can contain a number of marbles
#[derive(Debug, Copy, Clone)]
struct Hole {
marbles: i8,
}
impl Hole {
// Adds x marbles to the hole
fn add_x(&mut self, x: i8) {
self.marbles = x;
}
// Takes all marbles from the hole and returns their number
fn take_all(&mut self) -> i8 {
let marbles = self.marbles;
self.marbles = 0;
marbles
}
// Returns the number of marbles in the hole
fn count(&self) -> i8 {
self.marbles
}
}
// A mancala board with all its holes and mancalas to count the players points
#[derive(Debug, Copy, Clone)]
pub struct Board {
holes_a: [Hole; NO_OF_HOLES_OF_EACH_PLAYER],
holes_b: [Hole; NO_OF_HOLES_OF_EACH_PLAYER],
mancala_a: [Hole; 1],
mancala_b: [Hole; 1],
}
impl Board {
// Create, initialize and return a new mancala board
pub fn new() -> Self {
let init_hole = Hole {
marbles: STARTING_MARBLES,
};
let holes_a = [init_hole; NO_OF_HOLES_OF_EACH_PLAYER];
let holes_b = [init_hole; NO_OF_HOLES_OF_EACH_PLAYER];
let mancala_a = [Hole { marbles: 0 }];
let mancala_b = [Hole { marbles: 0 }];
Board {
holes_a,
holes_b,
mancala_a,
mancala_b,
}
}
// Take all marbles from the chosen hole and add them to the following holes and the player's mancala
// player: Player whos turn it is
// no: number of the selected hole. The numbering starts with 0 on the very left hole of the player whos turn it is
pub fn choose_hole(mut self, player: Player, no: usize) {
let (mut players_own_holes, other_players_holes, players_mancala) = match player {
Player::A => (self.holes_a, self.holes_b, self.mancala_a),
Player::B => (self.holes_b, self.holes_a, self.mancala_b),
};
let marbles_to_spend = players_own_holes[no].take_all() as usize;
let holes_iter = self
.holes_a
.iter_mut()
.chain(self.mancala_a.iter_mut())
.chain(self.holes_b.iter_mut())
.cycle()
.skip(no 1)
.take(marbles_to_spend);
for mut hole in holes_iter {
hole.add_x(1);
}
}
}
但是我收到以下錯誤:
error[E0277]: the trait bound `std::slice::IterMut<'_, Hole>: Clone` is not satisfied
--> src/lib.rs:75:14
|
75 | .cycle()
| ^^^^^ the trait `Clone` is not implemented for `std::slice::IterMut<'_, Hole>`
|
= note: required because of the requirements on the impl of `Clone` for `std::iter::Chain<std::iter::Chain<std::slice::IterMut<'_, Hole>, std::slice::IterMut<'_, Hole>>, std::slice::IterMut<'_, Hole>>`
note: required by a bound in `cycle`
--> /home/batman/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:3262:23
|
3262 | Self: Sized Clone,
| ^^^^^ required by this bound in `cycle`
我也嘗試使用該into_iter()方法。那時我沒有收到任何錯誤,但孔的值沒有改變。我猜想創建了一個副本,并且該方法在副本上運行,然后副本超出了范圍,看起來沒有任何改變。
uj5u.com熱心網友回復:
cycle()迭代器方法通過克隆輸入迭代器在內部作業,迭代克隆直到它回傳,None然后將克隆替換為輸入迭代器的另一個克隆。這要求可以克隆輸入迭代器,但不能克隆對切片元素的可變參考的迭代器,因為這樣您就可以呼叫next()原始迭代器和克隆并擁有兩個對相同值的可變參考。這在 Rust 中應該是不可能的,因此IterMut無法克隆。
解決這個問題的一種方法是改變你的資料結構。一個元素的陣列通常表示設計問題;無論如何,你可以只用一個值來完成同樣的事情。
為了使這個問題更簡單,只需使用帶有回圈索引的單個陣列。像這樣的東西:
| |12|11|10|09|08|07| |
|13|-----------------|06|
| |00|01|02|03|04|05| |
所以現在你的資料結構很簡單struct Board { holes: [Hole; 14] }。
遍歷這個資料結構現在變得非常簡單——你只需要做(0..14).cycle()一個重復的陣列索引迭代器。
請注意,這還可以讓您處理當前缺少的有關對手曼卡拉的邏輯。如果您在比賽期間到達對手的曼卡拉,您應該跳過它,但您的代碼不會跳過它。match我們可以使用簡單的 ,skip和來處理這個問題,以及從電路板的哪一側開始filter:
let (opponent_mancala_index, start_idx) = match player {
Player::A => (13, 0),
Player::B => (6, 7),
};
let indexes = (0..14)
.cycle()
.skip(no start_idx)
.filter(|&v| v != opponent_mancala_index)
.take(marbles_to_spend);
for i in indexes {
self.holes[i].add_x(1);
}
您可以考慮將這些特殊索引命名為常量。
另外,請注意您的Board::choose_hole()函式應該&mut self代替mut self,否則您正在對副本進行更改,然后丟棄該副本。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/490746.html
上一篇:使TLD陣列在gtld下
