Add code
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
/.idea/
|
||||||
|
/*.iml
|
||||||
6
Cargo.lock
generated
Normal file
6
Cargo.lock
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "tictactoe"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "tictactoe"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["t"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
21
src/main.rs
Normal file
21
src/main.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
mod tictactoe;
|
||||||
|
|
||||||
|
use crate::tictactoe::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut field = Field::new(3, 3);
|
||||||
|
//.mark(0, 0, Player::X)
|
||||||
|
//.mark(0, 1, Player::O);
|
||||||
|
field.print();
|
||||||
|
println!("----------------");
|
||||||
|
let mut player = Player::X;
|
||||||
|
while field.get_winner().is_none() {
|
||||||
|
let (x, y) = get_best_turn(&field, player);
|
||||||
|
field = field.mark(x, y, player);
|
||||||
|
field.print();
|
||||||
|
player = player.change();
|
||||||
|
println!("----------------");
|
||||||
|
}
|
||||||
|
println!("{:?}", field.get_winner());
|
||||||
|
|
||||||
|
}
|
||||||
171
src/tictactoe.rs
Normal file
171
src/tictactoe.rs
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub enum Player {
|
||||||
|
X, O, NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Player {
|
||||||
|
|
||||||
|
pub fn change(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
&Player::X => Player::O,
|
||||||
|
&Player::O => Player::X,
|
||||||
|
x => *x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Field {
|
||||||
|
fields: Vec<Vec<Player>>,
|
||||||
|
width: usize,
|
||||||
|
height: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Field {
|
||||||
|
|
||||||
|
pub fn new(width: usize, height: usize) -> Self {
|
||||||
|
Field { fields: vec![vec![Player::NONE; height]; width], width, height }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(&self) {
|
||||||
|
for j in 0 .. self.height {
|
||||||
|
for i in 0 .. self.width {
|
||||||
|
match self.fields[i][j] {
|
||||||
|
Player::X => print!("X"),
|
||||||
|
Player::O => print!("O"),
|
||||||
|
Player::NONE => print!(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mark(&self, x: usize, y: usize, player: Player) -> Self {
|
||||||
|
let mut fields = Vec::with_capacity(self.width);
|
||||||
|
for i in 0 .. self.width {
|
||||||
|
let mut column = Vec::with_capacity(self.height);
|
||||||
|
for j in 0 .. self.height {
|
||||||
|
if i == x && j == y {
|
||||||
|
column.push(player);
|
||||||
|
} else {
|
||||||
|
column.push(self.fields[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields.push(column);
|
||||||
|
}
|
||||||
|
Field { fields, width: self.width, height: self.height }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_winner(&self, player: Player) -> bool {
|
||||||
|
assert_eq!(self.width, self.height);
|
||||||
|
for i in 0 .. self.width { // check columns
|
||||||
|
let mut winner = true;
|
||||||
|
for j in 0 .. self.height {
|
||||||
|
if self.fields[i][j] != player {
|
||||||
|
winner = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if winner {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j in 0 .. self.height { // check rows
|
||||||
|
let mut winner = true;
|
||||||
|
for i in 0 .. self.width {
|
||||||
|
if self.fields[i][j] != player {
|
||||||
|
winner = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if winner {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // check top-left bottom-right diagonal
|
||||||
|
let mut winner = true;
|
||||||
|
for i in 0 .. self.width {
|
||||||
|
if self.fields[i][i] != player {
|
||||||
|
winner = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if winner {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // check bottom-left top-right diagonal
|
||||||
|
let mut winner = true;
|
||||||
|
for i in 0 .. self.width {
|
||||||
|
if self.fields[i][self.height - i - 1] != player {
|
||||||
|
winner = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if winner {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_winner(&self) -> Option<Player> {
|
||||||
|
if self.is_winner(Player::X) {
|
||||||
|
Some(Player::X)
|
||||||
|
} else if self.is_winner(Player::O) {
|
||||||
|
Some(Player::O)
|
||||||
|
} else {
|
||||||
|
let mut full = true;
|
||||||
|
for i in 0 .. self.width {
|
||||||
|
for j in 0 .. self.height {
|
||||||
|
if self.fields[i][j] == Player::NONE {
|
||||||
|
full = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if full {
|
||||||
|
Some(Player::NONE)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_best_turn(field: &Field, player: Player) -> (usize, usize) {
|
||||||
|
let (x, y, _) = search_best_turn(field, player);
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_best_turn(field: &Field, player: Player) -> (usize, usize, i8) {
|
||||||
|
let mut max_turn = (0, 0);
|
||||||
|
let mut max_value = -2;
|
||||||
|
for i in 0 .. field.width {
|
||||||
|
for j in 0 .. field.height {
|
||||||
|
if field.fields[i][j] == Player::NONE {
|
||||||
|
let played = field.mark(i, j, player);
|
||||||
|
let value = match played.get_winner() {
|
||||||
|
Some(p) => {
|
||||||
|
if p == player {
|
||||||
|
1
|
||||||
|
} else if p == Player::NONE {
|
||||||
|
0
|
||||||
|
} else { // loose
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let (_, _, sub_value) = search_best_turn(&played, player.change());
|
||||||
|
-sub_value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if value > max_value {
|
||||||
|
max_turn = (i, j);
|
||||||
|
max_value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(max_turn.0, max_turn.1, max_value)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user