我有一块黑板,我可以用glam::IVec2
分来索引.
struct Board{pieces: [char;64]}
type PieceOption = Option<char>;
这块板的指数方法是
impl Index<IVec2> for Board {
type Output = PieceOption;
fn index(&self, v : IVec2) -> &Self::Output{
if (v.abs() != v) || (v.max_element() > 8) {&None}
else {
let i : usize = (v.x + 8* v.y).try_into().unwrap();
&Some(self.pieces[i])
}
}
}
除了这个,PieceOption还有方法is_empty
,is_ally
和is_rival
,所以我的问题是:这个递归函数的值应该是什么,为了实现类型一致性,我需要该函数返回一个向量,但我不想在下一块是相同 colored颜色 (Is_Ally)的情况下返回该向量.除此之外,我想知道是否有一种方法可以解包Some
个值,这样我就不需要为Match语句中的每个分支键入一些(‘char’),特别是因为我已经过滤了下一步超出界限的情况.这是类型不一致的当前函数.这是目前为主教们实现的功能,我的目的是为每种运动类型提供此功能.
const DIAGONALS : [IVec2; 4] = [
ivec2(-1, -1), ivec2(-1, 1),
ivec2(-1, 1), ivec2(1, 1)
];
下面是该函数的当前状态
impl Board {
fn moves(&self, piece:&PieceOption, pos:IVec2, dir: Vec<IVec2>)->Vec<IVec2>{
dir.into_iter()
.map(|d| d+pos)
.filter(|p| (p.abs() == *p) && p.max_element() < 8)
.flat_map(|p|
match piece{
Some('B')|Some('b')=>{
if self[p].is_empty() {self.moves(piece, p, vec![p-pos]).push(p)}
else if self[p].is_rival(*piece) {p}
else {()} /* here is where i do not wish to return a vector because
this is likely a case where the next piece is an opponent*/
},
_ => () /* here is where i do not wish to return a vector because
the piece is likely empty space*/
}
)
.collect()
}
}
最新情况:
UPDATE我已经意识到我需要if let
来解开片段的选项,但是我真的不知道If let语句的返回值应该是什么,我当前函数的代码是
impl Board {
fn moves(&self, piece:&PieceOption, pos:IVec2, dir: Vec<IVec2>)->Option<Vec<IVec2>>{
dir.into_iter()
.map(|d| d+pos)
.filter(|p| (p.abs() == *p) && p.max_element() < 8)
.flat_map(|p|
if let Some(c) = piece{
match c{
'B'|'b'=>{
if self[p].is_empty() {self.moves(piece, p, vec![p-pos])?.push(p)}
else if self[p].is_rival(*piece) {Some(vec![p])}
else {None?}
},
_ => None
}
} else {None}
)
.collect()
}
}
此外,我非常感谢任何关于格式的建议,我想知道人们对这个潜在的解决方案的看法,如果这个问题措辞混乱,我会道歉吗? 完整代码可在以下位置找到: https://github.com/LyndonAlcock/chess_test个