Hangman game using qp a 16x2 LCD and joystick.

Dependencies:   TextLCD mbed qp

Revision:
0:1521c946a57b
Child:
1:4efaebc256d3
diff -r 000000000000 -r 1521c946a57b host.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host.cpp	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,185 @@
+#include "qp_port.h"
+#include "hangman.h"
+#include "bsp.h"
+
+class Host : public QActive {
+private:
+    char* word;
+    uint8_t selected_word;
+    uint8_t num_letters;
+    uint8_t incorrect_letters;
+    char* used_letters;
+
+    char letter;
+    char output1[17]; // buffer for display
+    char output2[17];
+
+public:
+    Host();
+
+private:
+    static QState initial(Host *me, QEvent const *e);
+    static QState welcome(Host *me, QEvent const *e);
+    static QState playing(Host *me, QEvent const *e);
+};
+
+#define BANK_SIZE   4
+char* const word_bank[] = { "hangmann", "global", "micro", "sensor" };
+char* const win_msg = "   You Win!";
+char* const loose_msg = "   You suck!";
+char* const press_play_msg = "Push to continue";
+
+
+// Local objects -------------------------------------------------------------
+static Host l_host;                                    // local Host object
+
+// Public-scope objects ------------------------------------------------------
+QActive * const AO_Host = &l_host;                    // "opaque" AO pointer
+
+//............................................................................
+Host::Host() : QActive((QStateHandler)&Host::initial) {
+}
+
+//............................................................................
+QState Host::initial(Host *me, QEvent const *e) {
+
+    QS_OBJ_DICTIONARY(&l_host);
+    QS_FUN_DICTIONARY(&QHsm::top);
+    QS_FUN_DICTIONARY(&Host::initial);
+    QS_FUN_DICTIONARY(&Host::playing);
+
+    QS_SIG_DICTIONARY(TERMINATE_SIG, 0); // global signal
+
+    QS_SIG_DICTIONARY(START_SIG, me);     // signals for Host
+    QS_SIG_DICTIONARY(SCROLL_SIG, me);
+    QS_SIG_DICTIONARY(SELECT_SIG, me);
+
+    me->subscribe(TERMINATE_SIG);
+
+    // output welcome message
+    BSP_lcdUpdate("Push btn to play mbed hangman!","");
+    wait(2.0);  // pause for 2 seconds
+
+    return Q_TRAN(&Host::welcome);
+}
+
+//............................................................................
+QState Host::welcome(Host *me, QEvent const *e) {
+    HostEvt *pe;
+
+    switch (e->sig) {
+        case START_SIG: {
+            uint8_t idx;
+
+            // init the game
+            time_t seconds = time(NULL);
+            me->selected_word = seconds % BANK_SIZE;
+            me->word = word_bank[me->selected_word];
+            me->num_letters = strlen(me->word);
+            me->incorrect_letters = 0;
+            for (int i = 0; i < 17; i++) { // clear output
+                me->output1[i] = ' ';
+                me->output2[i] = ' ';
+            }
+
+            for (idx = 0; idx < me->num_letters; idx++) {
+                me->output1[idx] = '_';
+            }
+            for (; idx < 16; idx++) {
+                me->output1[idx] = ' ';
+            }
+            me->letter = 'a';
+            idx = 16;
+            me->output1[idx] = me->letter;
+            // clear output2
+            for (idx = 0; idx < 17; idx++)
+                me->output2[idx] = ' ';
+
+            BSP_lcdUpdate(me->output1, me->output2); // update display
+
+            // post play to player
+            pe = Q_NEW(HostEvt, PLAY_SIG);
+            pe->scroll_pos = 0; // center
+            QF::PUBLISH(pe, me);
+
+            return Q_TRAN(&Host::playing);
+        }
+        case TERMINATE_SIG: {
+            QF::stop();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}
+
+//............................................................................
+QState Host::playing(Host *me, QEvent const *e) {
+
+    HostEvt *pe;
+
+    switch (e->sig) {
+        case SCROLL_SIG: {
+            if (((HostEvt const *)e)->scroll_pos < 0) { // go down
+                if (me->letter == 'a') // wrap around
+                    me->letter = 'z';
+                else
+                    me->letter--;
+            } else if (((HostEvt const *)e)->scroll_pos > 0) { // go up
+                if (me->letter == 'z') // wrap around
+                    me->letter = 'a';
+                else
+                    me->letter++;
+            }
+            me->output1[16] = me->letter;
+            BSP_lcdUpdate(me->output1,me->output2);
+
+            return Q_HANDLED();
+        }
+        case SELECT_SIG: {
+            // test for letter in word
+            char * pch;
+            pch=strchr(me->word,me->letter);
+            if (pch != NULL) { // found in word
+                do {
+                    me->word[pch-me->word] = ' ';
+                    me->output1[pch-me->word] = me->letter;
+                    pch=strchr(pch+1,me->letter);
+                } while (pch!=NULL);
+                // update screen
+                BSP_lcdUpdate(me->output1,me->output2);
+                // test for win
+                if (strpbrk(me->word,"abcdefghijklmnopqrs") == NULL) { // win!
+                    BSP_lcdScrollIn(win_msg, press_play_msg); // win msg
+                    // post play to player
+                    HostEvt *pe = Q_NEW(HostEvt, WIN_SIG);
+                    pe->scroll_pos = 0; // center
+                    QF::PUBLISH(pe, me);
+
+                    // go to welcome state
+                    return Q_TRAN(&Host::welcome);
+                }
+            } else {
+                if (++me->incorrect_letters >= MAX_LETTERS) { // loose
+                    BSP_lcdScrollIn(loose_msg, press_play_msg); // message
+                    // post play to player
+                    HostEvt *pe = Q_NEW(HostEvt, WIN_SIG);
+                    pe->scroll_pos = 0; // center
+                    QF::PUBLISH(pe, me);
+
+                    // go to welcome state
+                    return Q_TRAN(&Host::welcome);
+                } else {
+                    // post to used letters
+                    me->output2[me->incorrect_letters-1] = (char)(me->letter - 33); // make uppercase
+                    BSP_lcdUpdate(me->output1,me->output2); // update screen
+                }
+            }
+            return Q_HANDLED();
+        }
+        case TERMINATE_SIG: {
+            QF::stop();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}