Написание минимаксных алгоритмов в bash - PullRequest
1 голос
/ 29 мая 2019

Я прошу прощения за неопределенный вопрос, я полностью потерян и не знаю, что пошло не так в данный момент.

Недавно я пытался изучить bash-скриптинг и решил написать тиктактое с минимаксной и альфа-бета-обрезкой.Я написал сценарий очень питоническим способом, так как в целом я все еще плохо знаком с UNIX.Когда я попытался запустить функцию минимакса, я не получил никаких ошибок, но он ничего не выводил и не выходил нормально (пришлось CTRL C).

если текущая доска выиграна, функция может сказать, что она выиграна, и вернуть то, что мне нужно.Но когда он не выигран, он не может перейти на следующий уровень.

#!/bin/bash

declare -a board=( A1 " o" " x" " o" " o" " x" C1 C2 C3 )
shopt -s extglob


#draws the grid
draw(){
grid="| "${board[0]}" | ${board[1]} | ${board[2]} |
----------------
| ${board[3]} | ${board[4]} | ${board[5]} |
----------------
| ${board[6]} | ${board[7]} | ${board[8]} |" 

echo "$grid"
}

#test if board has a winning combination for either player
wintest(){
local testboard=("$@")
for p in " o" " x"
do
#test for vertical win
for i in $(seq 0 2) 
    do
        if [ "$p" == "${testboard[$i]}" -a "$p" == "${testboard[$(($i+3))]}" -a "$p" == "${testboard[$(($i+6))]}" ]; then
        echo 1
        fi
    done
#test for horizontal win
for i in 0 3 6 
    do  
        if [ "$p" == "${testboard[$i]}" -a "$p" == "${testboard[$i+1]}" -a "$p" == "${testboard[$i+2]}" ]; then
        echo 1
        fi
    done
#diagonal win   
if [ "$p" == "${testboard[0]}" -a "$p" == "${testboard[4]}" -a "$p" == "${testboard[8]}" ]; then
echo 1
fi
if [ "$p" == "${testboard[2]}" -a "$p" == "${testboard[4]}" -a "$p" == "${testboard[6]}" ]; then
echo 1
fi
done
}

#minimax function. parameters: player depth alpha beta board
minimax(){
if [ $1 -eq 1 ]; then
local player="1"
local p=" o"

elif [ $1 -eq 2 ]; then 
local player="2"
local p=" x"
fi

local depth=$2
local alpha=$3
local beta=$4

shift 4

#create array amove containing available moves
local boardc=("$@") 
local amove=("${boardc[@]/+(" x"|" o")}")
for i in "${!amove[@]}"; do 
if [[ -z "${amove[$i]}" ]]; then
unset amove[$i]
fi
done

#determine if anybody has won in the current board
#$player=1 is the maximing player. wintest is called on the start of the turn,
#if a winning combination exist, it belongs to the previous player

local winstat=$(wintest "${boardc[@]}")
if [ -n "$winstat" ]; then
    if [ "${player}" == 2 ]; then   
    echo "$depth"

    else  
    echo "-$depth"
    fi

else
    if [ "${player}" == 1 ]; then
    local bestval=-1000
        for i in "${amove[@]}"
        do      
            local boardcm="${boardc[@]}"    
            boardcm=("${boardcm[@]/"$i"/"$p"}")
            local value="$( minimax 2 $(( $depth+1 )) $alpha $beta "${boardcm[@]}" )"
            bestval=$(( "$bestval" > "$value" ? $bestval : "$value" ))
            alpha=$(( "$bestval" > "$alpha" ? "$bestval" : "$alpha" ))
            if [ "$beta" -le "$alpha" ] 
            then 
            break
            fi
        done
        echo "$bestval"

    elif [ "${player}" == 2 ]; then
    local bestval=1000
        for i in "${amove[@]}"
        do      
            local boardcm="${boardc[@]}"    
            boardcm=("${boardcm[@]/"$i"/"$p"}")
            local value="$( minimax 1 $(( $depth+1 )) $alpha $beta "${boardcm[@]}" )"
            bestval=$(( "$bestval" < "$value" ? "$bestval" : "$value" ))
            beta=$(( "$bestval" < "$beta" ? "$bestval" : "$beta" ))
            if [ "$beta" -le "$alpha" ]; then 
            break
            fi
        done
        echo "$bestval"
    fi
fi
}

Теоретически, функция минимакса должна возвращать единственное значение, которое является самым высоким (или самым низким в зависимости от игрока) значением, которое может быть гарантировано в текущем состоянии доски.Функция работает до той части, где происходит рекурсия.

Прошу прощения за то, что не могу более подробно ответить на мой вопрос, я действительно понятия не имею, почему функция не работает

...