Home > Enterprise >  Bash Script Tic Tac Toe cant detect winning fields
Bash Script Tic Tac Toe cant detect winning fields

Time:05-04

I am trying to make a little Tic Tac Toe. I tried to make the diagonal winning line, but it did not work. If I tried the normal winning line, it worked, but, only in the first 3 fields. I made a check_winner() function, where I detect all winning fields. I do not know, why it is not detecting the winning fields.

This is my Code:

#!/usr/bin/bash

player_1="X"
player_2="O"

turn=1

game_on=true

moves=( - - - - - - - - - )

welcome_message() {
  clear
  echo "========================"
  echo "=== LETS PLAY A GAME ==="
  echo "========================"
  sleep 3
}
print_board () {
  clear
  echo " ${moves[0]} | ${moves[1]} | ${moves[2]} "
  echo "-----------"
  echo " ${moves[3]} | ${moves[4]} | ${moves[5]} "
  echo "-----------"
  echo " ${moves[6]} | ${moves[7]} | ${moves[8]} "
  echo "============="
}

player_pick(){
  if [ $(($turn % 2)) == 0 ]
  then
    echo "Player 1 pick a square: "
    play=$player_2
  else

    play=$player_1
    echo "Player 2 pick a sqaure: "
  fi

  read square

  space=${moves[(square -1)]} 
  
  
    
  if [[ ${moves[(square-1)]} == "-" ]] && [[ $square = [0-9] ]] || [[ $space = [0-9]  ]]
  then 
    moves[(square -1)]=$play
    ((turn =1))
  else
  
    player_pick
    echo "Not a valid square."
  fi
  space=${moves[(square-1)]} 
}

check_match() {
  if  [[ ${moves[0]} == ${moves[1]} ]]&& 
      [[ ${moves[1]} == ${moves[2]} ]]; then
    game_on=false
  fi
  if [ $game_on == false ]; then
    if [ ${moves[$1]} == 'x' ];then
      echo "Player one wins!"
      return 
    else
      echo "player two wins!"
      return 
    fi
  fi
}

check_winner(){
  if [ $game_on == false ]; then return; fi
  check_match 0 1 2
  if [ $game_on == false ]; then return; fi
  check_match 3 4 5
  if [ $game_on == false ]; then return; fi
  check_match 6 7 8
  if [ $game_on == false ]; then return; fi
  check_match 0 4 8
  if [ $game_on == false ]; then return; fi
  check_match 2 4 6
  if [ $game_on == false ]; then return; fi
  check_match 0 3 6
  if [ $game_on == false ]; then return; fi
  check_match 1 4 7
  if [ $game_on == false ]; then return; fi
  check_match 2 5 8
  if [ $game_on == false ]; then return; fi
  
  if [ $turn -gt 9 ]; then 
    $game_on=false
    echo "Its a draw!"
  fi
}


welcome_message
print_board
while $game_on
do
  player_pick
  print_board
  check_winner
done

CodePudding user response:

Here is my modified version:

#!/bin/bash

player_1="X"
player_2="O"
turn=1
moves=( - - - - - - - - - )

welcome_message() {
    clear
    echo "========================"
    echo "=== LETS PLAY A GAME ==="
    echo "========================"
    sleep 3
}

print_board () {
    clear
    echo " ${moves[0]} | ${moves[1]} | ${moves[2]} "
    echo "-----------"
    echo " ${moves[3]} | ${moves[4]} | ${moves[5]} "
    echo "-----------"
    echo " ${moves[6]} | ${moves[7]} | ${moves[8]} "
    echo "============="
}

player_pick(){
    if [[ $(( turn % 2 )) == 0 ]]
    then
        echo "Player 1 pick a square: "
        play=$player_2
    else
        play=$player_1
        echo "Player 2 pick a square: "
    fi

    read -r square

    if [[ ${moves[(square-1)]} == "-" ]] &&
       [[ $square == [1-9] ]]
    then
        moves[(square -1)]=$play
        (( turn  = 1 ))
    else
        echo "Not a valid square."
        player_pick
    fi
}

check_match() {
    index1=$1
    index2=$2
    index3=$3

    if  [[ ${moves[$index1]} == "${moves[$index2]}" ]] &&
        [[ ${moves[$index1]} == "${moves[$index3]}" ]] &&
        [[ ${moves[$index1]} != "-" ]]
    then
        if [[ ${moves[$index1]} == 'X' ]]
        then
            echo "Player one wins!"
            exit
        else
            echo "player two wins!"
            exit
        fi
    fi
}

check_winner(){
    if [[ $turn -gt 9 ]]
    then
        echo "Its a draw!"
        exit
    fi
    check_match 0 1 2
    check_match 3 4 5
    check_match 6 7 8
    check_match 0 4 8
    check_match 2 4 6
    check_match 0 3 6
    check_match 1 4 7
    check_match 2 5 8
}

welcome_message
print_board
while true
do
    player_pick
    print_board
    check_winner
done

Modifications:

  • removed the game_on variable completely, the while is now on true.
  • in player_pick(), I removed the space variable, not required.
  • in check_match(), created 3 new variables (index1, index2, index3) to contain the values received in argument. Just to make it clearer later, but they are just $1, $2, $3.
  • in check_match(), replaced the hard coded indexes by the new variables. You had [0], [1] and [2] all the time. You only verified the first horizontal row all the time.
  • in check_match(), the if [[ ${moves[$index1]} == 'X' ]] ..., you had == 'x'. Capitals matter in bash.
  • in check_winner(), remove all the if statements. check_match() now exits when a player wins. Smaller code, easier to read.
  • in player_pick(), "Not a valid square." is now printed before player_pick() is called recursively.
  • Related