Skip to content

Instantly share code, notes, and snippets.

@astynax
Created September 15, 2025 06:35
Show Gist options
  • Select an option

  • Save astynax/b4772d5a0da9aeb4f8cf21984f1c9839 to your computer and use it in GitHub Desktop.

Select an option

Save astynax/b4772d5a0da9aeb4f8cf21984f1c9839 to your computer and use it in GitHub Desktop.
TitTacToe in Rust that I like :)
#[derive(Clone)]
struct Triple<T> where T: Clone {
v1: T,
v2: T,
v3: T,
}
#[derive(Copy, Clone)]
enum Coord { C1, C2, C3 }
use Coord::{*};
impl <T> Triple<T> where T: Clone {
fn over<F>(self, pos: Coord, op: F) -> Self where F: FnOnce(T) -> T {
match pos {
C1 => Triple { v1: op(self.v1), v2: self.v2, v3: self.v3 },
C2 => Triple { v1: self.v1, v2: op(self.v2), v3: self.v3 },
C3 => Triple { v1: self.v1, v2: self.v2, v3: op(self.v3) },
}
}
fn at(&self, pos: Coord) -> T {
match pos {
C1 => self.v1.clone(),
C2 => self.v2.clone(),
C3 => self.v3.clone(),
}
}
fn of(v: T) -> Self {
Triple { v1: v.clone(), v2: v.clone(), v3: v.clone() }
}
}
#[derive(Clone)]
enum XO { X, O }
use XO::{*};
#[derive(Clone)]
struct Field {
rows: Triple<Triple<Option<XO>>>
}
impl Field {
fn put(&self, x: Coord, y: Coord, piece: XO) -> Option<Self> {
if self.at(x, y).is_some() {
Option::None
} else {
Option::Some(Field {
rows: self.rows.clone()
.over(y, |row| {
row.over(x, |_| Option::Some(piece) )
})
})
}
}
fn at(&self, x: Coord, y: Coord) -> Option<XO> {
self.rows.at(y).at(x)
}
fn draw(&self) {
for y in [C1, C2, C3] {
for x in [C1, C2, C3] {
print!("{}", match self.at(x, y) {
None => "[ ]",
Some(X) => "[X]",
Some(O) => "[O]",
})
};
println!();
}
}
fn empty() -> Self {
Field { rows: Triple::of(Triple::of(None))}
}
}
fn main() {
Field::empty()
.put(C1, C1, X).unwrap()
.put(C2, C2, O).unwrap()
.put(C1, C3, X).unwrap()
.draw();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment