Πέμπτη 31 Δεκεμβρίου 2015

Τα πρώτα προγράμματα (Μ2000)

Πολλές φορές οι αναρτήσεις εδώ είναι δύσκολες, για τον απλό προγραμματιστή. Για το λόγο αυτό θα βάλω σποραδικά μερικές αναρτήσεις με απλά προγράμματα, και μάλιστα ξεκινώντας από εκείνα τα βήματα που θυμίζουν μια παλιά Basic.

Το παρακάτω πρόγραμμα χρησιμοποιεί μόνο ένα μπλοκ εντολών για να συγκρατήσει το λάθος που κανονικά σταματάει τον διερμηνευτεί, να πατήσουμε Enter χωρίς να δώσουμε τιμή στην μεταβλητή χ.

Ένας εύκολος τρόπος να παρακολουθήσει κανείς το πρόγραμμα είναι με την χρήση ετικετών. Και αυτό κάνουμε εδώ.

Ανοίγουμε το περιβάλλον της γλώσσας (m2000.exe). Αν θέλουμε να φύγει η χωριστή οθόνη (που κρατάει τις πάνω γραμμές σταθερές)  γράφουμε Οθόνη ,0  (η πρώτη παράμετρος που λείπει είναι το χρώμα φόντου, το αφήνουμε ως έχει)
Μετά γράφουμε Σ Α πατάμε enter και ανοίγει ο διορθωτής. Κάνουμε αντιγραφή και ή πατάμε Esc ή κάνουμε κλικ στη γραμμή πληροφοριών του διορθωτή και ανοίγει το μενού (και από εκεί διαλέγουμε το έξοδος, δείτε και τι άλλες επιλογές υπάρχουν - είναι και παρακάτω άλλες που δεν φαίνονται στην αρχή)
>Οθόνη ,0
>Σ Α

Χ[1-2, 0 έξοδος]=_

Μπορούμε να δώσουμε και αυτό:
>Δοκιμή Α
Οπότε ανοίγει η φόρμα διαλόγου όπου κάνουμε εκτέλεση εντολή προς εντολή ή με αργό ρυθμό. Αυτή η φόρμα δείχνει αριστερά σε τρία πεδία, το τμήμα, μετά την εντολή και μετά τη παράμετρο. Και τα τρία πεδία είναι κουμπιά που το πρώτο δείχνει το κώδικα του τμήματος ως βοήθεια, το δεύτερο δείχνει την βοήθεια της εντολής (αν την έχει), και το τρίτο δείχνει στο μεσαίο πεδίο το κώδικα που εκτελείται με χρώμα και σημειωμένη την εντολή. Ειδικά το τρίτο κάνει εναλλαγή μεταξύ κώδικα που τρέχει και σωρού - μεταβλητών. Στο κάτω πεδίο που λέει Τύπωσε γράφουμε π.χ. α, β, χ και βλέπουμε τις τιμές σε κάθε νέα εκτέλεση εντολής.



Καθαρό α, β , χ
πρώτο:
      Δες { \\ αν δεν δώσουμε τιμή βγαίνει λάθος και το κόβουμε με την Δες
            χ=0
            Εισαγωγή "Χ[1-2, 0 έξοδος]=", χ
      }
      Από χ Προς α0,α0
      Έξοδος
α0:
      Για β=1 έως 10
            Από χ Διαμέσου α1, α2
            Τύπωσε α
      Επόμενο β
      Προς πρώτο
      Τελος
α1:
      α=β
      επιστροφή
α2:
      α=β**2+10
      επιστροφή

Τμήματα ή Ρουτίνες. Η διαφορά στη Μ2000

Ανέβηκε και η αναθεώρηση 132. (διορθώνει μερικά bug μόνο, που δεν θα αναφερθούν εδώ)

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

Οι τρεις εκδόσεις του πιάνου (η 2η έκδοση παρουσιάστηκε και αντικαταστάθηκε με την 3η), παραμένουν σε αναρτήσεις εδώ για να παρατηρήσουμε πως ένα πρόγραμμα μεγαλώνει, με την ευκολία των ρουτινών.

Οι ρουτίνες βοηθούν στην επέκταση των προγραμμάτων. Αυτό συμβαίνει γιατί πρακτικά οι ρουτίνες είναι μέρη του τμήματος που βρίσκονται, και βλέπουν ότι ακριβώς και το τμήμα. Αν γράψουμε τη ρουτίνα ως ξεχωριστό πρόγραμμα (τμήμα) τότε μπορούμε να την μεταφέρουμε σε άλλο τμήμα και να την "δέσουμε" κατάλληλα. Μάλιστα στο παράδειγμα με το πιανάκι 004 έχουμε βάλει μεταβλητές που χρειάζονται μια φορά να υπολογιστούν πριν τον ορισμό της ρουτίνας.

Λίγα λόγια για την Ρουτίνα
Μπορούμε να έχουμε παραμέτρους ή όχι, αλλά παρενθέσεις θα βάλουμε (αλλιώς έχουμε άλλου τύπου ρουτίνας, τη κλήση σε ετικέτα και χρήση της Επιστροφής, όμως αυτές θα τις δούμε σε άλλη ανάρτηση). Δηλαδή εδώ θα δούμε τον ορισμό:

Ρουτίνα Όνομα1()

Τέλος Ρουτίνας
Η κλήση της ρουτίνας γίνεται με τη Διαμέσου (GOSUB). Επειδή οι ρουτίνες αναζητούνται από το τέλος, τις βάζουμε στο τέλος.

Μάλιστα αν η ροή προγράμματος βρει την λέξη Ρουτίνα τότε θεωρεί ότι έφτασε στο τέλος και τερματίζει το τμήμα!

Που μπαίνουν οι Ρουτίνες;
Οι ρουτίνες δεν βρίσκονται "μόνες" τους κάπου αλλά σε τμήματα. Τμήματα μπορούν να έχουν άλλα τμήματα και ρουτίνες. Η διαφορά βρίσκεται στο ότι οι ρουτίνες βλέπουν ότι έχει το τμήμα που τις καλεί, ενώ το τμήμα στο τμήμα δεν έχει πρόσβαση στο "πατρικό". Τα κοινά που έχουν τμήματα και ρουτίνες είναι ότι βρίσκονται σε τμήματα και έχουν ίδιο σωρό τιμών (ειδική στοίβα της Μ2000). Άρα μπορούμε να καλέσουμε μια ρουτίνα και να πάρουμε (Εφόσον το θέλουμε) μια επιστροφή στον σωρό τιμών (μπορεί στη κορυφή να έχουμε έναν αριθμό που να πληροφορεί πόσα στοιχεία ακολουθούν ή να έχουμε ένα πίνακα, ο σωρός δέχεται και ανίγραφο πίνακα σε ένα στοιχείο).

Οι ρουτίνες είναι "ελαφριές" δομές κώδικα
Αν δει κανείς τον ορισμό της ρουτίνας παραπάνω θα προσέξει ότι δεν έχει μπλοκ.εντολών {} Αυτό σημαίνει ότι χρειάζεται λιγότερους πόρους για να τρέξει (τα μπλοκ είναι μια στρώση ανώνυμου κώδικα και μπορούν να γίνουν δομή επανάληψης). Τα μπλοκ είναι εσωτερικά κλήσεις σε συνάρτηση και τρώνε πόρους από τον Stack του περιβάλλοντος (ο οποίος είναι περιορισμένος, γιατί είναι σε μια μονοκόματη περιοχή). Οι κλήσεις στις ρουτίνες με την ΔΙΑΜΕΣΟΥ γίνονται με στοίβα επιστροφής ανά τμήμα, μια δυναμική λίστα δηλαδή που κάθε στοιχείο της έχει ξεχωριστό χώρο (δεν γράφονται διαδοχικά όπως στο Stack). Προφανώς το Stack είναι πιο γρήγορο για τα τμήματα, αλλά επειδή οι ρουτίνες δεν αλλάζουν το αντικείμενο επεξεργασίας (process object), όπως γίνεται σε κάθε κλήση τμήματος, αλλά συνεχίζουν στο ίδιο αντικείμενο, έχουμε πάλι γρήγορη διαδοχή.

Που βρίσκεται η Ρουτίνα και που το Τμήμα
Μια σημαντική διαφορά ρουτινών και τμημάτων είναι ότι τα τμήματα έχουν τρεις θέσεις σε σχέση με τις ρουτίνες που έχουν δυο: Την θέση στο κώδικα, την θέση που λαμβάνουν στη λίστα τμημάτων (και για το λόγο αυτό ο ορισμός τους πρέπει να περάσει από τη ροή προγράμματος για να μπει στη λίστα), και τέλος το εκτελέσιμο αντίγραφο το οποίο καταναλώνεται σε ένα αντικείμενο επεξεργασίας. Μια ρουτίνα θα κληθεί μόνο μέσα από ένα τμήμα (ή συνάρτηση, και οι συναρτήσεις είναι σαν τα τμήματα, έχουν αντικείμενο επεξεργασίας), με αναζήτηση όχι στο εκτελέσιμο αντίγραφο (αφού αυτό καταναλώνεται...θα εξηγήσω στο τέλος τι σημαίνει κατανάλωση..κώδικα), αλλά στη δεύτερη θέση, στη λίστα τμημάτων. Αν δεν βρεθεί εκεί τότε ο διερμηνευτής πάει στη πρώτη θέση, δηλαδή στη λίστα τμημάτων εγγράφεται η πηγή απ΄όπου φορτώθηκε το τμήμα (αν έγινε η φόρτωση από κώδικα και όχι από το δίσκο). Ο λόγος που γίνεται αυτή η δεύτερη αναζήτηση είναι για λόγους οικονομίας, επειδή διαφορετικά μια ρουτίνα δεν θα μπορούσε να χρησιμοποιηθεί από "αδελφό" τμήμα (στο ίδιο πατρικό) και θα έπρεπε να γραφτεί ξανά!  Ουσιαστικά η ρουτίνα υπάρχει στο κώδικα και έρχεται όποτε θέλουμε με την Διαμέσου στο αντικείμενο εκτέλεσης (άρα σε δυο μέρη)

2023
Στις νεότερες εκδόσεις οι ρουτίνες με τη πρώτη κλήση ανατητούνται στο κώδικα, αλλά από τη δεύτερη και μετά βρίσκονται άμεσα επειδή έχει καταγραφεί η θέση τους. Επίσης εκτός από τις ρουτίνες έχουμε και τις απλές συναρτήσεις.
μ=@Αλφα(5)
Τύπωσε Τύπος$(μ)="Integer", μ=25


Συνάρτηση Αλφα(κ ως ακέραιος)
=κ**2
Τέλος Συνάρτησης


Οι απλές συναρτήσεις καλούνται με το @, δεν μπορούν να έχουν όνομα ίδιο μα αυτών των έτοιμων συναρτήσεων τις Μ2000. Αυτό συμβαίνει γιατί το @ χρησιμοποιείται για να καλέσουμε συναρτήσεις όπως τη @ριζα() όταν έχουμε φτιάξει μια δική μας συνάρτηση ρίζα() (κανονική συνάρτηση, όχι απλή) και δεν θέλουμε να καλέσουμε τη δική μας. Με το @ καλούμε και εντολές όπως τη Τύπωσε:
Στο παρακάτω έχουμε αλλάξει την Τύπωσε με δική μας. Μέσα στο τμήμα τύπωσε, η Τύπωσε είναι η κανονική (θα μπορούσαμε να βάλουμε το @, αν δεν καλέσουμε τη Τύπωσε με την Κάλεσε, η οποία επιτρέπει την αναδρομή στα τμήματα, ενώ με τη κλήση με το κανονικό όνομα δεν είναι θεατή, αλλά είναι θεατή η κανονική Τύπωσε της Μ2000). Στις νέες εκδόσεις αν βάλουμε τη κ ως άτυπο (variant) μπορούμε να διαβάζουμε ή να αλλάζουμε τύπο στη κ όποτε θέλουμε, εδώ η κ θα γίνει μια φορά αριθμός μετά θα γίνει αλφαριθμητικό και μετά πάλι αριθμός. Επίσης γίνεται αυτόματη μετατροπή σε αλφαριθμητικό στη παράσταση "("+κ+")". Αυτά γίνονται στην έκδοση 12.
Τμήμα Τύπωσε {
άτυπος κ // variant
ενώ όχι κενό
διάβασε κ
Τύπωσε "("+κ+") ";
τέλος ενώ
τύπωσε
}


Τύπωσε 1,"αλφα",3
@Τύπωσε 1,"αλφα",3 // κλήση




Επίσης στις νεότερες εκδόσεις ο διερμηνευτής είναι πιο έξυπνος και μπορεί να αντιμετωπίσει ονόματα πινάκων και ρουτινών που είναι ίδια. Αυτό το κάνει γιατί κοιτάει μετά το κλείσιμο της παρένθεσης στα ονόματα που μπορεί να είναι πίνακας ή ρουτίνα αν υπάρχει αλλαγή γραμμής ή άνω και κάτω τελεία (διαχωριστικό εντολής), ή τα σύμβολα '  \ και /, αλλά όχι τα /= και :=  (που είναι τελεστές για τους πίνακες).

πίνακας α(10) ως ακέραιος=20
α(1)++
Τύπωσε α(1)=21
α(α(1))   // 441


Ρουτίνα α(χ ως ακέραιος)
? χ^2
Τέλος ρουτίνας



Σχετικά με το παράδειγμα
Αν το παρακάτω τμήμα λέγεται Α τότε θα φτιάξει την Α.Χ, το τμήμα Α.Κ και θα πάει η ροή στην ρουτίνα όπου το Χ είναι το Α.Χ (επειδή το Α το γνωρίζει το αντικείμενο επεξεργασίας), μετά θα κληθεί η Κ, και εδώ με το τρόπο της κάλεσε όπου το όνομα Κ δεν θα χρησιμοποιηθεί αλλά το Α[1] και θα φτιαχτεί η Α[1].Χ και όταν πάει η ροή στη ρουτίνα το αντικείμενο επεξεργασίας στο Α[1] θα βρει την Κ ως Α[1].Κ. Μόλις το Κ τερματίσει το αντικείμενο επεξεργασιας θα χαθεί, θα χαθούν και οι μεταβλητές του.
Ουσιαστικά η Διαμέσου αντιγράφει το κώδικα από τη Ρουτίνα μέχρι το Τέλος Ρουτίνας και προσωρινά στο ίδιο αντικείμενο επεξεργασίας εκτελεί τον κώδικα και να επιστρέψει στο κώδικα που ήταν πριν, ή πριν από αυτό πάει σε άλλη κλήση ρουτίνας! Οι ρουτίνες αν δεν παρεμβάλουμε μπλοκ { } κώδικα έχουν μεγάλο εύρος αναδρομής (ακόμα και πάνω από ένα εκατομμύριο, και μπορούμε να ορίσουμε όριο με την ΟΡΙΟ.ΑΝΑΔΡΟΜΗΣ). Εξ ορισμούς είναι στις 10000. Γράφουμε Όριο.Αναδρομής (με την τελεία ανάμεσα) και μας δίνει το όριο στη κονσόλα. Γράφουμε το Όριο.Αναδρομής 1000000 και αλλάζουμε τη τιμή. Αυτό είναι δυνατό γιατί δεν χρησιμοποιείται ο σωρός επιστροφής του περιβάλλοντος (του m2000,exe) αλλά μνήμη του συστήματος. Οι απλές όμως συναρτήσεις σε κάθε κλήση χρησιμοποιούν τον σωρό επιστροφής του περιβάλλοντος και έχουν μέγιστη αναδρομή περίπου τις 3392 κλήσεις!

οριο.αναδρομής 1000000
κ=0
μέτρα()
ρουτίνα μέτρα()
κ++:? κ,:μέτρα()
τέλος ρουτίνας

Το προηγούμενο σταματάει στο 1000001. Δείτε και αυτό (σταματάει στο 3392):
κ=@μέτρα()
Συνάρτηση μέτρα()
κ++:? κ,:=@μέτρα()
τέλος συνάρτησης


Στο τρίτο πρόγραμμα η ρουτίνα α() δεν βρίσκει τη β() μέσα στο τμήμα Κ, ενώ στο τμήμα ΛΛ δουλεύει!
Σημασία όμως έχει να κατανοήσει κανείς πως η θέση της ρουτίνας έχει σχέση με την οικονομία στο κώδικα (να μην έχουμε πολλά αντίγραφα) και όχι με κλήση έξω από το τμήμα.
Όλες οι διαμέσου γίνονται στο ίδιο αντικείμενο εκτέλεσης (και θέλουν ελάχιστους πόρους).

\\ 1ο Πρόγραμμα
Χ=4
Τμήμα Κ {
      Χ=10
      Διαμέσου α()
}
Διαμέσου α() \\ Οκ  4
Κάλεσε Κ \\ Οκ 10
Ρουτίνα α()
      Τύπωσε "Οκ", Χ
Τελος Ρουτίνας


\\ 2ο Πρόγραμμα
Χ=4
Τμήμα Κ {
      Χ=10
      Διαμέσου α()
}
Διαμέσου α() \\ Οκ  4
Κάλεσε Κ \\ Οκ 10
Ρουτίνα β()
      Τύπωσε "Οκ2"
Τέλος Ρουτίνας
Ρουτίνα α()
      Διαμέσου β()
      Τύπωσε "Οκ", Χ
Τελος Ρουτίνας

\\ 3ο Πρόγραμμα
Τμήμα ΛΛ {
Χ=4
Τμήμα Κ {
      Χ=10
      Διαμέσου α()
}
Διαμέσου α() \\ Οκ  4
\\ Κάλεσε Κ      \\ θα βγει λάθος!
Ρουτίνα α()
      Διαμέσου β()
      Τύπωσε "Οκ", Χ
Τελος Ρουτίνας
}
Κάλεσε ΛΛ
Ρουτίνα β()
      Τύπωσε "Οκ2"
Τέλος Ρουτίνας


Δείτε και κάτι άλλο. Το παρακάτω δουλεύει γιατί η αναζήτηση της ρουτίνας γίνεται στη κλήση, και ψάχνει στο κώδικα το Ρουτίνα ή Ρουτίνα στη πρώτη γραμμή και μετά κοιτάει αν υπάρχει το α(, εδώ το βρίσκει παρόλο που είναι στο α$ ως σταθερά αλφαριθμητική και όχι ως πρόγραμμα. Στην ουσία το πρόγραμμα είναι μια σταθερά αλφαριθμητική.

Τμήμα ΛΛ {
α$={
Ρουτίνα α()
      Διαμέσου β()
      Τύπωσε "Οκ",  Χ
Τελος Ρουτίνας
}
Χ=4
Διαμέσου α() \\ Οκ  4
}
Κάλεσε ΛΛ
Ρουτίνα β()
      Τύπωσε "Οκ2"
Τέλος Ρουτίνας


Όταν τρέχει ένα πρόγραμμα τότε το αντικείμενο επεξεργασίας το καταναλώνει, δηλαδή ότι εκτελείται αφαιρείται! Μια επανάληψη ενός μπλοκ γίνεται επειδή έχει κρατηθεί αντίγραφο του κώδικα για επανάληψη! Μια ΠΡΟΣ όπως και η ΔΙΑΜΕΣΟΥ κάνουν έξοδο από το μπλοκ και νέα είσοδο εκεί που θέλουμε, με ανανεωση του κώδικα προς κατανάλωση!

Η Μ2000 δεν μετατρέπει το κώδικα σε κάτι ενδιάμεσο..τον καταναλώνει άμεσα! Έτσι μπορούμε με την Ένθεση να βάλουμε κώδικα (που δεν υπάρχει στο πηγαίο κώδικα αλλά μπορούμε να το φορτώσουμε από αλφαριθμητικό, από όπου θέλουμε). Επίσης με την εντολή Τμήμα χωρίς μπλοκ μετά το όνομα αλλάζουμε το όνομα του αντικείμενου επεξεργασίας...το οποίο το διαβάζουμε με την Τμήμα$. Με το τρόπο αυτό μπορούμε να έχουμε δυο σετ μεταβλητών ή και περισσότερα! Ουσιαστικά αλλάζουμε όνομα χώρου. Αλλά η ρουτίνα δεν σχετίζεται με όνομα χώρου (όπως τα τμήματα και οι συναρτήσεις). Εδώ καλούμε τη ρουτίνα και από τα δυο ονόματα!

Τμήμα ΔεςΕδω {
      α=1000
      γενική Κ$
      Κ$<=Τμήμα$
      ΑΒ=10
      Τμήμα ΑΛΦΑ1
      ΑΒ=20
      Τύπωσε ΑΒ \\20
      Διαμέσου Πολ(10)
      Τμήμα Κ$
      Τύπωσε ΑΒ \\10
      Διαμέσου Πολ(10)
      Τμήμα ΑΛΦΑ1
      Τύπωσε ΑΒ \\20
      Διαμέσου Πολ(10)
      Τμήμα Κ$ \\ αν δεν το βάλω η α θα είναι άγνωστη
      Τύπωσε α
}
Κάλεσε ΔεςΕδω
Ρουτίνα Πολ(α)
      Τύπωσε ΑΒ*α
Τέλος Ρουτίνας


Ουσιαστικά ένα τμήμα μπορεί να καλέσει ότι αναφέρεται ως γενικό και ότι έχει το ίδιο άμεσα (δεν μπορεί να καλέσει ένα τμήμα σε ένα δικό του τμήμα).
Αν θέλουμε κάτι τέτοιο τότε πάμε σε αντικείμενα. Εδώ δεν θα χρησιμοποιήσω συνάρτηση που επιστρέφει αντικείμενο όπως κάνει η ΚΛΑΣΗ όνομα { } που φτιάχνει την όνομα(), αλλά θα φτιάξω αυτό που λέμε στατικό αντικείμενο, ή ομάδα. Μάλιστα  μέσα στην ομάδα θα βάλω και άλλη ομάδα. Δείτε όμως πως τον ορισμό της ρουτίνας για οικονομία τον έβαλα στο τμήμα ΛΜ. Αν το έβαζα εκτός ομάδας τότε η κλήση στο ΛΜ και μετά στο .Λ.Μ θα ήταν δυο επίπεδα, άρα δεν θα έβρισκε τον ορισμό της στο Μ της ομάδας Λ στην ομάδα Α. Επίσης αν βάλουμε τη Ρουτίνα μέσα στο  τμήμα Κ δεν θα την βρει...το ΛΜ στο .Λ.Μ.

Το σύμβολο & σημαίνει πέρασμα με αναφορά. Όταν καλούμε το ΛΜ δεν διαβάζουμε από το σωρό την παράμετρο, το αφήνουμε να την διαβάσει το Λ.Μ δηλαδή το τμήμα Μ στην ομάδα Λ.

Η ομάδα α (το αντίγραφό της) που γράφτηκε στο αα(1) δεν είναι πια ένα στατικό αντικείμενο! Την περνάμε σε δυο τμήματα μέσω του πίνακα, στο ένα με αναφορά και στο άλλο με αντιγραφή. Στην αντιγραφή πίνακα έχουμε αντιγραφή και της ομάδας (δεν κρατάει δηλαδή αναφορά στην ομάδα το στοιχείο πίνακα αλλά περιέχει μια ομάδα με ότι έχει αυτή, τμήματα, συναρτήσεις, άλλους πίνακες, ομάδες). Τα μη στατικά αντικείμενα (ή πτητικά) είναι σαν προγράμματα χωρίς όνομα!


Ομάδα α {
      ι=5
      Τμήμα Κ {
            Διάβασε Χ
            Διαμέσου α()
            Τύπωσε Χ*
            ++
       
      }
      Ομάδα Λ {
            ι=10
            Τμήμα Μ {
                  Διάβασε Χ
                  Διαμέσου α()
                  Τύπωσε Χ*
                  ++
            }
       
      }
      Τμήμα ΛΜ {
            .Λ.Μ
            Ρουτίνα α()
                  Τύπωσε \\ τυπώνει το ι από κάθε ομάδα
            Τέλος Ρουτίνας
      }
}
Πίνακας ΚΚ(10)
ΚΚ(1)=α \\ αντίγραφο
Α.Κ 100 \5000
Α.Λ.Μ 100 \ 1000
Α.Κ 100 \600
Α.Λ.Μ 100 \1100
Α.ΛΜ 100 \1200


ΚΚ(1).ΛΜ 5000 \ 50000
Για ΚΚ(1) {
      .ΛΜ 5000 \ 55000
}
ΚΚ(1).ΛΜ 5000 \ 60000



Τμήμα ΔεςΚαιΕδώ {
      Διάβασε &αα()
      αα(1).ΛΜ 5000
}
ΔεςΚαιΕδώ &ΚΚ()
Τμήμα ΔεςΚαιΕδώ2 {
  Διάβασε αα()
  αα(1).ΛΜ 4000
}
ΔεςΚαιΕδώ2 ΚΚ()


Δείτε επίσης και τις παλιές αναρτήσεις πιο συνοπτικές για την Ρουτίνες:
Χρήση της ΔΙΑΜΕΣΟΥ ή GOSUB στη Μ2000 μέρος Α
και εδώ για την απλή χρήση της Διαμέσου με χρήση ετικετών και όχι ρουτινών
Χρήση της ΔΙΑΜΕΣΟΥ ή GOSUB στη Μ2000 μέρος Β

Τρίτη 29 Δεκεμβρίου 2015

Πιανάκι 004 με κλαβιέ (διόρθωση)


Τελική μορφή! Χρόνια Πολλά και καλή διασκέδαση!
(διόρθωσα το C4# σε C#4 πρώτα η νότα και μετά ο αριθμός οκτάβας)
Μπορεί κάποιος να ανεβάσει την οκτάβα, αλλά πρέπει να αλλάξει τα νούμερα από Α#3 ..D5...Συνολικά υπάρχουν 7 οκτάβες από 1 έως 7. Εδώ το πιανάκι είναι μπάσο, η 4η είναι η μεσαία οκτάβα. Παρακάτω έχω βάλει και το κανονικό πιανάκι!
Δεν είναι δύσκολο να γίνει με δυο κλαβιέ! Ήδη εδώ έχουμε δυο σειρές τα μαύρα και τα άσπρα πλήκτρα!


Πίνακας Νοτα1$(10,3), Νοτα2$(10,3)
διαμεσου ΓέμισεΠίνακα()
Φόρμα 60,30
Πένα 14
Οθονη 5
Διπλά
Αναφορά 2, "Πιανάκι 004"   
Κανονικά
Αναφορά 2,{Οδηγίες
1-Έξοδος  3-Ξυλόφωνο 4-Πιάνο 5-Σαξόφωνο  8-Πλήκτρα/Νότες 9-Ρυθμός Ναι 0-Ρυθμός Όχι


Διάστημα - Δυναμώνει τις νότες
-- Γιώργος Καρράς --


}
Σχέδιο.Νημάτων Διαδοχικό
Παίξε 0 \\ καθαρίζει το σύστημα
Γενική πλ$=" ", τέμπο=300, οργ=5, φ=0, εντ$="V90", φων(18), χρη(17) ' 0 ..17,
ν=1
Για ι=1 έως 16 { χρη(ι)=Αληθές }
χρη(10)= Ψευδές \\ για την drum machine
\\ υπολογισμός θέσης του κλαβιέ!
μμ=2*(χ.σημεια Δια 14)
μμ2= μμ δια 2
κκ=γραμμή/ύψος*υ.σημεια
κκ1=υ.σημεια/ύψος*8
γραμ=υ.σημεια/ύψος*1.5
Οθόνη , Γραμμή+9

Τμήμα Πλήκτρο {
      Διάβασε α$, πατ, επιλ
      αν πατ τοτε {
      Αν Θέση(πλ$,α$+"-")>0 τότε έξοδος
      διαμέσου Επομ()
      φων(επιλ)=φ \\ δεν χρειάζεται <=
      Τύπωσε α$, φ
      Φωνή φ, τεμπο, α$+εντ$ : πλ$<=πλ$+α$+"-": Παίξε φ, οργ
      } αλλιως {
            πλ$<=αλλαγή$(α$+"-","", πλ$)
            Αν φων(επιλ)>0 τότε {
             Παίξε φων(επιλ), 0 ' προσθήκη στην αναθ. 131
             χρη(φων(επιλ))~
             φων(επιλ)=0
             }
      }
      Ρουτίνα Επομ()
      τοπικη ι
      για ι=1 έως 16 {
            αν χρη(ι) τότε έξοδος
      }
      αν ι<17 τότε { φ<=ι : χρη(ι)~ } αλλιώς φ<=1: χρη(1)=αληθές : Τυπωσε "!!!!!!!!"
      Τέλος Ρουτίνας
}
\\ κανάλι 10 είναι το drum machine
Νήμα { Φωνή 10,400,"CV90CC  ab Cd eCC" : Παίξε 10,1 } ως Λ κάθε 60
Νήμα {
      πλήκτρο "A#2", πατημένο(κωδ("A")), 1
      πλήκτρο "B2", πατημένο(κωδ("Z")), 2
      πλήκτρο "C3", πατημένο(κωδ("X")), 3
      πλήκτρο "C#3", πατημένο(κωδ("D")), 4
      πλήκτρο "D3", πατημένο(κωδ("C")), 5
      πλήκτρο "D#3", πατημένο(κωδ("F")), 6
      πλήκτρο "E3", πατημένο(κωδ("V")), 7
      πλήκτρο "F3", πατημένο(κωδ("B")), 8
      πλήκτρο "F#3", πατημένο(κωδ("H")), 9
      πλήκτρο "G3", πατημένο(κωδ("N")), 10
      πλήκτρο "G#3", πατημένο(κωδ("J")), 11
      πλήκτρο "A3", πατημένο(κωδ("M")), 12
      πλήκτρο "A#3", πατημένο(κωδ("K")), 13
      \\ https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
      πλήκτρο "B3", πατημένο(0xBC), 14 \\ VK_OEM_COMMA
      πλήκτρο "C4", πατημένο(0xBE), 15 \\ VK_OEM_PERIOD
      πλήκτρο "C#4", πατημένο(0xBA), 16 \\ VK_OEM_1
      πλήκτρο "D4", πατημένο(0xBF), 17 \\VK_OEM_2  
} ως ΑΛ κάθε 50
Τύπωσε "οκ"
Νηματα
Αναμονή 100 \\ ξεκινάει το Λ μέσα στην αναμονή και μετά αλλάζουμε το χρόνο του!
Νήμα Λ Κάθε 6000
Κύριο.Έργο 100 {
      Διαμέσου Εμφ_Κλαβιέ(μμ, κκ, μμ2, κκ1)
      αν πατημένο(κωδ("1")) τότε έξοδος
      αν πατημένο(κωδ("3")) τότε οργ<=14 : τέμπο<=100 ' ξυλόφωνο
      αν πατημένο(κωδ("4")) τότε οργ<=5 : τέμπο<=300 ' Πιάνο
      αν πατημένο(κωδ("5")) τότε οργ<=65 : τέμπο<=5000 ' Σαξόφωνο
      αν πατημένο(κωδ("8")) τότε ν=1-ν
      αν πατημένο(κωδ("9")) τότε Νήμα Λ Ξεκίνα
      αν πατημένο(κωδ("0")) τότε Νήμα Λ Κράτα
      αν πατημένο(32) τότε { εντ$<="V127" } Αλλιώς εντ$<="V90"
      Τύπωσε "--------"
}
Τύπωσε "Τέλος"

Ρουτίνα Εμφ_Κλαβιέ(π0,υ0, π1, υ1)
      ανανεωση 5000
      Διαμέσου Κλαβιέ(π0, υ0, π1, υ1, 0, &Νοτα1$())
      Διαμέσου Κλαβιέ(π0-π1/2,υ0,π1,υ1*2/3, -1, &Νοτα2$())
      ανανέωση 50
Τέλος Ρουτίνας

Ρουτινα Κλαβιέ(π0, υ0,π1, υ1, π3, &Ν$())
      Ένωσε Ν$() στο Ν()
      π3-!
      Τοπικές κ=-1, ι
      Για ι=π0 εως 9*π1+π0 ανά π1
      κ++
      Αν Ν$(κ,0)<>"" Τότε {
            θέση ι+π3*π1/6, υ0
            Αν π3 τότε {
                  βαψε π1-π3*π1/3-15,υ1-15, 7* (1-(φων(Ν(κ,2))>0))+1, 0,1
            } Αλλιώς {
                  βαψε π1-15,υ1-15,15,7* (1-(φων(Ν(κ,2))=0))+1,1
            }
            θέση ι+π3*π1/6, υ0
            βαψε @ π1-π3*π1/3,υ1,2,1
            θέση ι+π3*π1/6, υ0+υ1-γραμ
             πένα π3*15 { βαψε @ π1-π3*π1/3,γραμ,5,Ν$(κ,ν)}
      }
      Επόμενο ι
Τέλος Ρουτίνας

Ρουτίνα ΓέμισεΠίνακα()
Τοπικές ν,π, ν$, κ$, νο
Σωρός Νέος {
      Σειρά "A#2", "A", 1, 1, 2
      Σειρά "B2", "Z", 2, 1, 1
      Σειρά "C3", "X", 3, 2, 1
      Σειρά "C#3", "D", 4, 3, 2
      Σειρά "D3", "C", 5, 3, 1
      Σειρά "D#3", "F", 6, 4, 2
      Σειρά "E3", "V", 7, 4, 1
      Σειρά "F3", "B", 8, 5, 1
      Σειρά "F#3", "H", 9, 6, 2
      Σειρά "G3", "N", 10, 6, 1
      Σειρά "G#3", "J", 11, 7, 2
      Σειρά "A3", "M", 12, 7, 1
      Σειρά "A#3", "K", 13, 8, 2
      Σειρά "B3", ",", 14, 8, 1
      Σειρά "C4", ".", 15, 9, 1
      Σειρά "C#4",";", 16 , 10, 2 \\ 10 μικρά - λείπουν μερικά
      Σειρά "D4", "/", 17, 10, 1 \\ 10 μεγάλα πλήκτρα
      Ενώ όχι κενό {
      Διάβασε ν$, κ$, νο, ν, π
            Αν π=1 τότε {
                νοτα1$(ν-1,0):= ν$, κ$, νο
            } Αλλιώς {
                  νοτα2$(ν-1,0):= ν$, κ$, νο
            }
      }
}
Τέλος Ρουτίνας



Και με μια οκτάβα πιο ψηλά (στο μέσον δηλαδή, η 4 είναι η μεσαία)

Πίνακας Νοτα1$(10,3), Νοτα2$(10,3)
διαμεσου ΓέμισεΠίνακα()
Φόρμα 60,30
Πένα 14
Οθονη 5
Διπλά
Αναφορά 2, "Πιανάκι 005"   
Κανονικά
Αναφορά 2,{Οδηγίες
1-Έξοδος  3-Ξυλόφωνο 4-Πιάνο 5-Σαξόφωνο  8-Πλήκτρα/Νότες 9-Ρυθμός Ναι 0-Ρυθμός Όχι


Διάστημα - Δυναμώνει τις νότες
-- Γιώργος Καρράς --


}
Σχέδιο.Νημάτων Διαδοχικό
Παίξε 0 \\ καθαρίζει το σύστημα
Γενική πλ$=" ", τέμπο=300, οργ=5, φ=0, εντ$="V90", φων(18), χρη(17) ' 0 ..17,
ν=1
Για ι=1 έως 16 { χρη(ι)=Αληθές }
χρη(10)= Ψευδές \\ για την drum machine
\\ υπολογισμός θέσης του κλαβιέ!
μμ=2*(χ.σημεια Δια 14)
μμ2= μμ δια 2
κκ=γραμμή/ύψος*υ.σημεια
κκ1=υ.σημεια/ύψος*8
γραμ=υ.σημεια/ύψος*1.5
Οθόνη , Γραμμή+9
Τμήμα Πλήκτρο {
      Διάβασε α$, πατ, επιλ
      αν πατ τοτε {
      Αν Θέση(πλ$,α$+"-")>0 τότε έξοδος
      διαμέσου Επομ()
      φων(επιλ)=φ \\ δεν χρειάζεται <=
      Τύπωσε α$, φ
      Φωνή φ, τεμπο, α$+εντ$ : πλ$<=πλ$+α$+"-": Παίξε φ, οργ
      } αλλιως {
            πλ$<=αλλαγή$(α$+"-","", πλ$)
            Αν φων(επιλ)>0 τότε {
             Παίξε φων(επιλ), 0 ' προσθήκη στην αναθ. 131
             χρη(φων(επιλ))~
             φων(επιλ)=0
             }
      }
      Ρουτίνα Επομ()
      τοπικη ι
      για ι=1 έως 16 {
            αν χρη(ι) τότε έξοδος
      }
      αν ι<17 τότε { φ<=ι : χρη(ι)~ } αλλιώς φ<=1: χρη(1)=αληθές : Τυπωσε "!!!!!!!!"
      Τέλος Ρουτίνας
}
\\ κανάλι 10 είναι το drum machine
Νήμα { Φωνή 10,400,"CV90CC  ab Cd eCC" : Παίξε 10,1 } ως Λ κάθε 60
Νήμα {
      πλήκτρο "A#3", πατημένο(κωδ("A")), 1
      πλήκτρο "B3", πατημένο(κωδ("Z")), 2
      πλήκτρο "C4", πατημένο(κωδ("X")), 3
      πλήκτρο "C#4", πατημένο(κωδ("D")), 4
      πλήκτρο "D4", πατημένο(κωδ("C")), 5
      πλήκτρο "D#4", πατημένο(κωδ("F")), 6
      πλήκτρο "E4", πατημένο(κωδ("V")), 7
      πλήκτρο "F4", πατημένο(κωδ("B")), 8
      πλήκτρο "F#4", πατημένο(κωδ("H")), 9
      πλήκτρο "G4", πατημένο(κωδ("N")), 10
      πλήκτρο "G#4", πατημένο(κωδ("J")), 11
      πλήκτρο "A4", πατημένο(κωδ("M")), 12
      πλήκτρο "A#4", πατημένο(κωδ("K")), 13
      \\ https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
      πλήκτρο "B4", πατημένο(0xBC), 14 \\ VK_OEM_COMMA
      πλήκτρο "C5", πατημένο(0xBE), 15 \\ VK_OEM_PERIOD
      πλήκτρο "C#5", πατημένο(0xBA), 16 \\ VK_OEM_1
      πλήκτρο "D5", πατημένο(0xBF), 17 \\VK_OEM_2  
} ως ΑΛ κάθε 50
Τύπωσε "οκ"
Νηματα
Αναμονή 100 \\ ξεκινάει το Λ μέσα στην αναμονή και μετά αλλάζουμε το χρόνο του!
Νήμα Λ Κάθε 6000
Κύριο.Έργο 100 {
      Διαμέσου Εμφ_Κλαβιέ(μμ, κκ, μμ2, κκ1)
      αν πατημένο(κωδ("1")) τότε έξοδος
      αν πατημένο(κωδ("3")) τότε οργ<=14 : τέμπο<=100 ' ξυλόφωνο
      αν πατημένο(κωδ("4")) τότε οργ<=5 : τέμπο<=300 ' Πιάνο
      αν πατημένο(κωδ("5")) τότε οργ<=65 : τέμπο<=5000 ' Σαξόφωνο
      αν πατημένο(κωδ("8")) τότε ν=1-ν
      αν πατημένο(κωδ("9")) τότε Νήμα Λ Ξεκίνα
      αν πατημένο(κωδ("0")) τότε Νήμα Λ Κράτα
      αν πατημένο(32) τότε { εντ$<="V127" } Αλλιώς εντ$<="V90"
      Τύπωσε "--------"
}
Τύπωσε "Τέλος"
Ρουτίνα Εμφ_Κλαβιέ(π0,υ0, π1, υ1)
      ανανεωση 5000
      Διαμέσου Κλαβιέ(π0, υ0, π1, υ1, 0, &Νοτα1$())
      Διαμέσου Κλαβιέ(π0-π1/2,υ0,π1,υ1*2/3, -1, &Νοτα2$())
      ανανέωση 50
Τέλος Ρουτίνας
Ρουτινα Κλαβιέ(π0, υ0,π1, υ1, π3, &Ν$())
      Ένωσε Ν$() στο Ν()
      π3-!
      Τοπικές κ=-1, ι
      Για ι=π0 εως 9*π1+π0 ανά π1
      κ++
      Αν Ν$(κ,0)<>"" Τότε {
            θέση ι+π3*π1/6, υ0
            Αν π3 τότε {
                  βαψε π1-π3*π1/3-15,υ1-15, 7* (1-(φων(Ν(κ,2))>0))+1, 0,1
            } Αλλιώς {
                  βαψε π1-15,υ1-15,15,7* (1-(φων(Ν(κ,2))=0))+1,1
            }
            θέση ι+π3*π1/6, υ0
            βαψε @ π1-π3*π1/3,υ1,2,1
            θέση ι+π3*π1/6, υ0+υ1-γραμ
             πένα π3*15 { βαψε @ π1-π3*π1/3,γραμ,5,Ν$(κ,ν)}
      }
      Επόμενο ι
Τέλος Ρουτίνας
Ρουτίνα ΓέμισεΠίνακα()
Τοπικές ν,π, ν$, κ$, νο
Σωρός Νέος {
      Σειρά "A#3", "A", 1, 1, 2
      Σειρά "B3", "Z", 2, 1, 1
      Σειρά "C4", "X", 3, 2, 1
      Σειρά "C#4", "D", 4, 3, 2
      Σειρά "D4", "C", 5, 3, 1
      Σειρά "D#4", "F", 6, 4, 2
      Σειρά "E4", "V", 7, 4, 1
      Σειρά "F4", "B", 8, 5, 1
      Σειρά "F#4", "H", 9, 6, 2
      Σειρά "G4", "N", 10, 6, 1
      Σειρά "G#4", "J", 11, 7, 2
      Σειρά "A4", "M", 12, 7, 1
      Σειρά "A#4", "K", 13, 8, 2
      Σειρά "B4", ",", 14, 8, 1
      Σειρά "C5", ".", 15, 9, 1
      Σειρά "C#5",";", 16 , 10, 2 \\ 10 μικρά - λείπουν μερικά
      Σειρά "D5", "/", 17, 10, 1 \\ 10 μεγάλα πλήκτρα
      Ενώ όχι κενό {
      Διάβασε ν$, κ$, νο, ν, π
            Αν π=1 τότε {
                νοτα1$(ν-1,0):= ν$, κ$, νο
            } Αλλιώς {
                  νοτα2$(ν-1,0):= ν$, κ$, νο
            }
      }
}
Τέλος Ρουτίνας


Υπάρχουν πληκτρολόγια που δέχονται έξι πλήκτρα μαζί! (έχω ένα Logitech K310 που παίζει 6 νότες μαζί). Σε φορητούς σπάνια παίζουν πάνω από δύο πλήκτρα. Με χρήση δεύτερου πληκτρολόγιου αυξάνουμε τα πλήκτρα που μπορούν να παίξουν ταυτόχρονα.