Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Rustic-Tac-Toe
extern crate rand;
use std::io;
use rand::Rng;
fn main() {
let zero_ascii = 48;
let default_char = '-';
let last_turn = 5;
// Step one, create board:
let mut board = [default_char; 9];
for i in 0..9 {
board[i] = (i + zero_ascii) as u8 as char;
}
print_board(board);
let mut results = someone_has_won(board);
let mut turn = 1;
while !results.0 {
if cats_game(board) {
println!("Cats game. Nobody wins!");
return;
}
// Step two, ask where the user wants to place their X.
println!("Where would you like to place an 'X'?");
let mut answer = String::new();
io::stdin().read_line(&mut answer)
.ok()
.expect("Error reading line");
let answer:usize = match answer.trim().parse() {
Ok(num) => num,
Err(_) => 10,
};
if answer > (board.len() - 1) {
println!("You cannot place something there!");
continue;
}
match board[answer] {
'X' => {
println!("You have already placed something there!");
continue;
}
'O' => {
println!("There is already something placed there!");
continue;
}
_ => {
board[answer] = 'X';
if turn < last_turn {
ai_move(&mut board);
}
print_board(board);
results = someone_has_won(board);
turn = turn + 1;
}
}
}
println!("{} has won!", results.1);
}
fn ai_move(board: &mut [char;9]) {
let mut rng = rand::thread_rng();
if rng.gen() {
// Do a good move. Basically, we look for a spot that has an X
// adjacent to it. We also prioritize the middle.
if board[4] != 'X' && board[4] != 'O' {
board[4] = 'O';
return;
}
else {
// First, we check to see if there are any two X's in a row so
// that we can defend.
for i in 0..3{
let mut rowCount = 0;
for j in 0..3 {
if board[j + 3*i] == 'X' {
rowCount = rowCount + 1;
}
}
if rowCount == 2 {
for j in 0..3 {
if board[j + 3*i] != 'X' && board[j + 3*i] != 'O' {
board[j + 3*i] = 'O';
return;
}
}
}
}
// Now we check columns
for i in 0..3 {
let mut columnCount = 0;
for j in 0..3 {
if board[i + 3*j] == 'X' {
columnCount = columnCount + 1;
}
}
if columnCount == 2 {
for j in 0..3 {
if board[i + 3*j] != 'X' && board[i + 3*j] != 'O' {
board[i + 3*j] = 'O';
return;
}
}
}
}
let mut empty_spot = -1;
for i in 0..9 {
if board[i] == 'O' {
let new_spot = get_available_adjacent(*board, i);
if new_spot < board.len() {
board[new_spot] = 'O';
return;
}
}
else if board[i] != 'X' {
empty_spot = i;
}
}
board[empty_spot] = 'O';
}
}
else {
// Do a random move
let mut num: usize = rng.gen_range(0, 9);
while board[num] == 'X' || board[num] == 'O' {
num = rng.gen_range(0, 9);
}
board[num] = 'O';
return;
}
}
fn print_board(board: [char;9]) {
for i in 0..9 {
print!("{} ", board[i]);
if i > 0 && (i+1) % 3 == 0 {
println!("");
}
}
}
fn someone_has_won(board: [char;9]) -> (bool, char) {
if board[0] == board[1] && board[1] == board[2] {
return (true, board[0]);
} else if board[3] == board[4] && board[4] == board[5] {
return (true, board[3]);
} else if board[6] == board[7] && board[7] == board[8] {
return (true, board[6]);
} else if board[0] == board[3] && board[3] == board[6] {
return (true, board[0]);
} else if board[1] == board[4] && board[4] == board[7] {
return (true, board[1]);
} else if board[2] == board[5] && board[5] == board[8] {
return (true, board[2]);
} else if board[0] == board[4] && board[4] == board[8] {
return (true, board[0]);
} else if board[2] == board[4] && board[4] == board[6] {
return (true, board[2]);
} else {
return (false, '-');
}
}
fn cats_game(board: [char;9] ) -> bool {
for i in 0..board.len() {
if board[i] == (i + 48) as u8 as char {
return false;
}
}
return true;
}
fn get_available_adjacent(board: [char;9], spot: usize) -> usize {
if spot == 4 {
if board[2] != 'X' && board[2] != 'O' {
return 2;
}
else if board[0] != 'X' && board[0] != 'O' {
return 0;
}
else if board[6] != 'X' && board[6] != 'O' {
return 6;
}
else if board[8] != 'X' && board[8] != 'O' {
return 8;
}
}
if spot + 3 < board.len() {
if board[spot + 3] != 'X' && board[spot + 3] != 'O' {
return spot + 3;
}
}
else if (spot as isize - 3) >= 0 {
if board[spot - 3] != 'X' && board[spot - 3] != 'O' {
return spot - 3;
}
}
else if ((spot + 1) / 3) == (spot / 3) {
if spot + 1 < board.len() {
if board[spot + 1] != 'X' && board[spot + 1] != 'O' {
return spot + 1;
}
}
}
else if ((spot -1) / 3) == (spot / 3) {
if board[spot - 1] != 'X' && board[spot - 1] != 'O' {
return spot - 1;
}
}
for i in 0..board.len() {
if board[i] != 'X' && board[i] != 'O' {
return i;
}
}
return 10;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment