Просмотр исходного кода

WIP: report part 3

tags/v1.0b1
Christos Choutouridis 4 лет назад
Родитель
Сommit
ebced2aa74
6 измененных файлов: 123 добавлений и 43 удалений
  1. Двоичные данные
      report/images/Graph.png
  2. Двоичные данные
      report/images/graph.png
  3. Двоичные данные
      report/report.pdf
  4. +102
    -33
      report/report.tex
  5. +16
    -7
      src/host/labyrinth/Board.java
  6. +5
    -3
      src/host/labyrinth/Common.java

Двоичные данные
report/images/Graph.png Просмотреть файл

До После
Ширина: 3686  |  Высота: 1665  |  Размер: 226 KiB

Двоичные данные
report/images/graph.png Просмотреть файл

До После
Ширина: 3686  |  Высота: 1957  |  Размер: 263 KiB

Двоичные данные
report/report.pdf Просмотреть файл


+ 102
- 33
report/report.tex Просмотреть файл

@@ -37,14 +37,14 @@
Στο συγκεκριμένο παιχνίδι καλούμαστε να δημιουργήσουμε ένα λαβύρινθο μέσα στον οποίο κινούνται με τυχαίο τρόπο δύο παίχτες, ο Θησέας και ο Μινώταυρος.
Στόχος του Μινώταυρου είναι να “πιάσει” τον Θησέα και στόχος του Θησέα είναι να βρει όλα τα εφόδια που είναι τυχαία κατανεμημένα στο ταμπλό πριν ξημερώσει και πριν τον πιάσει ο Μινώταυρος.
Στο παιχνίδι αυτό υπάρχουν δύο βασικά προβλήματα τα οποία χρειάζεται να λύσουμε.
Το πρόβλημα τις δημιουργίας του λαβύρινθου και το πρόβλημα της λειτουργίας του παιχνιδιού.
Το πρόβλημα της δημιουργίας του λαβύρινθου και το πρόβλημα της λειτουργίας των παιχτών και του υπόλοιπου παιχνιδιού.

\par Κατά την άποψή μας η δημιουργία του ταμπλό είναι το κυριότερο από τα δύο προβλήματα.
Το ταμπλό αποτελείται από πλακίδια και τοίχους.
Τα πλακίδια είναι διατεταγμένα σε τετραγωνικό σχήμα και ανάμεσά τους τοποθετούνται οι τοίχοι.
Το πρόβλημα έγκειται στην επιλογή και τοποθέτηση τοίχων με τέτοιο τρόπο ώστε να πληρούνται οι προδιαγραφές του παιχνιδιού όπως πχ κάθε πλακίδιο να μπορεί να έχει το πολύ δύο τοίχους ή τα εξωτερικά πλακίδια να έχουν τοίχο από την έξω μεριά.
Μετά από μια πιο λεπτομερή ανάλυση του προβλήματος, διαπιστώσαμε πως οι δοθείσες προδιαγραφές δεν αποτρέπουν τη δημιουργία κλειστών δωματίων, κάτι που θεωρήσαμε άδικο, με αποτέλεσμα, όπως περιγράφουμε και αναλυτικά παρακάτω, \textbf{να προσθέσουμε έναν ακόμη περιορισμό.
Την αποτροπή κλειστών δωματίων στο ταμπλό.}
Μετά από μια πιο λεπτομερή ανάλυση του προβλήματος, διαπιστώσαμε πως οι δοθείσες προδιαγραφές δεν αποτρέπουν τη δημιουργία κλειστών δωματίων, κάτι που θεωρήσαμε άδικο, με αποτέλεσμα, όπως περιγράφουμε και αναλυτικά παρακάτω, \textbf{να προσθέσουμε έναν ακόμη περιορισμό}.
\textbf{Την αποτροπή κλειστών δωματίων στο ταμπλό}.

\par Το πρόβλημα της λειτουργίας του υπόλοιπου παιχνιδιού έχει να κάνει με τη δημιουργία των παιχτών καθώς και τις κινήσεις τους.
Οι προδιαγραφές αφορούν περιορισμούς στην κίνηση των παιχτών και τον τρόπο με τον οποίο λειτουργεί το παιχνίδι.
@@ -55,55 +55,51 @@
Τα επισυναπτόμενα παραδοτέα αποτελούνται από:
\begin{itemize}
\item Τον \eng{\textbf{root}}κατάλογο στον οποίο υπάρχει και το \eng{project}του \eng{eclipse.}
Αυτός ο κατάλογος μπορεί να γίνει \eng{import}στο \eng{eclipse.}

\item Ένας υποκατάλογος \eng{\textbf{src/}}με τον κώδικα της \eng{java,}αποτελούμενο από ένα αριθμό αντικειμένων ενσωματωμένο στο πακέτο \eng{host.labyrinth.}
Αναφορά σε αυτό τον κατάλογο υπάρχει στο \eng{eclipse project.}

\item Ένας υποκατάλογος \eng{\textbf{out/}} που περιέχει το παραγόμενο \eng{command line jar}του παιχνιδιού.

\item Ένας υποκατάλογος \eng{\textbf{doc/}}με την τεκμηρίωση του κώδικα όπως αυτή έχει παραχθεί από τα σχόλια, με το εργαλείο \eng{doxygen.}
Το αρχείο ρυθμίσεων του \eng{doxygen}είναι στον \eng{root} με το όνομα \eng{Doxyfile.}
Η πλοήγηση στην τεκμηρίωση μπορεί να γίνει ανοίγοντας το αρχείο \eng{doc/index.html}

\item Ένας υποκατάλογος \eng{\textbf{report/}} που περιέχει την \textbf{παρούσα αναφορά}.
\end{itemize}
Εκτός από τα επισυναπτόμενα αρχεία διαθέσιμο υπάρχει και το \textbf{\eng{git}αποθετήριο} ολόκληρης της εργασίας \href{https://git.hoo2.net/hoo2/Labyrinth}{εδώ}.
Αυτό περιέχει τόσο τον κώδικα της εφαρμογής όσο και τον κώδικα της αναφοράς.

\section{Υλοποίηση}
Η όλη υλοποίηση έγινε σε \eng{java.}
\section{Σχεδιαστικές επιλογές}
Πριν ασχοληθούμε όμως με τα ζητηθέντα αντικείμενα του προγράμματος, θα πρέπει να αναφερθούμε σε ορισμένες δομές που προστέθηκαν, αλλά και κάποιες σχεδιαστικές επιλογές που έγιναν για να απλοποιήσουν τον κώδικα.

\subsection{\eng{Accessor - mutator idiom}}
Στις προδιαγραφές της εργασίας αφήνεται να εννοηθεί πως ζητείται η χρήση του \eng{\textit{accessor - mutator idiom.}}
Θα πρέπει να παραδεχτούμε όμως, πως \textbf{θεωρούμε το συγκεκριμένο ιδίωμα ιδιαίτερα προβληματικό}.
Ο κύριος λόγος είναι πως παραβιάζει θεμελιακά τις αφαιρέσεις.
Αντ' αυτού \textbf{τα αντικείμενα που υλοποιούνται ως αφαιρέσεις μπορούν να προσφέρουν μεθόδους που εκτελούν κάποια λειτουργία, κρύβοντας τελείως τις εσωτερικές λεπτομέρειες τις υλοποίησης}.
Εν αντιθέτως με το ιδίομα αυτό, \textbf{τα αντικείμενα που υλοποιούνται ως αφαιρέσεις μπορούν να προσφέρουν μεθόδους που εκτελούν κάποια λειτουργία, κρύβοντας τελείως τις εσωτερικές λεπτομέρειες τις υλοποίησης}.
Αυτός είναι και ο δρόμος που διαλέξαμε για το σχεδιασμό του προγράμματος.
Η κάθε τάξη προσφέρει δημόσια ένα αριθμό από μεθόδους που είναι απαραίτητες για την απαιτούμενη λειτουργικότητα της και κρύβει όσο καλύτερα γίνεται την εσωτερική υλοποίηση.
Η κάθε τάξη προσφέρει δημόσια ένα αριθμό από μεθόδους που είναι απαραίτητες για την εκάστοτε απαιτούμενη λειτουργικότητα και κρύβει όσο καλύτερα γίνεται την εσωτερική υλοποίηση.
Ενώ λοιπόν υλοποιήσαμε το ζητηθέν \eng{get-set}ζευγάρι για την κάθε μεταβλητή των τάξεων, δεν το χρησιμοποιήσαμε πουθενά μέσα στο πρόγραμμα.

\subsection{Ενοποιημένο σύστημα συντεταγμένων}
Στις προδιαγραφές της εργασίας περιγράφεται επίσης ένα διπλό σύστημα συντεταγμένων, τόσο για τα πλακίδια όσο και για τα εφόδια.
Ένα καρτεσιανό που διευθυνσιοδοτεί ως προς δύο άξονες και περιέχει ένα ζευγάρι γραμμής και στήλης και ένα μονοδιάστατο που αποτελείται από τον γραμμικό συνδυασμό του καρτεσιανού.
Ένα καρτεσιανό που διευθυνσιοδοτεί ως προς δύο άξονες και περιέχει ένα ζευγάρι γραμμής και στήλης και ένα μονοδιάστατο που αποτελείται από τον γραμμικό συνδυασμό των προηγουμένων.
Το μονοδιάστατο αντικατοπτρίζει και την απεικόνιση στη μνήμη ενός πίνακα 2 διαστάσεων σε \eng{row major order.}

\par Γενικά θεωρούμε ότι κάτι τέτοιο δημιουργεί πλεονασμό δεδομένων και επομένως είναι κακή πρακτική.
Αυτό γιατί μεταξύ άλλων μειονεκτημάτων, που κυρίως αφορά τον πολυνηματικό προγραμματισμό, οδηγεί και σε προγραμματιστικά λάθη που πιθανώς θα αφήνουν τα δύο συστήματα ασυγχρόνιστα.
Για να λύσουμε αυτό το πρόβλημα \textbf{δημιουργήσαμε την τάξη\eng{Position,}}στην οποία εσωτερικά χρησιμοποιούμε μόνο το ένα από τα δύο συστήματα, για την ακρίβεια το μονοδιάστατο και ταυτόχρονα παρέχουμε μεθόδους για την πρόσβαση στη θέση και από τα δύο συστήματα.
Η τάξη μεταξύ άλλων προσφέρει και \textbf{στατικές μεθόδους για τις μετατροπές} προσφέροντας έτσι μια είδους εργαλειοθήκη για την εφαρμογή.
Έτσι χρησιμοποιήσαμε την \eng{Position}όπου ήταν δυνατό μέσα στον κώδικα.
Για την παρούσα εργασία χρησιμοποιήσαμε την \eng{Position}όπου ήταν δυνατό.

\section{Αναβάθμιση της τάξης\eng{Tile}}
\subsection{Αναβάθμιση της τάξης\eng{Tile}}
Κατά τον προγραμματισμό του παιχνιδιού παρατηρήσαμε πως τόσο η τάξη\eng{Tile}όσο και η\eng{Supply}έχουν πληροφορίες για τη θέση τους στο ταμπλό.
Αυτό σημαίνει πως και τα πλακίδια όσο και τα εφόδια ανήκουν στο ταμπλό.
Κάτι τέτοιο γίνεται αντιληπτό ακόμα και από τις προδιαγραφές της\eng{Board}η οποία είναι αυτή που περιέχει τους πίνακες αναφορών τόσο των πλακιδίων όσο και των εφοδίων.
Μια ποιο διαισθητική προσέγγιση βέβαια θα ήθελε τα εφόδια να ανήκουν στα πλακάκια και όχι στο ταμπλό.
Αυτό σημαίνει πως τόσο τα πλακίδια όσο και τα εφόδια ανήκουν στο ταμπλό.
Ακόμα σημαίνει πως δημιουργούν επιπλέον πλεονασμό σε δεδομένα, καθώς απαιτούνται οι συντεταγμένες των εφοδίων μέσα στην\eng{Supply.}
Κάτι τέτοιο γίνεται αντιληπτό και από τις προδιαγραφές της\eng{Board}η οποία είναι αυτή που περιέχει τους πίνακες αναφορών τόσο των πλακιδίων όσο και των εφοδίων.
\textbf{Μια ποιο διαισθητική προσέγγιση βέβαια θα ήθελε τα εφόδια να ανήκουν στα πλακίδια} και όχι στο ταμπλό.
Με αυτό τον τρόπο η τάξη\eng{Supply} δεν θα είχε πληροφορίες θέσης, αλλά αντίθετα η τάξη\eng{Tile}θα είχε επιπρόσθετη πληροφορία για το αν υπάρχει εφόδιο ή όχι.

\par Όπως είναι φυσικό θελήσαμε να υλοποιήσουμε αυτή την αίσθηση.
\par Όπως είναι φυσικό θελήσαμε να υλοποιήσουμε αυτή την προσέγγιση.
Αν όμως μετακινούσαμε τις αναφορές των εφοδίων στην\eng{Tile}θα αλλοιώναμε τις προδιαγραφές της εκφώνησης.
Έτσι επιλέξαμε μια μέση οδό.
Επομένως επιλέξαμε μια μέση οδό.
Εμπλουτίσαμε την\eng{Tile}με μεθόδους που αφορούν τα εφόδια.
Αυτές είναι οι:
\begin{itemize}
@@ -120,53 +116,126 @@
Η δημιουργία της\eng{Board}αποτέλεσε τον μεγαλύτερο όγκο του κώδικα της παρούσας εργασίας.
Για να κάνουμε τον κώδικα καθαρότερο αλλά και ευκολότερο στην κατανόηση επινοήσαμε κάποια\eng{\textbf{concepts}.}
Η ιδέα των\eng{concepts}προέρχεται από την\eng{C++}όπου τα\eng{concepts}είναι ένα είδους \eng{compile time predicate}και εφαρμόζεται στους τύπους δεδομένων.
Εμείς για την εργασία υλοποιήσαμε κάποια\eng{concepts} σε μορφή\eng{predicate.}
Εμείς για την εργασία υλοποιήσαμε κάποια\eng{concepts} σε μορφή συναρτήσεων κατά την εκτέλεση του προγράμματος.
Τα\eng{concepts}αυτά αφορούν έννοιες σχετικές με την εφαρμογή και έχουν την μορφή\eng{predicate.}
Μας δίνεται έτσι η δυνατότητα να ελέγχουμε αν κάποια είσοδός ενός \eng{concept}πληροί τις προδιαγραφές του ή όχι.
Στο σχήμα \ref{fig:concepts} φαίνεται μια οπτικοποιημένη έκδοση τους.

\subsection{\eng{Sentinel tile}}
\subsection{Πλακίδιο φρουρός - \textit{\eng{isSentinel()}}}
\WrapFigure{0.5}{r}{fig:concepts}{images/concepts.png}{Οπτική αναπαράσταση των\eng{concepts}που χρησιμοποιούμε σε ένα ταμπλό $7x7$}
Πρόκειται για\eng{concept}που μας επιτρέπει να ελέγξουμε αν το πλακίδιο είναι \textbf{“πλακίδιο φρουρός”}.
Αν δηλαδή βρίσκεται στα εξωτερικά άκρα του ταμπλό.
Η υλοποίηση αυτού του\eng{concept}γίνεται μέσω τεσσάρων συναρτήσεων που ελέγχουν χωριστά τις τέσσερεις διευθύνσεις του ταμπλό.

\par Για την παράδειγμα η \eng{\textit{boolean isLeftSentinel (int tileId)}}μας δίνει την δυνατότητα να ελέγξουμε αν το πλακίδιο είναι “πλακίδιο φρουρού” αριστερά του ταμπλό.
Αυτό είναι χρήσιμο για λειτουργίες όπως για παράδειγμα αν θέλουμε να δούμε μήπως χρειάζεται να τοποθετηθεί τοίχος αριστερά του πλακιδίου.
Αντίστοιχα υπάρχουν και οι υπόλοιπες συναρτήσεις για τις υπόλοιπες διευθύνσεις.

\subsection{\eng{Walkable direction}}
\subsection{Διασχίσιμη διεύθυνση - \textit{\eng{isWalkable()}}}
Πρόκειται για\eng{predicate}που μας επιτρέπει να ελέγξουμε αν μια διεύθυνση σε κάποιο πλακίδιο είναι \textbf{“διασχίσημη”}.
Αν δηλαδή κάποιος παίκτης μπορεί να κινηθεί σε αυτή.
Για να ισχύει κάτι τέτοιο θα πρέπει:
\begin{itemize}
\item Η διεύθυνση να μην έχει τοίχο.
\item Η διεύθυνση να μην είναι η “Κάτω” διεύθυνση του πλακιδίου εισόδου στο λαβύρινθο.
\end{itemize}

\subsection{\eng{Wallable direction}}
\subsection{Χτίσιμη διεύθυνση - \textit{\eng{isWallableDir()}}}
Πρόκειται για\eng{predicate}που μας επιτρέπει να ελέγξουμε αν μια διεύθυνση κάποιου πλακιδίου είναι \textbf{”χτίσιμη”}.
Αυτό το\eng{concept}είναι πολύ χρήσιμο κατά τη δημιουργία των τοίχων.
Αν δηλαδή μπορούμε να τοποθετήσουμε τοίχο στη διεύθυνση αυτή.
Για να είναι μια διεύθυνση χτίσιμη θα πρέπει:
\begin{itemize}
\item Η διεύθυνση να μην έχει τοίχο.
\item Η διεύθυνση να μην είναι η “Κάτω” διεύθυνση του πλακιδίου εισόδου στο λαβύρινθο.
\item Η διεύθυνση να είναι “διασχίσιμη”.
\item Το γειτονικό πλακίδιο σε αυτή τη διεύθυνση να μην περιέχει ήδη τον μέγιστο αριθμό πλακιδίων.
\item Ο τοίχος να μην δημιουργεί κάποιο κλειστό δωμάτιο.\\
Αυτή η απαίτηση δεν υπάρχει στις προδιαγραφές και την παίρνουμε υπόψιν μόνο αν ο χρήστης την έχει ζητήσει από την γραμμή εντολών.
Αυτή η τελευταία \textbf{η απαίτηση δεν υπάρχει στις προδιαγραφές} και την παίρνουμε υπόψιν μόνο αν ο χρήστης την έχει ζητήσει από την γραμμή εντολών.
Ο λόγος είναι γιατί ο υπολογισμός της κοστίζει και αυτό μπορεί να μην παίζει ρόλο για ταμπλό μεγέθους $15x15$, αλλά αν ζητηθεί κάποιο πολύ μεγαλύτερο τότε ο χρόνος είναι υπολογίσιμος.
Φυσικά στον κώδικα κάνουμε χρήση αυτού του \eng{concept}μόνο κατά τη δημιουργία του ταμπλό.
Φυσικά στον κώδικα κάνουμε χρήση αυτού του \eng{concept}μόνο κατά τη δημιουργία του ταμπλό, με αποτέλεσμα να μην επιβαρύνεται καθόλου η λειτουργία του προγράμματος κατά τη διάρκεια του παιχνιδιού.
Αναφερόμαστε αναλυτικά σε αυτό τον αλγόριθμο στην ενότητα \ref{sec:isRoomCreator}
\end{itemize}

\subsection{\eng{Wallable tile}}
\subsection{Χτίσιμο πλακίδιο - \textit{\eng{isWallable()}}}
Πρόκειται για\eng{predicate}που μας επιτρέπει να ελέγξουμε αν κάποιο πλακιδίο είναι \textbf{”χτίσιμo”}.
Αν δηλαδή μπορούμε σε κάποια πλευρά του πλακιδίου να τοποθετήσουμε τοίχο.
Για να ισχύει αυτό θα πρέπει:
\begin{itemize}
\item Το πλακίδιο να μην έχει ήδη τον μέγιστο αριθμό τοίχων.
\item Να υπάρχει τουλάχιστον μία “χτίσιμη” διεύθυνση στο πλακίδιο.
\end{itemize}

\subsection{Εύρεση κλειστών δωματίων}
Όπως αναφέραμε και παραπάνω οι προδιαγραφές της εργασίας δεν αποτρέπουν τη δημιουργία κλειστών δωματίων, κάτι που θεωρήσαμε άδικο.
\subsection{Δημιουργός κλειστού δωματίου - \textit{\eng{isRoomCreator()}}} \label{sec:isRoomCreator}
Όπως αναφέραμε και παραπάνω οι προδιαγραφές της εργασίας δεν αποτρέπουν τη δημιουργία κλειστών δωματίων.
Για το λόγο αυτό υλοποιήσαμε ένα αλγόριθμο που ανιχνεύει την πιθανότητα δημιουργίας κλειστών δωματίων του οποίου η ενεργοποίηση γίνεται κατόπιν επιλογής του χρήστη από τη γραμμή εντολών.

\InsertFigure{0.6}{fig:graph}{images/graph.png}{Γράφος.}
\par Ένας αλγόριθμος για να είναι λειτουργικός χρειάζεται δεδομένα.
Στη δική μας περίπτωση τα δεδομένα είναι οι τοίχοι.
Θέλαμε λοιπόν ένα τρόπο αναπαράστασης των τοίχων που να βολεύει για το συγκεκριμένο πρόβλημα.
Η λύση που χρησιμοποιήσαμε συνοψίζεται στα εξής:
\begin{itemize}
\item Οι διασταυρώσεις ανάμεσα στα πλακίδια ονομάζονται κόμβοι και η θέση τους αναπαρίστανται μονοδιάστατα σαν διεύθυνση σε\eng{row majer order.}
\item Ο κάθε κόμβος αποτελεί τον κόμβο-γωνία\eng{(vertex)}ενός γράφου.
\item Ο κάθε τοίχος αναπαρίσταται ως ακμή στον γράφο.
\end{itemize}
Για παράδειγμα ένας τοίχος αριστερά του πλακιδίου `0` αναπαρίσταται ως η ακμή `(0,4)`,
Στο σχήμα \ref{fig:graph} φαίνεται ένα παράδειγμα αναπαράστασης.
\InsertFigure{0.6}{fig:graph}{images/graph.png}{
\\(α) Διευθυνσιοδότηση πλακιδίων(τετραγωνάκια) και κόμβων(σφαίρες) ενός ταμπλό $3x3$.\\
(β) Ένας συνεκτικός γράφος που προκύπτει από το (α) ξεκινώντας από τον τοίχο (7, 11).
}

\par Για τον αλγόριθμο υλοποιήσαμε δύο αντικείμενα.
Το\eng{\textbf{Edge}}που δημιουργεί ζευγάρια κόμβων ώστε να μπορεί να αποθηκεύσει τον κάθε τοίχο(ακμή) και το\eng{\textbf{Graph}}που προσφέρει λειτουργίες δημιουργίας συνεκτικού γράφου λαμβάνοντας ως είσοδο τοίχους(ακμές).

\par Η λειτουργία του είναι απλή.
Κάθε φορά που ελέγχουμε αν μία διεύθυνση πλακιδίου είναι χτίσιμη, \textbf{δημιουργούμε το μεγαλύτερο δυνατό συνεκτικό γράφο που περιέχει τον εν λόγο τοίχο} και όλους τους ήδη τοποθετημένους τοίχους.
Αν στον γράφο που προκύπτει υπάρχει κάποιος κόμβος περισσότερες από μία φορές, δηλαδή ο γράφος δεν είναι απλός, τότε αυτό σημαίνει πως στον εν λόγο κόμβο μπορούμε να πάμε ακολουθώντας κάποιο τοίχο από τουλάχιστον δύο κατευθύνσεις.
Άρα το ταμπλό περιέχει κάποιο κλειστό δωμάτιο.
Αφού τον αλγόριθμο τον εκτελούμε για κάθε πιθανή χτίσιμη διεύθυνση, τότε ο τοίχος που προκαλεί το κλειστό δωμάτιο είναι αυτός που ελέγχουμε την εκάστοτε στιγμή.

\par Για την λειτουργία του αλγόριθμου χρειαζόμαστε όλους τους τοίχους που είναι ήδη τοποθετημένοι στο ταμπλό στη μορφή\eng{Edge.}
Γιαυτό προσθέσαμε στην τάξη \eng{Board} μια λίστα αναφορών\eng{(ArrayList)} και σε αυτήν αποθηκεύουμε κάθε τοίχο που δημιουργούμε.
Τον αλγόριθμο μπορούμε να τον ενεργοποιήσουμε αν περάσουμε στο πρόγραμμα ως επιλογή το όρισμα\eng{\texttt{-{}-norooms}} από τη γραμμή εντολών.

\par Δυστυχώς η κωδικοποίηση που χρησιμοποιούμε εδώ δεν ταιριάζει με αυτή της υπόλοιπης εφαρμογής.
Αυτό έχει σαν αποτέλεσμα να πρέπει να δημιουργούμε τον γράφο κάθε φορά.
Αυτό έχει κόστος σε χρόνο.
Για την ακρίβεια $O(N^{2}logN)$, όπου $Ν$, ο συνολικός αριθμός πλακιδίων του ταμπλό.
Αυτό το κόστος αφορά τον έλεγχο του κάθε πλακιδίου.
Για όλο το ταμπλό το κόστος είναι $O(N^{4}logN)$.
Φυσικά θα μπορούσαμε να χρησιμοποιήσουμε υπομνηματισμό και να αποθηκεύουμε τους γράφους
Όμως λόγο του ότι η επιβάρυνση λαμβάνει χώρα μόνο μία φορά κατά την εκκίνηση, σε συνδυασμό με το μικρό μέγεθος του ταμπλό, αποφασίσαμε να μην προχωρήσουμε σε περαιτέρω βελτιστοποίηση.

\section{Υλοποίηση}
Για την δημιουργία της εφαρμογής, εκτός από τα ζητηθέντα αντικείμενα υλοποιήσαμε και τα παρακάτω.
\begin{itemize}
\item \eng{\textbf{Const}}\\
Το αντικείμενο αυτό περιέχει σταθερές για όλη την εφαρμογή.
\item \eng{\textbf{Session}}\\
Το αντικείμενο αυτό περιέχει όλες τις τιμές της εφαρμογής που αποτελούν επιλογές, όπως πχ το μέγεθος του ταμπλό, τον αριθμό των εφοδίων κτλ.
\item \eng{\textbf{Direction}}\\
Το αντικείμενο αυτό λειτουργεί σαν \eng{C++ enumerator}και παρέχει ονοματολογία στις διευθύνσεις που χρησιμοποιούμε στην εφαρμογή.
\item \eng{\textbf{DirRange}}\\
Ομοίως ένα βοηθητικό αντικείμενο αυτή τη φορά για την δημιουργία σε βρόχους επανάληψης.
\item \eng{\textbf{Edge}}\\
Το αντικείμενο αυτό όπως είδαμε και στην ενότητα \ref{sec:isRoomCreator}, λειτουργεί ως αναπαράσταση των τοίχων με τη μορφή ακμών ενός γράφου.
Προσφέρει \eng{constructor} που δέχεται για ορίσματα συντεταγμένες από πλακίδια και διευθύνσεις.
Με αυτό τον τρόπο λειτουργεί ως διεπαφή ανάμεσα στην κωδικοποίηση που χρησιμοποιείται στην υπόλοιπη εφαρμογή και στην κωδικοποίηση που χρησιμοποιείται για την εύρεση κλειστών δωματίων.
\item \eng{\textbf{Graph}}\\
Το αντικείμενο αυτό υλοποιεί λειτουργίες ενός συνεκτικού γράφου.
Ο \eng{constructor}της τάξης δέχεται ως όρισμα μια ακμή και στην ουσία δημιουργεί τους 2 πρώτους κόμβους.
Οι βασικές λειτουργίες είναι η \eng{\textit{attach()}}η οποία δέχεται μια ακμή και αν κάποιος κόμβος της ακμής ανήκει ήδη στο γράφο τότε τοποθετεί και τον άλλο.
Και η \eng{\textit{count()}}η οποία δέχεται ένα κόμβο και μετράει πόσες φορές ο κόμβος αυτός περιέχεται στον γράφο.
\item \eng{\textbf{Position}}\\
Το αντικείμενο αυτό χρησιμοποιείται για να παρέχει ένα ενοποιημένο σύστημα συντεταγμένων για όλη την εφαρμογή.
\item \eng{\textbf{Range}}\\
Το αντικείμενο χρησιμοποιείται για να δημιουργεί εύρη τιμών.
\item \eng{\textbf{ShuffledRange}}\\
Το αντικείμενο αυτό χρησιμοποιείται για να δημιουργεί “τυχαίως ανακατεμένα” εύρη τιμών.
\end{itemize}

\section{Εκτελέσιμο}

\section{Συμπεράσματα και παρατηρήσεις}

% References
% ============================


+ 16
- 7
src/host/labyrinth/Board.java Просмотреть файл

@@ -134,6 +134,12 @@ class Board {

/**
* Predicate to check if a direction is Walkable.
*
* A `walkable` direction is a tile direction where:
* <ul>
* <li>The wall is not the DOWN wall from tile (0, 0).
* <li>There is not already a wall in the desired direction. (Implies no sentinel tile).
* </ul>
*
* @param tileId The starting tileId.
* @param direction The desired direction.
@@ -147,6 +153,12 @@ class Board {
/**
* Predicate to check if a direction is Walkable.
*
* A `walkable` direction is a tile direction where:
* <ul>
* <li>The wall is not the DOWN wall from tile (0, 0).
* <li>There is not already a wall in the desired direction. (Implies no sentinel tile).
* </ul>
*
* @param row Row position of the starting tile.
* @param col Column position of the starting tile.
* @param direction The desired direction.
@@ -296,13 +308,12 @@ class Board {
* @param direction The wall's relative direction.
* @return True if the wall creates a closed room, false otherwise.
*/
private boolean makesClosedRoom (int tileId, int direction) {
private boolean isRoomCreator (int tileId, int direction) {
// Clone the list of all the walls locally.
ArrayList<Edge> w = new ArrayList<Edge>();
for (Edge it : walls)
w.add(new Edge(it));
// Create a graph from the current wall(edge)
// and populate the graph with all the edges we can attach.
// Create the largest possible coherent graph from the list of walls(edges)
Graph g = new Graph(new Edge(tileId, direction));
int size;
do {
@@ -344,9 +355,7 @@ class Board {
*/
private boolean isWallableDir (int tileId, int direction) {
// Check list
if (tileId == 0 && direction == Direction.DOWN)
return false;
if (tiles[tileId].hasWall(direction))
if (!isWalkable(tileId, direction))
return false;
switch (direction) {
case Direction.UP:
@@ -362,7 +371,7 @@ class Board {
if (tiles[rightTileId.apply(tileId)].hasWalls() >= Const.maxTileWalls) return false;
break;
}
if (Session.loopGuard && makesClosedRoom(tileId, direction))
if (Session.loopGuard && isRoomCreator(tileId, direction))
return false;
return true;
}


+ 5
- 3
src/host/labyrinth/Common.java Просмотреть файл

@@ -309,10 +309,12 @@ class Edge {
* its easy to find any closed loops. Using graph we transform the problem
* of the closed room into the problem of finding a non simple graph.
*
* If the board has non connected wall structure then we would need more than
* one graph to represent it.
* If the board has non connected wall structure then we would need a non
* coherent graph to represent it. This class provides constroctors and
* methods to create coherent graphs
*
* An example graph we can create from the board bellow, starting from V=1 is:
* An example of the biggest coherent graph we can create from the board bellow,
* starting from V=1 is:
* <pre>
* 6---7 8 (1)
* | | / \


Загрузка…
Отмена
Сохранить