Advertisement
Guest User

Untitled

a guest
May 20th, 2015
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.48 KB | None | 0 0
  1. #![feature(core, rand)]
  2. extern crate core;
  3. use std::io::{self,Write};
  4. use std::rand;
  5. use std::rand::distributions::{IndependentSample, Range};
  6.  
  7. #[derive(PartialEq, Clone, Copy)]
  8. enum Field {
  9.     N,
  10.     X,
  11.     O,
  12. }
  13.  
  14. use Field::{N,X,O};
  15.  
  16. impl core::fmt::Display for Field {
  17.     fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
  18.         write!(f, "{}", match *self {
  19.             N => ' ',
  20.             X => 'x',
  21.             O => 'o',
  22.         })
  23.     }
  24. }
  25.  
  26. fn other_player(player:Field) -> Field {
  27.     match player {
  28.         X => O,
  29.         O => X,
  30.         N => N,
  31.     }
  32. }
  33.  
  34. fn show(board:&[Field; 9]) {
  35.     print!("+---+\n");
  36.     print!("|{}{}{}|\n", board[0], board[1], board[2]);
  37.     print!("|{}{}{}|\n", board[3], board[4], board[5]);
  38.     print!("|{}{}{}|\n", board[6], board[7], board[8]);
  39.     print!("+---+\n");
  40. }
  41.  
  42. // Should perhaps be refactored to iterator?
  43. fn streaks<F>(board:&[Field; 9], streak_handler:&mut F) where F : FnMut([Field; 3]) {
  44.     for row in 0..3 {
  45.         streak_handler([board[3*row + 0], board[3*row + 1], board[3*row + 2]]);
  46.     }
  47.     for col in 0..3 {
  48.         streak_handler([board[3*0 + col], board[3*1 + col], board[3*2 + col]]);
  49.     }
  50.     streak_handler([board[3*0 + 0], board[3*1 + 1], board[3*2 + 2]]);
  51.     streak_handler([board[3*0 + 2], board[3*1 + 1], board[3*2 + 0]]);
  52. }
  53.  
  54. fn find_winner(board:&[Field; 9]) -> Field {
  55.     let mut winner = N;
  56.     streaks(board, &mut |streak:[Field; 3]| {
  57.         if streak[0] != N && streak[0] == streak[1] && streak[1] == streak[2] {
  58.             winner = streak[0];
  59.         }
  60.     });
  61.     return winner;
  62. }
  63.  
  64. fn free_pos<F>(board:&[Field; 9], pos_handler:&mut F) where F : FnMut(usize) {
  65.     for pos in 0..9 {
  66.         if board[pos] == N {
  67.             pos_handler(pos);
  68.         }
  69.     }
  70. }
  71.  
  72. fn moves<F>(board:&[Field; 9], to_play:Field, move_handler:&mut F) where F : FnMut(usize, &[Field; 9]) {
  73.     let mut new_board = *board;
  74.     free_pos(board, &mut |pos| {
  75.         new_board[pos] = to_play;
  76.         move_handler(pos, &new_board);
  77.         new_board[pos] = N;
  78.     });
  79. }
  80.  
  81. fn finished(board:&[Field; 9]) -> bool {
  82.     if board.iter().find(|x| { **x == N }) == None {
  83.         return true;
  84.     }
  85.     if find_winner(board) != N {
  86.         return true;
  87.     }
  88.     return false;
  89. }
  90.  
  91. fn score(board:&[Field; 9], player:Field, to_play:Field) -> u32 {
  92.     let winner = find_winner(board);
  93.     if winner == player { return 2; }
  94.     if winner == other_player(player) { return 0; }
  95.  
  96.     let mut scores:Vec<u32> = vec![];
  97.     let next_player = other_player(to_play);
  98.     moves(board, to_play, &mut |_pos, new_board| {
  99.         scores.push(score(new_board, player, next_player));
  100.     });
  101.  
  102.     if player == to_play {
  103.         return *scores.iter().max().unwrap_or(&1u32);
  104.     } else {
  105.         return *scores.iter().min().unwrap_or(&1u32);
  106.     }
  107. }
  108.  
  109. fn best_move(rng:&mut rand::ThreadRng, board:&[Field; 9], player:Field) -> usize {
  110.     let mut scores:Vec<(usize, u32)> = vec![];
  111.     let next_player = other_player(player);
  112.  
  113.     moves(board, player, &mut |pos, new_board| {
  114.         scores.push((pos, score(new_board, player, next_player)));
  115.     });
  116.  
  117.     let max_score = scores.iter().fold(0u32,
  118.         |max, &(_, score)| {
  119.             if score > max { score } else { max }
  120.         }
  121.     );
  122.  
  123.     let good_moves = scores.iter()
  124.         .filter(|&&(_, score)| { score == max_score })
  125.         .collect::<Vec<&(usize, u32)>>();
  126.  
  127.     let choice = Range::new(0, good_moves.len()).ind_sample(rng);
  128.     let (pos, _) = *good_moves[choice];
  129.     return pos;
  130. }
  131.  
  132. fn read_move(reader: &mut io::BufRead, &board: &[Field; 9]) -> Result<usize, io::Error> {
  133.     loop {
  134.         print!("X's move [0-8]: ");
  135.         io::stdout().flush().ok().expect("Could not flush stdout");
  136.         let mut buffer = String::new();
  137.         try! { reader.read_line(&mut buffer) };
  138.         match buffer.trim().parse::<usize>() {
  139.             Ok(n) => {
  140.                 if n > 8 {
  141.                     println!("out of range");
  142.                 } else if board[n] != N {
  143.                     println!("square is occupied");
  144.                 } else {
  145.                     return Ok(n);
  146.                 }
  147.             },
  148.             Err(_) => println!("enter an integer")
  149.         }
  150.     }
  151. }
  152.  
  153. fn main_core() -> Result<i32, io::Error> {
  154.     let mut rng = rand::thread_rng();
  155.     let mut board:[Field; 9] = [
  156.         N, N, N,
  157.         N, N, N,
  158.         N, N, N,
  159.     ];
  160.  
  161.     let reader = io::stdin();
  162.  
  163.     while !finished(&board) {
  164.         show(&board);
  165.  
  166.         let xmove = try!{ read_move(&mut reader.lock(), &board) };
  167.         board[xmove] = X;
  168.         if finished(&board) {
  169.             break;
  170.         }
  171.  
  172.         show(&board);
  173.         let omove = best_move(&mut rng, &board, O);
  174.         print!("O's move [0-8]: {}\n", omove);
  175.         board[omove] = O;
  176.     }
  177.  
  178.     show(&board);
  179.     match find_winner(&board) {
  180.         N => print!("Tie\n"),
  181.         winner => print!("{} wins!\n", winner),
  182.     };
  183.  
  184.     return Ok(0);
  185. }
  186.  
  187. fn main() {
  188.     match main_core() {
  189.         Ok(_) => (),
  190.         Err(err) => print!("Terminated with IO error: {}\n", err),
  191.     }
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement