pub struct GameEngine {
pub current_player: Player,
pub ai_enabled: bool,
/* private fields */
}Expand description
The core Tic-Tac-Toe game engine.
This struct manages the board, enforces rules, and provides an unbeatable AI opponent using the Minimax algorithm if enabled.
§Board Representation
The board is stored internally as a flat array of 9 cells.
Indices map to positions like this:
0 | 1 | 2
-----------
3 | 4 | 5
-----------
6 | 7 | 8§Game Modes
- Human vs Human: Both players call [
make_move] manually. - Human vs AI: calls [
make_move], then queries [get_best_move] to find the AI’s move and applies it with [make_move].
§Examples
§Human vs Human
use xo_core::{GameEngine, Player};
let mut game = GameEngine::with_ai(false);
game.make_move(0).unwrap(); // X plays top-left
game.make_move(4).unwrap(); // O plays center
assert_eq!(game.current_player, Player::X);§Human vs AI
use xo_core::GameEngine;
let mut game = GameEngine::with_ai(true);
game.make_move(0).unwrap(); // Human plays top-left
if let Some(ai_move) = game.get_best_move() {
game.make_move(ai_move).unwrap(); // Apply AI move
}Fields§
§current_player: PlayerThe player whose turn it is.
ai_enabled: boolWhether the AI is enabled.
true: Single-player vs AIfalse: Human vs Human
Implementations§
Source§impl GameEngine
impl GameEngine
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new instance of the game engine with an empty board.
The game always starts with Player::X.
By default, AI is enabled.
§Example
use xo_core::{GameEngine, Player, Cell};
let game = GameEngine::new();
assert_eq!(game.current_player, Player::X);
assert!(game.get_board().iter().all(|&c| c == Cell::Empty));
assert!(game.ai_enabled);Sourcepub fn make_move(&mut self, index: usize) -> Result<(), MoveError>
pub fn make_move(&mut self, index: usize) -> Result<(), MoveError>
Attempts to make a move for the current player at the given board index.
§Parameters
index: The 0-based cell index (0–8).
§Returns
Ok(())if the move was made successfully.Err(MoveError)if the move is invalid:MoveError::OutOfBoundsifindex >= 9MoveError::CellOccupiedif the cell already has a mark
§Example
use xo_core::{GameEngine, MoveError};
let mut game = GameEngine::new();
assert!(game.make_move(0).is_ok());
assert_eq!(game.make_move(0), Err(MoveError::CellOccupied));Sourcepub fn check_state(&self) -> GameState
pub fn check_state(&self) -> GameState
Returns the current state of the game.
Possible values:
GameState::InProgressGameState::TieGameState::Won(Player::X)GameState::Won(Player::O)
Sourcepub fn get_best_move(&self) -> Option<usize>
pub fn get_best_move(&self) -> Option<usize>
Calculates the best move for the current player using Minimax with pruning.
Returns:
Some(index)for the best move when AI is enabled.Noneif the game is over or AI is disabled.
§Example
use xo_core::GameEngine;
let game = GameEngine::with_ai(false);
assert_eq!(game.get_best_move(), None); // AI disabled§Example with AI
use xo_core::GameEngine;
let mut game = GameEngine::new();
game.make_move(0).unwrap(); // X
game.make_move(4).unwrap(); // O
game.make_move(1).unwrap(); // X
// O should block X's winning move at index 2
assert_eq!(game.get_best_move(), Some(2));Auto Trait Implementations§
impl Freeze for GameEngine
impl RefUnwindSafe for GameEngine
impl Send for GameEngine
impl Sync for GameEngine
impl Unpin for GameEngine
impl UnsafeUnpin for GameEngine
impl UnwindSafe for GameEngine
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more