Script: tic-tac-toe (tres en raya)
Posted in Scripts, linux on April 5th, 2009 by mrcomputer – 2 CommentsEste clásico juego de mesa, que ha jugado un papel muy importante en algunas peliculas, también se puede hacer con bash.
Solo tenéis que guardar este código en un archivo llamado ttt.sh o bajarlo desde aquí y darle privilegios de ejecución con chmod +x ttt.sh. Ya podrás ejecutarlo con ./ttt.sh y jugar a este juego.
#!/bin/bash # Sat Jul 12 16:52:30 EDT 2003 # NAME: ttt # Copyright 2003, Chris F.A. Johnson # Released under the terms of the GNU General Public License ESC=$'\e' tictactoe() { [ $verbose -ge 1 ] && echo tictactoe $* >&2 board=`printf "%9.9s" " "` mvnum=1 remainder=" 1 2 3 4 5 6 7 8 9 " show "$board" while : do status eval \$player$P [ $? -ne 0 ] && return put $_MOVE "$board" board=$_PUT # show "$board" mkbold "$_MOVE" printat 0 0 $mvnum printat $prompt sleep $pause & mlist="$mlist $_MOVE" remainder=${remainder/ $_MOVE / } checkboard "$board" && { mkbold $win printat $prompt "$cle" eval winner \$player$P return } [ $mvnum -eq 9 ] && { B=$U mkbold "$_MOVE" winner "Neither player" return } wait B=$U mkbold "$_MOVE" if [ $P = O ] then P=X OP=O else P=O OP=X fi mvnum=$(( $mvnum + 1 )) done } winner() { [ $verbose -ge 1 ] && echo winner $* >&2 printat $prompt "$cle $* wins\n\n" } status() { [ $verbose -ge 1 ] && echo status $* >&2 if [ $verbose -ge 1 ] then printat 4 0 printf "${cle}Move: %s Player: %s Board: \"%s\" Last move: %s Move list: %s" \ "$mvnum" "$P" "${board// /-}" "$_MOVE" "$mlist" else false fi } show() { [ $verbose -ge 1 ] && echo show $* >&2 printat 0 0 $mvnum printat 0 $top ##$(( ($LINES - 5) / 2 )) printf " %${margin}.${margin}s | %1s | %1s\n" "${1:0:1}" "${1:1:1}" "${1:2:1}" printf "%${margin}.${margin}s---+---+---\n" " " printf " %${margin}.${margin}s | %1s | %1s\n" "${1:3:1}" "${1:4:1}" "${1:5:1}" printf "%${margin}.${margin}s---+---+---\n" " " printf " %${margin}.${margin}s | %1s | %1s\n" "${1:6:1}" "${1:7:1}" "${1:8:1}" } put() { [ $verbose -ge 1 ] && echo put $1 \""$2"\" >&2 local n=$(( $1 - 1 )) _PUT=${2:-$board} [ "${_PUT:$n:1}" = " " ] && _PUT=${_PUT:0:$n}$P${_PUT:$1} } checkboard() { [ $verbose -ge 1 ] && echo checkboard \"$*\" >&2 case $1 in $P??$P??$P??) win="1 4 7" ;; ?$P??$P??$P?) win="2 5 8" ;; ??$P??$P??$P) win="3 6 9" ;; ??$P?$P?$P??) win="3 5 7" ;; $P???$P???$P) win="1 5 9" ;; $P$P$P??????) win="1 2 3" ;; ???$P$P$P???) win="4 5 6" ;; ??????$P$P$P) win="7 8 9" ;; *) false ;; esac } mkbold() { [ $verbose -ge 1 ] && echo mkbold $* >&2 for sq in $* do row=$(( ($sq - 1) / 3 )) col=$(( ($sq - 1) % 3 + 1 )) printat $(( ($col * 4) + $margin - 2 )) $(( ($row * 2) + $top )) printf "${B}$P${U}" done } human() { [ $verbose -ge 1 ] && echo human $* >&2 while : do key "Select ($remainder)" # case $_MOVE in # "$ESC") read -sn1; read -sn1 kp; continue ;; # esac _MOVE=$_KEY case $_MOVE in 1|2|3|4|5|6|7|8|9) [ "${board:_MOVE-1:1}" = " " ] && break ;; q|Q|x|X) echo; return 5 ;; p) printat $prompt KEYECHO= KEYMAX=$(( $COLUMNS - 10 )) key "Enter delay in seconds" pause=$_KEY ;; "") set -- $remainder _MOVE=$1 [ $verbose -ge 1 ] && echo "|$_MOVE|" >&2 break ;; *) printat $prompt printf "\r%s%s\r" " "$cle" $_MOVE: Invalid move" sleep 1 printf "%s\r" "$cle" ;; esac done } randy() { [ $verbose -ge 1 ] && echo randy $* >&2 randstr $remainder _MOVE=$_RANDSTR } key() { [ $verbose -ge 1 ] && echo key $* >&2 printat $prompt "$cle$CVIS$beep" read -${KEYECHO}n$KEYMAX -p "${1:-PAK}: " _KEY 2>&1 printf "$CINV" } getkey() { local OKchars=${1:-${remainder// /}} local kp2 kp3 stty -echo while : do prompt="==>" prompt IFS= read -r -sn1 -p " " kp 2>&1 || exit 2 #cleanup case $OKchars in *"$kp"*) case $kp in $ESC) read -st1 -n1 kp2 case $kp2 in \[) read -st1 -n1 kp3 case $kp3 in A) kp=$UP; break ;; B) kp=$DN; break ;; C) kp=$RT; break ;; D) kp=$LF; break ;; esac ;; esac ;; *) break ;; esac ;; esac done _KEY=$kp } randstr() { [ $verbose -ge 1 ] && echo randstr $* >&2 # [ -n "$1" ] || return 1 n=$(( ($RANDOM % $#) + 1 )) eval _RANDSTR=\${$n} } isblock() { [ $verbose -ge 1 ] && echo isblock $* >&2 win= block= for _MOVE in $remainder do P=$OP put $_MOVE P=$OP checkboard "$_PUT" && return done _MOVE= } block() { [ $verbose -ge 1 ] && echo block $* >&2 block= for _MOVE in $remainder do put $_MOVE checkboard "$_PUT" && return P=$OP put $_MOVE P=$OP checkboard "$_PUT" && block=$_MOVE done [ "$block" ] && { _MOVE=$block; return; } randy } computer() { [ $verbose -ge 1 ] && echo computer $* >&2 local r c case $mvnum in 1) randstr 1 3 7 9 _MOVE=$_RANDSTR ;; 2) if [ "${board:4:1}" = " " ] then _MOVE=5 else randstr 1 3 7 9 _MOVE=$_RANDSTR fi ;; 3) r=${mlist// /} c='1 3 7 9' randstr ${c//[$r]/} # randstr ${remainder//[$r]/} _MOVE=$_RANDSTR ;; 4) isblock [ "$_MOVE" ] && return r=${mlist// /} c='2 4 6 8' randstr ${remainder//[$r]/} _MOVE=$_RANDSTR ;; *) block ;; esac } printat() { #== print arguments 3-... at Y=$2 X=$1 [ $verbose -ge 1 ] && echo printat $* >&2 [ $# -lt 2 ] && return 1 local y=$2 local x=$1 shift 2 msg="$*" printf "\e[%d;%dH%b" $y $x "$msg" } version() { echo " $progname, version $version Copyright $copyright, $author $email This is free software, released under the terms of the GNU General Public License. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " } usage() { echo " ${B}NAME${U}: $progname - Tic-Tac-Toe ${B}USAGE${U}: $progname [OPTIONS] ${B}OPTIONS${U}: -x player1 - specify first player -o player2 - specify second player -c player1,player2 - specify both players -p seconds - time to pause between moves -h, --help - help: print this message -H, --help_long - help: print more detailed message (if available) -v, --verbose - sends messsages to \$HOME/tttlog -V, --version - print version information Copyright 2003, Chris F.A. Johnson " } verbose=0 longusage=0 version="1.0" copyright=2003 author="Chris F.A. Johnson" progname=${0##*/} P=X OP=O playerX=human playerO=computer co= li= if tput ce >/dev/null 2>&1 then ## e.g. FreeBSD co=co li=li elif tput el 2>/dev/null then ## e.g. Linux co=cols li=lines fi UNBOLD=$'\E[0m' standout=$'\E[0;1;7m' cle=$'\E[K' clb=$'\E[1K' ULINE=$'\E[0;4m' REVERSE=$'\E[0;7m' BLINK=$'\E[0;5m' BOLD=$'\E[0;1m' CINV=$'\E[0;8m' R=$REVERSE U=$UNBOLD B=$BOLD BR=$B$R Cl=$'\f' if [ "$co" ] then tput reset COLUMNS=${COLUMNS:=`tput $co`} else COLUMNS=${COLUMNS:-80} fi top=6 margin=11 prompt="3 $(( $top + 9 ))" beep= #$'\a' pause=1 KEYMAX=1 KEYECHO=s while getopts vVhH-:xoX:O:c:p: var do case "$var" in x) playerX=human playerO-computer ;; o) playerO=human playerX=computer ;; X) playerX=$OPTARG ;; O) playerO=$OPTARG ;; c|C) playerO=${OPTARG#*,} playerX=${OPTARG%,*} ;; p) pause=$OPTARG ;; -) case $OPTARG in help) usage; exit ;; verbose) verbose=$(( $verbose + 1 )) ;; version) version; exit ;; esac ;; h) usage; exit ;; H) longusage=1; usage; exit ;; v) verbose=$(( $verbose + 1 )) ;; V) version; exit ;; *);; esac done shift $(( $OPTIND - 1 )) if [ "$co" ] then COLUMNS=`tput $co` else COLUMNS=${COLUMNS:-80} fi margin=11 ##$(( ($COLUMNS - 11) / 2 )) clear if [ $verbose -ge 1 ] then exec 2>$HOME/tttlog set -x fi tictactoe printat $prompt "\n$CVIS\n"












