NFsec Logo

Rozszyfruj: Gra słowna

18/09/2009 w Hacks & Scripts Brak komentarzy.  (artykuł nr 156, ilość słów: 1009)

P

rzedstawiony skrypt jest tłumaczeniem “Unscramble: A Word Game” z książki “Wicked Cool Shell Scripts” autorstwa Dave’a Taylor’a udostępnionym on-line (Skrypt #99) na stronie http://www.intuitive.com/wicked/. Do tłumaczenia zostało dodane także parę informacji od tłumacza.

      Jeśli widziałeś grę rozsypankę w twojej lokalnej gazecie lub grałeś w ogóle w gry słowne, jesteś zaznajomiony z podstawowymi zasadami działania tych gier: wybierane jest losowo słowo, które następnie jest kodowane. Twoim zadaniem jest zorientowanie się oraz odgadnięcie jakie oryginalnie słowo kryje się za rozsypanką w minimalnej ilości tur.

Kod:

#!/bin/sh

# unscramble - wybiera słowo, koduje je i prosi użytkownika
# o odgadnięcie oryginalnego słowa...

wordlib="/usr/lib/games/long-words.txt"
randomquote="$HOME/bin/randomquote.sh"

scrambleword()
{
  # pick a word randomly from the wordlib, and scramble it
  # Original word is 'match' and scrambled word is 'scrambled'

  match="$($randomquote $wordlib)"

  echo "Picked out a word!"

  len=$(echo $match | wc -c | sed 's/[^[:digit:]]//g')
  scrambled=""; lastval=1

  for (( val=1; $val < $len ; )) 
  do
    if [ $(perl -e "print int rand(2)") -eq 1 ] ; then
      scrambled=$scrambled$(echo $match | cut -c$val)
    else
      scrambled=$(echo $match | cut -c$val)$scrambled
    fi
    val=$(( $val + 1 ))
  done
}

if [ ! -r $wordlib ] ; then
  echo "$0: Missing word library $wordlib" >&2
  echo "(online at http://www.intuitive.com/wicked/examples/long-words.txt" >&2
  echo "save the file as $wordlib and you're ready to play!)" >&2
  exit 1
fi

newgame=""; guesses=0; correct=0; total=0 

until [ "$guess" = "quit" ] ; do

  scrambleword

  echo ""
  echo "You need to unscramble: $scrambled"

  guess="??" ; guesses=0
  total=$(( $total + 1 ))

  while [ "$guess" != "$match" -a "$guess" != "quit" -a "$guess" != "next" ] 
  do
    echo ""
    echo -n "Your guess (quit|next) : "
    read guess
 
    if [ "$guess" = "$match" ] ; then
      guesses=$(( $guesses + 1 ))
      echo ""
      echo "*** You got it with tries = ${guesses}!  Well done!! ***"  
      echo ""
      correct=$(( $correct + 1 ))
    elif [ "$guess" = "next" -o "$guess" = "quit" ] ; then
      echo "The unscrambled word was \"$match\". Your tries: $guesses"
    else
      echo "Nope. That's not the unscrambled word. Try again."
      guesses=$(( $guesses + 1 ))
    fi
  done
done

echo "Done. You correctly figured out $correct out of $total scrambled words."

exit 0

Jak to działa:

By losowo wybrać pojedynczą linię z pliku skrypt ten używa skryptu #76, “Wyświetlanie losowego tekstu” – nawet jeśli pierwotne został napisany w celu pracy ze stronami internetowymi. Podobnie jak wiele dobrych narzędzi Uniksa, okazuje się, że jest przydatną formą budowania w innych kontekstach niż ta jedna, do której został przeznaczony:

match="$($randomquote $wordlib)"

Najtrudniejszą częścią tego skryptu było wymyślenie jak ma być kodowane słowo. Nie ma żadnego uniksowego narzędzia, które by mogło w tym pomóc, ale na szczęście okazuje się, że jeśli złożymy zakodowane słowo, przechodząc litera po literze przez prawidłowo napisane słowo, a następnie losowo dodając każdą kolejną literę do zakodowanej sekwencji albo na jej początku, albo na jej końcu, możemy nawet efektywnie zakodować słowo – za każdym razem nieprzewidywalnie oraz w inny sposób:

if [ $(perl -e "print int rand(2)") -eq 1 ] ; then
  scrambled=$scrambled$(echo $match | cut -c$val)
else
  scrambled=$(echo $match | cut -c$val)$scrambled
fi

Należy zwrócić uwagę, gdzie w dwóch liniach znajduje się $scrambled: w pierwszej na początku jest dodawana litera, podczas, gdy w drugiej na końcu.

I innym przypadku główna logika gry powinna być z łatwością zrozumiana: zewnętrzna pętla while pracuje aż do momentu, kiedy użytkownik zamiast odgadywać słowo wpiszę frazę: quit, natomiast wewnętrzna pętla działa, aż użytkownik zgadnie słowo albo wpiszę frazę: next, aby przejść do kolejnego.

Uruchamianie skryptu:

Skrypt ten nie posiada żadnych argumentów czy parametrów, tak więc wystarczy wklepać jego nazwę i jesteś gotowy do gry!

Rezultaty:

$ unscramble
Picked out a word!
You need to unscramble: ninrenoccg
Your guess (quit|next) : concerning
*** You got it with tries = 1! Well done!! ***
Picked out a word!
You need to unscramble: esivrmipod
Your guess (quit|next) : quit
The unscrambled word was "improvised". Your tries: 0
Done. You correctly figured out 1 out of 2 scrambled words.

Czyste oraz intuicyjne odgadnięcie za pierwszym razem!

Modyfikowanie skryptu:

Być może jakaś metoda podpowiedzi uczyniłaby tę grę bardziej interesującą lub alternatywnie flaga, która by wymagała minimalną długość słowa, które jest akceptowalne. Aby wykonać to pierwsze, można na przykład kosztem wyniku pokazać pierwsze kilka liter niezaszyfrowanego wyrazu. Jeśli chodzi o to drugie, trzeba by mieć rozbudowany słownik wyrazów, ponieważ w tym załączonym do skryptu minimalna długość słowa to dziesięć liter, co z pewnością utrudnia zgadywanie!

Shell Script 076-randomquote.sh:

#!/bin/sh

# randomquote - given a one-line-per-entry datafile, this 
#   script will randomly pick one and display it. Best used
#   as an SSI call within a Web page.

awkscript="/tmp/randomquote.awk.$$"

if [ $# -ne 1 ] ; then
  echo "Usage: randomquote datafilename" >&2
  exit 1
elif [ ! -r "$1" ] ; then
  echo "Error: quote file $1 is missing or not readable" >&2
  exit 1
fi

trap "/bin/rm -f $awkscript" 0

cat < < "EOF" > $awkscript
BEGIN { srand(); }
      { s[NR] = $0 } 
END   { print s[randint(NR)] } 
function randint(n) { return int (n * rand() ) + 1 }
EOF

awk -f $awkscript < "$1"

exit 0

Powyżej został zawarty kod skryptu randomquote.sh niezbędny do działania gry słownej, który należy skopiować do katalogu /bin w swoim domowym katalogu lub jeśli gra ma być dostępna dla ogółu użytkowników w systemie należy sam skrypt jak i dodatek umieścić w głównym katalogu /bin oraz nadać mu odpowiednie prawa wykonywalności. Do prawidłowego działania także wymagane jest umieszczenie słownika słów, które mają być zgadywane w katalogu: /usr/lib/games/ pod nazwą: long-words.txt.

Więcej informacji: Script Shell, man bash

Kategorie K a t e g o r i e : Hacks & Scripts

Tagi T a g i : , ,

Podobne artykuły:

  • Brak tematycznie powiązanych artykułów.

Komentowanie tego wpisu jest zablokowane.