use crate::gameboard::{GameBoard, BoardSpace, BoardSpaceLocation};
mod win_position_constants;
#[derive(Debug, PartialEq, Eq)]
pub enum GameOutcome{
PlayerX(WinPosition),
PlayerO(WinPosition),
Draw,
Incomplete
}
impl GameOutcome {
pub fn analyze_game(board: &GameBoard) -> GameOutcome
{
for win_position in WinPosition::all(){
let mut board_space_values =
win_position.as_board_spaces().iter().map(|board_space|{
board.space(*board_space)
});
let possible_winner = board_space_values.next().unwrap();
let is_winner = board_space_values.all(|board_space|{
board_space == possible_winner});
if is_winner{
match possible_winner {
BoardSpace::Empty => {},
BoardSpace::X => {return GameOutcome::PlayerX(win_position);},
BoardSpace::O => {return GameOutcome::PlayerO(win_position);}
}
}
}
for (_, space) in board.all_spaces() {
if space == &BoardSpace::Empty {
return GameOutcome::Incomplete;
}
}
GameOutcome::Draw
}
pub fn game_finished(&self) -> bool
{
!matches!(self, Self::Incomplete)
}
pub fn game_won(&self) -> bool
{
!matches!(self, Self::Draw | Self::Incomplete)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum WinPosition {
TopRow,
MiddleRow,
BottomRow,
LeftColumn,
MiddleColumn,
RightColumn,
TopLeftToBottomRight,
BottomLeftToTopRight
}
impl WinPosition{
pub const fn as_board_spaces(&self) -> &'static [BoardSpaceLocation; 3]
{
match self {
Self::TopRow => &win_position_constants::TOP_ROW,
Self::MiddleRow => &win_position_constants::MIDDLE_ROW,
Self::BottomRow => &win_position_constants::BOTTOM_ROW,
Self::LeftColumn => &win_position_constants::LEFT_COLUMN,
Self::MiddleColumn => &win_position_constants::MIDDLE_COLUMN,
Self::RightColumn => &win_position_constants::RIGHT_COLUMN,
Self::TopLeftToBottomRight => &win_position_constants::TOP_LEFT_TO_BOTTOM_RIGHT,
Self::BottomLeftToTopRight => &win_position_constants::BOTTOM_LEFT_TO_TOP_RIGHT
}
}
pub fn all() -> impl Iterator<Item = Self>
{
const VARIANTS: [WinPosition; 8] = [
WinPosition::TopRow,
WinPosition::MiddleRow,
WinPosition::BottomRow,
WinPosition::LeftColumn,
WinPosition::MiddleColumn,
WinPosition::RightColumn,
WinPosition::TopLeftToBottomRight,
WinPosition::BottomLeftToTopRight
];
VARIANTS.into_iter()
}
}