Προς το περιεχόμενο

Προγραμματίζοντας ένα παιχνίδι με λέξεις


White_Cat

Προτεινόμενες αναρτήσεις

Καλησπέρα σε όλους !

 Αφορμή γι' αυτό το μήνυμα ήταν κατ' αρχήν ένα εισαγωγικό βιβλίο Αγγλικών που στο οπισθόφυλλό του έχει μια λίστα με περίπου 3.000 λέξεις, ώστε να ανατρέχει εύκολα ο αναγνώστης. Θέλοντας λοιπόν να ξαναθυμηθώ τα φοιτητικά μου χρόνια και το δηλωτικό προγραμματισμό, πήρα λέξη προς λέξη αυτή τη λίστα και την πέρασα στη βάση γνώσης της γλώσσας Prolog. Συγκεκριμένα χρησιμοποίησα τον μεταγλωττιστή SWI Prolog, ο οποίος έχει πολύ καλή τεκμηρίωση και είναι ως εκ τούτου αρκετά δημοφιλής.
 Η κάθε μία λέξη δηλώθηκε χωριστά μέσω του κατηγορήματος word/1 ως εξής :

word(abandon).
word(ability).
word(able).
word(about).
word(above).

.....

Έτσι περάστηκαν στη βάση γνώσης της Prolog και οι 3.000 περίπου λέξεις. Ύστερα προσπάθησα να σκεφτώ αν με αυτό το δείγμα λέξεων που είναι αρκετά μεγάλο, μπορεί να φτιαχτεί κάτι χρήσιμο, κάποιο απλό παιχνίδι ας πούμε. Έτσι άρχισα να υλοποιώ διάφορα κατηγορήματα...

append([],L,L).
append([H|T],L,[H|Q]) :- append(T,L,Q).
reversed_list([],[]).
reversed_list([H|T],R) :- reversed_list(T,Tmp),append(Tmp,[H],R).
count_elements([],0) :- !.
count_elements([H],1) :- !.
count_elements([H|T],N) :- count_elements(T,Tmp), N is Tmp + 1, !.
element_at([H|T],0,X) :- false.
element_at([],N,X) :- false.
element_at([H|T],1,H).
element_at([H|T],N,X) :- Q is N-1, element_at(T,Q,X), !.
check_palindrome(X) :- word(X), name(X,L), reversed_list(L,L).
all_palindromes :- word(X), term_to_atom(X,K),check_palindrome(K),write(K),nl, fail.
all_palindromes :- !.
meaningful_backwards(X) :- word(X), term_to_atom(X,K),not(check_palindrome(K)),name(K,L),
                           reversed_list(L,L2), name(NW,L2),word(NW).
all_meaningful_backwards :- meaningful_backwards(Q),write(Q),nl,fail.
all_meaningful_backwards :- !.
word_length(W,N) :- word(W),term_to_atom(W,K),name(K,L),count_elements(L,N).
all_certain_length(W,N) :- word_length(W,N),write(W),nl,fail.
all_certain_length(W,N) :- !.
contains(W,X) :- word(W),term_to_atom(W,W),name(W,L),char_code(X,M),member(M,L), !.
contained_in(L1, L2) :- maplist(included(L2), L1).
included(L, X) :- member(X, L).
hangman_aux(Ln,[H|T],W) :- word(W),word_length(W,Ln),term_to_atom(W,W),atom_chars(W,L1),contained_in([H|T],L1).
hangman(Ln,[H|T],W) :- distinct(hangman_aux(Ln,[H|T],W)).

Τα πρώτα κατηγορήματα είναι βοηθητικά και συμβάλουν όπως βλέπετε στην επεξεργασία λιστών, αφού ένας συνήθης τρόπος επεξεργασίας των αλφαριθμητικών στην Prolog είναι η μετατροπή τους σε λίστες χαρακτήρων. Το ενδιαφέρον αρχίζει λίγο παρακάτω.
 Το κατηγόρημα check_palindrome(X) ελέγχει αν μια λέξη X απ' αυτές που βρίσκονται στη βάση γνώσης είναι παλινδρομική, όπως για παράδειγμα οι λέξεις refer, level, mom, dad.
Το κατηγόρημα all_palindromes εμφανίζει όλες τις λέξεις της βάσης γνώσης που έχουν αυτή την ιδιότητα.
Επίσης υπάρχει και το κατηγόρημα meaningful_backwards(X) που ελέγχει αν μια μη παλινδρομική λέξη X βγάζει νόημα αν διαβαστεί ανάποδα. Τέτοιες λέξεις είναι για παράδειγμα το ρήμα flow και το ουσιαστικό wolf.  Ομοίως για τις λέξεις peek και keep.
Το κατηγόρημα all_meaningful_backwards εμφανίζει όλες τις γνωστές στο πρόγραμμα λέξεις που έχουν αυτή την ιδιότητα.
 Τελευταίο έγραψα ένα κατηγόρημα που το ονομάζω hangman ώστε να βοηθάει αν κάποιος παίξει κρεμάλα με αυτό το δείγμα λέξεων.
 Το κατηγόρημα hangman δέχεται δύο ορίσματα εισόδου και ένα όρισμα εξόδου. Τα ορίσματα εισόδου είναι πρώτον το μήκος της ζητούμενης λέξης και δεύτερον μια λίστα με γράμματα. Το όρισμα εξόδου είναι μια τυχαία μεταβλητή.
 Αν δώσω δηλαδή hangman(5,[a,b,t],W). αυτό σημαίνει «να ευρεθούν όλες οι λέξεις που αποτελούνται από πέντε γράμματα και περιλαμβάνουν τα γράμματα a,b και t. Η παράμετρος W είναι ουσιαστικά ένα όνομα συνόλου, στο οποίο τοποθετούνται οι λέξεις που θα ευρεθούν.
Το πρόγραμμα απαντάει W = { about, habit, table }.
 Δυστυχώς δεν ξέρω κάποιον μεταγλωττιστή της Prolog που να μπορεί να παράγει απ' ευθείας εκτελέσιμα αρχεία. Άρα για να δοκιμάσετε το πρόγραμμα θα πρέπει να έχετε ήδη εγκατεστημένο τον μεταγλωττιστή στον υπολογιστή σας.
Επίσης οι προτάσεις και τα ερωτήματα της Prolog τελειώνουν πάντα με τελεία, άρα για να τρέξει ας πούμε το all_meaningful_backwards πρέπει στο command prompt της γλώσσας να γράψετε :

?-  all_meaningful_backwards.

Η για παράδειγμα ....

?-  hangman(5,[a,b,t],W).

 Εκείνο που με στενοχωρεί είναι ότι δεν έχω ένα αρκετά μεγάλο δείγμα λέξεων σε ηλεκτρονική μορφή (κατά προτίμηση απλό αρχείο κειμένου του notepad) ώστε να το περάσω όλο μαζί μέσα στη βάση γνώσης της Prolog και να φτιαχτεί κάτι λίγο πιο ενδιαφέρον.
 Επίσης θα ήθελα να γνωρίσω άλλα μέλη του Insomnia που αγαπούν την Prolog ώστε όποιος έχει όρεξη να μου βελτιώσει λίγο τον κώδικα αν μπορεί.
Αυτό τον καιρό ξαναδιαβάζω φανατικά Prolog και ανακαλύπτω σιγά-σιγά ότι μου αρέσει, γιατί όπως είδατε και πιο πάνω, με τόσο λίγο κώδικα μπορούν να γίνουν τόσα πολλά πράγματα.
Στο μήνυμά μου αυτό επισυνάπτω το αρχείο WordGame.prolog που τα περιλαμβάνει όλα, δηλαδή τόσο τη βάση γνώσης, όσο και τον κώδικα των κατηγορημάτων.  Για να το φορτώσετε στο μεταγλωττιστή της SWI Prolog απλά γράψτε swipl WordGame.prolog στη γραμμή εντολών.
Αν με τα όσα έγραψα παραπάνω παρακινήσω έστω κι έναν από εσάς που δεν γνωρίζει Prolog να ασχοληθεί έστω λίγο μ' αυτή την τόσο ιδιαίτερη γλώσσα θα είμαι ευτυχής γιατί θεωρώ ότι έχει τεράστια δυναμική.

Να είστε όλοι καλά, σας ευχαριστώ πολύ !!!

Ο Άσπρος Γάτος

 

WordGame.prolog

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

δες εδώ για μια λίστα λέξεων:

https://web.archive.org/web/20180611003215/http://www.puzzlers.org/pub/wordlists/unixdict.txt

επίσης υπάρχει και τεράστιο αρχείο εδώ:

https://github.com/dwyl/english-words

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...