1

I can't select the last square (3;3). The main problem was that. I hope someone can help me because i cannot know whats the problem.

The code is here:

#!/bin/bash

board=( " "  " "  " "
        " "  " "  " "
        " "  " " )

function draw_board {
    echo "+---+---+---+"
    echo "| ${board[0]} | ${board[1]} | ${board[2]} |"
    echo "+---+---+---+"
    echo "| ${board[3]} | ${board[4]} | ${board[5]} |"
    echo "+---+---+---+"
    echo "| ${board[6]} | ${board[7]} | ${board[8]}  |"
    echo "+---+---+---+"
}

function check_win {
    local symbol=$1
    if [[ ${board[0]} == $symbol && ${board[1]} == $symbol && ${board[2]} == $symbol ]] ||
       [[ ${board[3]} == $symbol && ${board[4]} == $symbol && ${board[5]} == $symbol ]] ||
       [[ ${board[6]} == $symbol && ${board[7]} == $symbol && ${board[8]} == $symbol ]] ||
       [[ ${board[0]} == $symbol && ${board[3]} == $symbol && ${board[6]} == $symbol ]] ||
       [[ ${board[1]} == $symbol && ${board[4]} == $symbol && ${board[7]} == $symbol ]] ||
       [[ ${board[2]} == $symbol && ${board[5]} == $symbol && ${board[8]} == $symbol ]] ||
       [[ ${board[0]} == $symbol && ${board[4]} == $symbol && ${board[8]} == $symbol ]] ||
       [[ ${board[2]} == $symbol && ${board[4]} == $symbol && ${board[6]} == $symbol ]]; then
        echo true
    else
        echo false
    fi
}


function is_free {
    local index=$1
    if [[ ${board[$index]} == " " ]]; then
        echo true
    else
        echo false
    fi
}

function game_loop {
    local player="X"
    local move_count=0
    local win=false
    while [[ $move_count -lt 10  && $win == false ]]; do
        draw_board
        echo "$player következik. Adja meg az x koordinátát [1-3]: "
        read x
        echo "Adja meg az y koordinátát [1-3]: "
        read y
        x=$((x-1))
        y=$((y-1))
        if [[ $x -lt 0 || $x -gt 2 || $y -lt 0 || $y -gt 2 ]]; then
            echo "Hibás koordináta!" >&2
        elif [[ $(is_free $((y*3+x))) == true ]]; then
            board[$((y*3+x))]="$player"
            win=$(check_win $player)
            if [[ $win == true ]]; then
                echo "$player győzött!"
            else
                ((move_count++))
                if [[ $player == "X" ]]; then
                    player="O"
                else
                    player="X"
        fi
        echo "Lépéshiba!" >&2
        fi
        fi
    done
if [[ $win == false ]]; then
    draw_board
    echo "Dontetlen!"
fi
}

I tried 3;3 and the program was not accept it and give me another try. Thank you for the reading! If you have any solution please share with me! Have a nice day!

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 1
    Please show use sample input & expected output in a [Minimal, Complete, and Verifiable example.](https://stackoverflow.com/help/mcve) – Gilles Quénot Feb 27 '23 at 11:20
  • @GillesQuénot There's only one line missing; `game_loop` to start it. And he explained the problem. – Emanuel P Feb 27 '23 at 11:32
  • 4
    The `board` array is one `" "` too short. – Emanuel P Feb 27 '23 at 11:37
  • 1
    Splitting the board array over three lines makes that really obvious. :) – Charles Duffy Feb 27 '23 at 14:36
  • BTW, re: `function foobar {` -- the POSIX standard syntax is `foobar() {` with no preceding `function`; see https://wiki.bash-hackers.org/scripting/obsolete, particularly the entry in the 3rd table (*This table lists features that are used only if you have a specific reason to prefer it over another alternative...*) – Charles Duffy Feb 27 '23 at 14:38
  • **NOTE:** It is highly recommended to avoid using **single-character** or **very short strings** for variable **names**, because that makes variable usage difficult to search for uniquely, because of the frequent match with substring in ordinary words or other variables. That would make such code nearly unmaintainable in an automated development environment, forcing manual updates/corrections for cases involving such instances. – Eric Marceau Mar 02 '23 at 03:24

1 Answers1

1

Your original script was a nice piece of work for a terminal game. However...

There was some logic error in the calculation of the placement positions in the grid.

Also, I shifted the bash array by one ... in order to make the 3x3 matrix more consistent with traditional mathematical representations of coordinates.

In the below adaptation of the script, I have also updated the message strings with some sensible equivalents in English for common understanding.

I am personally not a fan of elif usage, so I exploded those code segments for more clarity (in my view). I hope you like the updated version.

The modified script:

#!/bin/bash

board=( " "
    " "  " "  " "
    " "  " "  " "
    " "  " "  " " )

function draw_board {
    echo -e "\n\t+---+---+---+"
    echo -e "\t| ${board[1]} | ${board[2]} | ${board[3]} |"
    echo -e "\t+---+---+---+"
    echo -e "\t| ${board[4]} | ${board[5]} | ${board[6]} |"
    echo -e "\t+---+---+---+"
    echo -e "\t| ${board[7]} | ${board[8]} | ${board[9]} |"
    echo -e "\t+---+---+---+"
}

function check_win {
    local symbol=${1}
    if [[ ${board[1]} == ${symbol} && ${board[2]} == ${symbol} && ${board[3]} == ${symbol} ]] ||
       [[ ${board[4]} == ${symbol} && ${board[5]} == ${symbol} && ${board[6]} == ${symbol} ]] ||
       [[ ${board[7]} == ${symbol} && ${board[8]} == ${symbol} && ${board[9]} == ${symbol} ]] ||
       [[ ${board[1]} == ${symbol} && ${board[4]} == ${symbol} && ${board[7]} == ${symbol} ]] ||
       [[ ${board[2]} == ${symbol} && ${board[5]} == ${symbol} && ${board[8]} == ${symbol} ]] ||
       [[ ${board[3]} == ${symbol} && ${board[6]} == ${symbol} && ${board[9]} == ${symbol} ]] ||
       [[ ${board[1]} == ${symbol} && ${board[5]} == ${symbol} && ${board[9]} == ${symbol} ]] ||
       [[ ${board[3]} == ${symbol} && ${board[5]} == ${symbol} && ${board[7]} == ${symbol} ]]; then
        echo "true"
    else
        echo "false"
    fi
}


function is_free {
    local index=${1}
    if [[ ${board[${index}]} == " " ]]; then
        echo "true"
    else
        echo "false"
    fi
}

function game_loop {
    local player="X"
    local move_count=0
    local win=false

    draw_board

    while [[ ${move_count} -lt 9 ]]; do
        #echo "$player következik. Adja meg az x koordinátát [1-3]: "
        echo -e "\nPlayer $player:\n\tEnter your choice of x coordinate [1-3]: \c"
        read x
        echo -e "\tEnter your choice of y coordinate [1-3]: \c"
        read y

        if [[ $x -lt 1 || $x -gt 3 || $y -lt 1 || $y -gt 3 ]]; then
            echo -e "\tInvalid coordinate entered!" >&2
    else
        if [[ $(is_free $(( (y-1) * 3 + x ))) == true ]]; then
            board[$(( (y-1) * 3 + x ))]="${player}"
                ((move_count++))

                win=$(check_win $player)
                if [[ ${win} == "true" ]]; then
                    draw_board
                    echo -e "\n\t*** ${player} wins Tic-Tac-Toe ***"
                    break
                else
                    if [[ ${player} == "X" ]]; then
                            player="O"
                    else
                            player="X"
                fi
            fi
        else
            echo -e "\t\t That space is taken.  Please choose another ..."
            fi
        fi
        draw_board
    done

    if [[ ${win} == "false" ]]; then
        echo -e "\n\t*** Draw ***"
    fi
}

game_loop
Eric Marceau
  • 1,601
  • 1
  • 8
  • 11