4 #[derive(Copy, Clone, PartialEq)]
11 #[derive(Copy, Clone)]
32 impl fmt::Display for Sign {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 write!(f, "{}", match *self {
42 impl fmt::Display for Game {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 for i in 0..self.grid.len() {
45 for j in 0..self.grid[i].len() {
46 if let Err(e) = write!(f, "{}", self.grid[i][j]) {
50 if i < (self.grid.len() - 1) {
51 if let Err(e) = write!(f, "\\n") {
60 impl fmt::Display for Content {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 &Content::Node(ref n) => write!(f, "[label=\"{}\"]", n.game),
64 &Content::Leaf(s) => write!(f, "[label=\"{}\"]", s),
69 impl fmt::Display for Tree {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71 if let Err(e) = write!(f, " {}{};\n",
72 self.id, self.content) {
76 Content::Node(ref n) => {
78 if let Err(e) = write!(f, "{} {} -> {};\n", t, self.id, t.id) {
83 Content::Leaf(_) => {},
92 grid: [[Sign::None; 3]; 3],
97 fn get_free_compartments(&self) -> Vec<(usize, usize)> {
98 (0..self.grid.len()).flat_map(|x|
99 (0..self.grid[0].len()).filter_map(|y|
100 if self.grid[x][y] == Sign::None {
105 ).collect::<Vec<_>>()
110 fn is_full(&self) -> bool {
111 self.get_free_compartments().len() == 0
114 fn play(&self, (x, y): (usize, usize)) -> Game {
117 let mut grid = self.grid.clone();
118 grid[x][y] = self.next;
121 next: match self.next {
122 Sign::None => Sign::None,
123 Sign::Cross => Sign::Circle,
124 Sign::Circle => Sign::Cross,
129 fn is_over(&self) -> Option<Sign> {
130 for &s in &[Sign::Cross, Sign::Circle] {
131 for i in 0..self.grid.len() {
133 for j in 0..self.grid[i].len() {
134 if self.grid[i][j] != s {
143 for i in 0..self.grid[0].len() {
145 for j in 0..self.grid.len() {
146 if self.grid[j][i] != s {
156 let mut diag0 = true;
157 let mut diag1 = true;
158 for i in 0..self.grid.len() {
159 if self.grid[i][i] != s {
162 if self.grid[(self.grid.len() - 1) - i][i] != s {
172 return Some(Sign::None);
179 fn new(g: Game, id: &mut usize, max_id: usize, depth: usize, max_depth: usize) -> Tree {
182 content: Content::Node(Node {
184 rest: if let Some(s) = g.is_over() {
188 content: Content::Leaf(s),
190 } else if depth < max_depth {
191 g.get_free_compartments().iter().filter_map(|&c| {
194 Some(Tree::new(g.play(c), id, max_id, depth + 1, max_depth))
208 let default_max_id = std::usize::MAX;
209 let default_max_depth = std::usize::MAX;
211 let args: Vec<String> = env::args().collect();
213 let max_id = if args.len() >= 2 {
214 match args[1].parse() {
216 Err(_) => default_max_id,
222 let max_depth = if args.len() == 3 {
223 match args[2].parse() {
225 Err(_) => default_max_depth,
232 println!("{}: error: too many arguments", args[0]);
234 println!("digraph G {{");
235 println!(" graph[fontname=\"Courier New\"];");
236 println!(" node[fontname=\"Courier New\"];");
237 println!(" edge[fontname=\"Courier New\"];");
238 print!("{}", Tree::new(Game::new(), &mut 0, max_id, 0, max_depth));