| Crates.io | xo-core |
| lib.rs | xo-core |
| version | 0.2.0-alpha |
| created_at | 2025-08-08 04:29:44.95347+00 |
| updated_at | 2025-08-15 10:09:21.010774+00 |
| description | A fast, reusable, and well-documented game engine for Tic-Tac-Toe (Noughts and Crosses) in Rust |
| homepage | |
| repository | https://github.com/Allie72-Aur/xo-core |
| max_upload_size | |
| id | 1786199 |
| size | 32,003 |
A fast, reusable, and well-documented game engine for Tic-Tac-Toe (Noughts and Crosses) in Rust, featuring a robust Minimax AI. This library is designed to be embedded in CLI, GUI, and web applications, or used as an educational resource for turn-based game development and AI.
Cargo.toml:[dependencies]
xo-core = "0.1"
(Replace the version with the latest on crates.io)
cargo add xo-core
use xo_core::{GameEngine, Player, Cell, GameState};
fn main() {
let mut game = GameEngine::new();
// Play moves: X at 0, O at 4, X at 1, O at 5, X at 2 (X wins)
let moves = [0, 4, 1, 5, 2];
for m in moves {
game.make_move(m).unwrap();
}
match game.check_state() {
GameState::Win(Player::X) => println!("X wins!"),
GameState::Win(Player::O) => println!("O wins!"),
GameState::Tie => println!("It's a tie!"),
GameState::InProgress => println!("Game is still in progress."),
}
}
use xo_core::{GameEngine, Player, Cell};
fn main() {
let mut game = GameEngine::new();
// Human is X, AI is O
loop {
// Human move (for example, always picking the first empty)
let board = game.get_board();
let my_move = board.iter().position(|&c| c == Cell::Empty).unwrap();
game.make_move(my_move).unwrap();
// Check for game over
if game.is_over() {
break;
}
// AI move
let ai_move = game.get_best_move().unwrap();
game.make_move(ai_move).unwrap();
// Check for game over
if game.is_over() {
break;
}
}
println!("Final board: {:?}", game.get_board());
}
GameEngine: The main engine struct. Manages board state, moves, and AI.Player: Enum for X and O.Cell: Enum for X, O, or Empty cell.GameState: Enum for Win(Player), Tie, or InProgress.MoveError: Enum for move errors (OutOfBounds, CellOccupied).GameEngine::new(): Create a new game.make_move(index): Attempt a move at given cell (0-8).get_board(): Get the current board state as [Cell; 9].check_state(): Check if the game is over, won, tied, or still in progress.is_over(): Boolean, true if game finished.get_best_move(): Returns the best move for the current player (Minimax AI).Cells are indexed left-to-right, top-to-bottom:
0 | 1 | 2
---|---|---
3 | 4 | 5
---|---|---
6 | 7 | 8
Result<(), MoveError>.MoveError::OutOfBounds — index not in 0..=8MoveError::CellOccupied — cell already filledYou can easily use xo-core with web frameworks (e.g., Yew), desktop GUI (e.g., egui, gtk-rs), or in server-side logic.
The engine is detached from any I/O or UI, making it flexible for integration.
MIT
Contributions, bug reports, and feature requests welcome!
Please open an issue or submit a pull request on GitHub.
While working on this, I stumbled across a couple of cool projects. Check them out while you're at it: