#!/usr/bin/env bash clear() { printf '\x1b\x5b\x48\x1b\x5b\x32\x4a' } red() { if (( $# )); then local red=$'\x1b\x5b\x33\x31\x6d' local rst=$'\x1b\x28\x42\x1b\x5b\x6d' printf %s%s%s "$red" "$1" "$rst" fi } render() { local pce=${pcs[$pos-1]} if [[ $pce = " " ]]; then pcs[$pos-1]=$(red "*") else pcs[$pos-1]=$(red "$pce") fi clear printf "%s\n" "${brd[0]}" printf "${brd[1]}\n" "${pcs[@]:0:3}" printf "%s\n" "${brd[2]}" printf "%s\n" "${brd[0]}" printf "${brd[1]}\n" "${pcs[@]:3:3}" printf "%s\n" "${brd[2]}" printf "%s\n" "${brd[0]}" printf "${brd[1]}\n" "${pcs[@]:6:3}" printf "%s\n" "${brd[0]}" pcs[$pos-1]=$pce } place() { if (( $# )); then local chr=$1 plc=$2 row win col pcs[$plc]=$chr for (( row = 0; row < 7; row += 3 )); do if [[ ${pcs[*]:$row:3} = @(x x x|o o o) ]]; then win=${pcs[$row]} break fi done if [[ -z $win ]]; then for col in {0..2}; do if [[ ${pcs[$col]}${pcs[$col+3]}${pcs[$col+6]} = @(xxx|ooo) ]]; then win=${pcs[$col]} break fi done fi if [[ -z $win ]]; then if [[ ${pcs[0]}${pcs[4]}${pcs[8]} = @(xxx|ooo) ]]; then win=${pcs[0]} elif [[ ${pcs[2]}${pcs[4]}${pcs[6]} = @(xxx|ooo) ]]; then win=${pcs[2]} fi fi (( pld += 1 )) if [[ -n $win ]]; then case $win in x) res=1 ;; o) res=2 esac elif (( pld == 9 )); then res=3 else res=0 fi return "$res" fi return 4 } win=0 pld=0 pos=1 pcs=( " " " " " " " " " " " " " " " " " " ) brd=( ' | |' ' %s | %s | %s' '___|___|___' ) while ! (( win )); do render while true; do read -rsn 1 key dir= case $key in "") if [[ ${pcs[$pos-1]} = " " ]]; then break fi ;; $'\x1b') read -rsn 2 arrow case $arrow in $'\x4f\x41'|$'\x5b\x41') dir=up ;; $'\x4f\x42'|$'\x5b\x42') dir=down ;; $'\x4f\x43'|$'\x5b\x43') dir=right ;; $'\x4f\x44'|$'\x5b\x44') dir=left ;; esac ;; w|W) dir=up ;; s|S) dir=down ;; d|D) dir=right ;; a|A) dir=left ;; esac if [[ -n $dir ]]; then case $dir in up) if (( pos > 3 )); then (( pos -= 3 )) fi ;; down) if (( pos < 7 )); then (( pos += 3 )) fi ;; right) if (( pos % 3 )); then (( pos += 1 )) fi ;; left) if (( (pos % 3) != 1 )); then (( pos -= 1 )) fi esac fi render done place x "$(( pos - 1 ))" if ! (( res )); then unu=( ) for (( cnt = 0; cnt < 9; ++cnt )); do if [[ ${pcs[$cnt]} = " " ]]; then unu+=( "$cnt" ) fi done ops=$(( RANDOM % ${#unu[@]} )) place o "${unu[$ops]}" fi if (( $res )); then render case $res in 1) printf 'x wins\n' ;; 2) printf 'o wins\n' ;; 3) printf 'tie game\n' esac exit fi done