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))
206 fn only_winning(self, sign: Sign) -> Option<Tree> {
208 Content::Node(Node { game: g, rest: r }) => {
209 let mut rest = Vec::new();/*r.iter().filter_map(|t|
211 ).collect::<Vec<Tree>>();*/
213 if let Some(wt) = t.only_winning(sign) {
220 content: Content::Node(Node {
229 Content::Leaf(s) => if s == sign {
239 let default_max_id = std::usize::MAX;
240 let default_max_depth = std::usize::MAX;
242 let args: Vec<String> = env::args().collect();
244 let max_id = if args.len() >= 2 {
245 match args[1].parse() {
247 Err(_) => default_max_id,
253 let max_depth = if args.len() >= 3 {
254 match args[2].parse() {
256 Err(_) => default_max_depth,
262 let ws = if args.len() == 4 {
263 match args[3].as_ref() {
264 "X" => Some(Sign::Cross),
265 "x" => Some(Sign::Cross),
266 "O" => Some(Sign::Circle),
267 "o" => Some(Sign::Circle),
268 "_" => Some(Sign::None),
276 println!("{}: error: too many arguments", args[0]);
278 let t = Tree::new(Game::new(), &mut 0, max_id, 0, max_depth);
280 Some(s) => t.only_winning(s),
285 println!("digraph G {{");
286 println!(" graph[fontname=\"Courier New\"];");
287 println!(" node[fontname=\"Courier New\"];");
288 println!(" edge[fontname=\"Courier New\"];");
292 None => println!("no result"),