fix: have no start item selection, only choose who starts (bot game type)
This commit is contained in:
parent
5f5f34a52f
commit
7d1162f117
84
src/main.rs
84
src/main.rs
@ -46,6 +46,7 @@ trait Displayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the **Tic-Tac-Toe** board game
|
/// Represents the **Tic-Tac-Toe** board game
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
struct Board {
|
struct Board {
|
||||||
// board array is reprensented as follow:
|
// board array is reprensented as follow:
|
||||||
// [ 0, 1, 2 ]
|
// [ 0, 1, 2 ]
|
||||||
@ -224,6 +225,20 @@ impl Player {
|
|||||||
fn new(item: Item, is_bot: bool) -> Self {
|
fn new(item: Item, is_bot: bool) -> Self {
|
||||||
Player { item, is_bot }
|
Player { item, is_bot }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_bot() -> Self {
|
||||||
|
Player {
|
||||||
|
item: Item::Empty,
|
||||||
|
is_bot: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_human() -> Self {
|
||||||
|
Player {
|
||||||
|
item: Item::Empty,
|
||||||
|
is_bot: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Player {
|
impl Default for Player {
|
||||||
@ -239,10 +254,7 @@ impl Player {
|
|||||||
/// init players with the game type
|
/// init players with the game type
|
||||||
fn from_game_type(game_type: GameType) -> Vec<Player> {
|
fn from_game_type(game_type: GameType) -> Vec<Player> {
|
||||||
match game_type {
|
match game_type {
|
||||||
GameType::TwoPlayers => vec![
|
GameType::TwoPlayers => vec![Player::new(Item::X, false), Player::new(Item::O, false)],
|
||||||
Player::new(Item::Empty, false),
|
|
||||||
Player::new(Item::Empty, false),
|
|
||||||
],
|
|
||||||
GameType::Bot => vec![
|
GameType::Bot => vec![
|
||||||
Player::new(Item::Empty, false),
|
Player::new(Item::Empty, false),
|
||||||
Player::new(Item::Empty, true),
|
Player::new(Item::Empty, true),
|
||||||
@ -255,7 +267,7 @@ impl Player {
|
|||||||
/// Two `GameType` availables:
|
/// Two `GameType` availables:
|
||||||
/// * TwoPlayers: no bot
|
/// * TwoPlayers: no bot
|
||||||
/// * Bot: player against the bot
|
/// * Bot: player against the bot
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
enum GameType {
|
enum GameType {
|
||||||
TwoPlayers,
|
TwoPlayers,
|
||||||
Bot,
|
Bot,
|
||||||
@ -306,15 +318,15 @@ impl TicTacToe {
|
|||||||
self.game_type = game_type;
|
self.game_type = game_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_players_item(&mut self, first_item: Item) -> Result<(), String> {
|
fn set_players_item(&mut self) -> Result<(), String> {
|
||||||
if self.players.len() != 2 {
|
if self.players.len() != 2 {
|
||||||
return Err(
|
return Err(
|
||||||
"unable to initialize players item, 2 players must be initialized".to_string(),
|
"unable to initialize players item, 2 players must be initialized".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.players[0].item = first_item;
|
self.players[0].item = Item::X;
|
||||||
self.players[1].item = first_item.next();
|
self.players[1].item = Item::O;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -334,8 +346,17 @@ impl TicTacToe {
|
|||||||
Ok(self.players[0])
|
Ok(self.players[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// set the item for the first player (the one that starts)
|
/// if `GameType` is againt bot, you can select who starts
|
||||||
fn select_first_player_item(&mut self) {
|
fn select_first_player(&mut self) {
|
||||||
|
if self.players.len() != 2 {
|
||||||
|
fatal("unable to initialize the game, 2 players must be set".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first player always starts whith 'X'
|
||||||
|
if self.game_type == GameType::TwoPlayers {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut attempt = 0;
|
let mut attempt = 0;
|
||||||
loop {
|
loop {
|
||||||
if attempt == 2 {
|
if attempt == 2 {
|
||||||
@ -343,19 +364,29 @@ impl TicTacToe {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let input = TicTacToe::get_user_input("first player, choose your item: ('X' or 'O')");
|
let input = TicTacToe::get_user_input("who starts: ('B': bot, 'H': you as human)");
|
||||||
let item_start = Item::try_from(input);
|
let is_bot = self.players[0].is_bot;
|
||||||
match item_start {
|
|
||||||
Ok(item) => {
|
match &input[..] {
|
||||||
match self.set_players_item(item) {
|
"B" | "b" => {
|
||||||
Ok(()) => break,
|
if !is_bot {
|
||||||
Err(e) => fatal(e),
|
self.players.swap(0, 1)
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
Err(e) => error(e.to_string()),
|
"H" | "h" => {
|
||||||
|
if is_bot {
|
||||||
|
self.players.swap(0, 1)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error("bad input, please retry!".to_string());
|
||||||
attempt += 1;
|
attempt += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set_players_item();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,9 +441,22 @@ impl TicTacToe {
|
|||||||
Ok(available_indexes[0] + 1)
|
Ok(available_indexes[0] + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// minimax algorithm used by the bot player to find the best move (minimizing the loses)
|
||||||
|
fn minimax(&self, board: Option<Board>, player: Player, depth: usize) -> usize {
|
||||||
|
let mut board = match board {
|
||||||
|
Some(b) => b,
|
||||||
|
None => self.board.clone(),
|
||||||
|
};
|
||||||
|
let availables_indexes = board.get_available_indexes();
|
||||||
|
for index in availables_indexes {
|
||||||
|
board.set_item(player.item, index);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
self.select_game_type();
|
self.select_game_type();
|
||||||
self.select_first_player_item();
|
self.select_first_player();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if self.board.is_full() {
|
if self.board.is_full() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user