Dependencies:   mbed wave_player mbed-rtos 4DGL-uLCD-SE SDFileSystem

Revision:
3:6e41a5ce16c2
Parent:
2:acd4656312d8
Child:
4:c1da839b41b1
diff -r acd4656312d8 -r 6e41a5ce16c2 main.cpp
--- a/main.cpp	Sun Apr 26 00:47:37 2020 +0000
+++ b/main.cpp	Mon Apr 27 03:14:16 2020 +0000
@@ -10,17 +10,51 @@
 #include <fstream>
 #include <algorithm>
 
-using namespace std;
+enum DIFF_LEVEL{NA=0, EASY=1, MED=2, HARD=3, SCORE=4};
+enum SIGN{PLUS=0, MINUS=1, MULT=2};
+
+struct Gen_Question{
+    int num1;
+    int num2;
+    int sign;
+    int corr_ans;
+    int ans[4];
+};
+
+struct Game_Difficulty{
+    bool is_selected;
+    enum DIFF_LEVEL level;
+    int ans_time;
+    int max_num;
+    int num_of_q;
+    int score_mult;
+};
+
+struct Game_Settings{
+    Game_Difficulty new_diff;
+    int score;
+    int live_left; 
+    int q_on;
+    bool is_timeout;
+    bool is_lose;
+};
+
+
+Game_Settings new_game = {.q_on=1, .live_left = 3, .new_diff.is_selected=false, .is_timeout=true, .is_lose =false};
+
+
+void print_high_score();
+int* read_high_score();
 
 /*
 ------------------CONSTS
 */
+//const int EASY_TIME =20;
+//const int MED_TIME =15;
+//const int HARD_TIME =10;
 
 volatile bool homescreen = true;
-volatile bool diff_selected = false;
 volatile bool boot_vid = true;
-bool timeout = true;
-bool game_is_over = false;
 
 /*
 ------------------I/O VARS
@@ -50,14 +84,8 @@
 /*
 ------------------GENERAL VARS
 */
-int difficulty = 0;
-string scores;
-int score_val[3];
-volatile char bnum;
-int ans[4];
-int corr_ans;
-char sign;
-int live_left = 3;
+volatile char bnum = '0';
+
 
 Mutex lcd_mutex;
 Mutex blue_mutex;
@@ -65,23 +93,17 @@
 
 void main_screen()
 {
-
-    //while(true){
-    //        if(homescreen){
-    pc.printf("MAIN_SCREEN\r\n");
-    lcd_mutex.lock();
+    //pc.printf("MAIN_SCREEN\r\n");
     uLCD.cls();
-    uLCD.text_height(1.9);
-    uLCD.text_width(1.9);
-    uLCD.color(WHITE);
+    uLCD.text_height(1);
+    uLCD.text_width(1);
+    uLCD.color(0xF0F6F7);
     uLCD.locate(6, 1);
     uLCD.printf("MATH FUN");
-    //MAKE MATH FUN BLINK
     uLCD.locate(1, 4);
-    uLCD.text_height(1.3);
     uLCD.printf("Difficulty");
-    uLCD.text_height(1.3);
-    uLCD.text_width(1.9);
+    uLCD.text_height(1);
+    uLCD.text_width(1);
     uLCD.locate(3, 6);
     uLCD.color(GREEN);
     uLCD.printf("1) Easy");
@@ -91,25 +113,16 @@
     uLCD.locate(3, 10);
     uLCD.color(RED);
     uLCD.printf("3) Very Uneasy");
-    uLCD.color(BLUE);
+    uLCD.color(0x669DB2);
     uLCD.locate(1, 13);
     uLCD.printf("4) High Scores");
-    lcd_mutex.unlock();
-    //pc.printf("thread 1\r\n");
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
     homescreen = false;
-    //  Thread::wait(100);
-    // }
-    // else{
-    //     Thread::yield();
-    // }
-    //}
 }
 
 bool count_distinct(int arr[], int n)
 {
-
     int res = 1;
-
     // Pick all elements one by one
     for (int i = 1; i < n; i++)
     {
@@ -117,12 +130,10 @@
         for (j = 0; j < i; j++)
             if (arr[i] == arr[j])
                 break;
-
-        // If not printed earlier, then print it
+    // If not printed earlier, then print it
         if (i == j)
             res++;
     }
-
     if (res == 4)
     {
         return false;
@@ -133,67 +144,64 @@
     }
 }
 
-void gen_ans(int &num1, int &num2, int sign_val)
+void gen_ans(Gen_Question *gen_new_q)
 {
-
-    switch (sign_val)
+    //rand()%(max-min + 1) + min;
+    gen_new_q->num1 = rand() % (new_game.new_diff.max_num + 1 - 0) + 0;
+    gen_new_q->num2 = rand() % (new_game.new_diff.max_num + 1 - 1) + 1;
+    gen_new_q->sign = rand() % (3 + 1 - 1) + 1;
+    
+    switch (gen_new_q->sign)
     {
     case 1:
-        sign = '*';
-        ans[0] = num1 * num2;
-        ans[1] = (num1 + (rand() % (10 + 1 - 1) + 1)) * num2;
-        ans[2] = (num1 * num2) + (rand() % (20 + 1 - 1) + 1);
-        ans[3] = (num1 * num2) + (rand() % (20 + 1 - 1) + 1);
+        gen_new_q->sign = '*';
+        gen_new_q->ans[0] = gen_new_q->num1 * gen_new_q->num2;
+        gen_new_q->ans[1] = (gen_new_q->num1 + (rand() % (10 + 1 - 1) + 1)) * gen_new_q->num2;
+        gen_new_q->ans[2] = (gen_new_q->num1 * gen_new_q->num2) + (rand() % (20 + 1 - 1) + 1);
+        gen_new_q->ans[3] = (gen_new_q->num1 * gen_new_q->num2) + (rand() % (20 + 1 - 1) + 1);
         break;
     case 2:
-        sign = '+';
-        ans[0] = num1 + num2;
-        ans[1] = (num1 + (rand() % (10 + 1 - 1) + 1)) + num2;
-        ans[2] = (num1 + num2) - (rand() % ((num1 + num2) + 1 - 1) + 1);
-        ans[3] = (num1 * num2) + (rand() % (10 + 1 - 1) + 1);
+        gen_new_q->sign = '+';
+        gen_new_q->ans[0] = gen_new_q->num1 + gen_new_q->num2;
+        gen_new_q->ans[1] = (gen_new_q->num1 + (rand() % (10 + 1 - 1) + 1)) + gen_new_q->num2;
+        gen_new_q->ans[2] = (gen_new_q->num1 + gen_new_q->num2) - (rand() % ((gen_new_q->num1 + gen_new_q->num2) + 1 - 1) + 1);
+        gen_new_q->ans[3] = (gen_new_q->num1 * gen_new_q->num2) + (rand() % (10 + 1 - 1) + 1);
         break;
     case 3:
-        sign = '-';
-        //rand()%(max-min + 1) + min;
-        while (num1 == num2)
+        gen_new_q->sign = '-';
+        while (gen_new_q->num1 == gen_new_q->num2)
         {
-            num1 = (rand() % ((num1 + 2) - 1 + 1) + 1);
+            gen_new_q->num1 = (rand() % ((gen_new_q->num1 + 2) - 1 + 1) + 1);
         }
-        ans[0] = num1 - num2;
-        ans[1] = (num1 - num2) * -1 + (rand() % (10 + 1 - 1) + 1);
-        ans[2] = num1 + num2 - (rand() % (10 + 1 - 1) + 1);
-        ans[3] = num1 * num2 - (rand() % (20 + 1 - 1) + 1);
-        break;
-    case 4:
-        sign = '/';
-        ans[0] = num1 - num2;
+        gen_new_q->ans[0] = gen_new_q->num1 - gen_new_q->num2;
+        gen_new_q->ans[1] = (gen_new_q->num1 - gen_new_q->num2) * -1 + (rand() % (10 + 1 - 1) + 1);
+        gen_new_q->ans[2] = gen_new_q->num1 + gen_new_q->num2 - (rand() % (10 + 1 - 1) + 1);
+        gen_new_q->ans[3] = gen_new_q->num1 * gen_new_q->num2 - (rand() % (20 + 1 - 1) + 1);
         break;
     }
 }
 
-void game_questions()
+void game_questions(Gen_Question *gen_new_q)
 {
-    int gen1 = rand() % (10 + 1 - 0) + 0;
-    int gen2 = rand() % (10 + 1 - 1) + 1;
-    int gen_sign = rand() % (3 + 1 - 1) + 1;
-    gen_ans(gen1, gen2, gen_sign);
-    bool reroll = count_distinct(ans, 4);
+    gen_ans(gen_new_q);
+    bool reroll = count_distinct(gen_new_q->ans, 4);
     while (reroll)
     {
-        gen_ans(gen1, gen2, gen_sign);
-        reroll = count_distinct(ans, 4);
+        gen_ans(gen_new_q);
+        reroll = count_distinct(gen_new_q->ans, 4);
         //pc.printf("reroll\r\n");
     }
 
-    corr_ans = ans[0];
-    random_shuffle(&ans[0], &ans[3]);
-
+    gen_new_q->corr_ans = gen_new_q->ans[0];
+    //pc.printf("%i\r\n", gen_new_q->ans[0]);
+    //pc.printf("%i\r\n", gen_new_q->corr_ans);
+    random_shuffle(&(gen_new_q->ans[0]), &(gen_new_q->ans[3]));
     uLCD.cls();
     uLCD.locate(2, 1);
     uLCD.text_height(2);
     uLCD.text_width(2);
     uLCD.color(0xFC766A);
-    uLCD.printf("Q1");
+    uLCD.printf("Q%i",new_game.q_on);
     uLCD.text_height(1);
     uLCD.text_width(1);
 
@@ -209,7 +217,7 @@
     uLCD.locate(2, 4);
     uLCD.text_height(2);
     uLCD.text_width(2);
-    uLCD.printf("%i%c%i=", gen1, sign, gen2);
+    uLCD.printf("%i%c%i=", gen_new_q->num1, gen_new_q->sign, gen_new_q->num2);
     uLCD.text_height(1);
     uLCD.text_width(1);
 
@@ -219,7 +227,7 @@
 
     uLCD.color(0x669DB2);
     uLCD.locate(8, 7);
-    uLCD.printf("%i", ans[0]);
+    uLCD.printf("%i", gen_new_q->ans[0]);
 
     uLCD.color(0xFC766A);
     uLCD.locate(2, 9);
@@ -227,7 +235,7 @@
 
     uLCD.color(0x669DB2);
     uLCD.locate(8, 9);
-    uLCD.printf("%i", ans[1]);
+    uLCD.printf("%i", gen_new_q->ans[1]);
 
     uLCD.color(0xFC766A);
     uLCD.locate(2, 11);
@@ -235,7 +243,7 @@
 
     uLCD.color(0x669DB2);
     uLCD.locate(8, 11);
-    uLCD.printf("%i", ans[2]);
+    uLCD.printf("%i", gen_new_q->ans[2]);
 
     uLCD.color(0xFC766A);
     uLCD.locate(2, 13);
@@ -243,10 +251,11 @@
 
     uLCD.color(0x669DB2);
     uLCD.locate(8, 13);
-    uLCD.printf("%i", ans[3]);
+    uLCD.printf("%i", gen_new_q->ans[3]);
 
     uLCD.line(0, 115, 127, 115, 0xA89C94);
 }
+
 void game_over()
 {
     uLCD.cls();
@@ -255,8 +264,34 @@
     uLCD.text_width(2);
     uLCD.color(0xFC776A);
     uLCD.printf("GAME OVER");
-    game_is_over = true;
-    wait(2);
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+}
+
+void win_game()
+{
+    uLCD.cls();
+    uLCD.locate(2, 7);
+    uLCD.text_height(2);
+    uLCD.text_width(2);
+    uLCD.color(GREEN);
+    uLCD.printf("YOU WIN");
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+
+}
+
+void score_game()
+{
+    uLCD.cls();
+    uLCD.locate(1, 3);
+    uLCD.text_height(2);
+    uLCD.text_width(2);
+    uLCD.color(GREEN);
+    uLCD.printf("SCORE");
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+    uLCD.text_height(1);
+    uLCD.text_width(1);
+    uLCD.locate(7, 7);
+    uLCD.printf("%i",new_game.score);
 }
 
 void life_count_check()
@@ -265,19 +300,20 @@
     life[1] = 0;
     life[2] = 0;
 
-    for (int i = 0; i < live_left; i++)
+    for (int i = 0; i < new_game.live_left; i++)
     {
         life[i] = 1;
     }
-    if (live_left == 0)
+    if (new_game.live_left == 0)
     {
-        game_over();
+        new_game.is_lose = true;
+
     }
 }
 
-void check_correct_ans()
+void check_correct_ans(Gen_Question check_new_q)
 {
-    if (timeout)
+    if (new_game.is_timeout)
     {
         //pc.printf("TIMEOUT\r\n");
         uLCD.cls();
@@ -286,7 +322,7 @@
         uLCD.text_width(2);
         uLCD.color(0xF0F6F7);
         uLCD.printf("TIME");
-        live_left--;
+        new_game.live_left--;
         //wait(2);
     }
     else
@@ -294,7 +330,7 @@
         //pc.printf("%i\r\n", corr_ans);
         //pc.printf("%i\r\n", ans[(bnum-'0' -1)]);
 
-        if (corr_ans == ans[(bnum - '0') - 1])
+        if (check_new_q.corr_ans == check_new_q.ans[(bnum - '0') - 1])
         {
 
             uLCD.cls();
@@ -303,6 +339,7 @@
             uLCD.text_width(2);
             uLCD.color(GREEN);
             uLCD.printf("CORRECT");
+            new_game.score = new_game.score + new_game.new_diff.score_mult;
             //wait(2);
             //pc.printf("CORRECT\r\n");
         }
@@ -315,7 +352,7 @@
             uLCD.text_width(2);
             uLCD.color(RED);
             uLCD.printf("INCORRECT");
-            live_left--;
+            new_game.live_left--;
             //wait(2);
         }
     }
@@ -324,8 +361,9 @@
 
 bool get_bluetooth_button()
 {
-    pc.printf("BLUETOOTH\r\n");
-    blue_mutex.lock();
+    //pc.printf("BLUETOOTH\r\n");
+    bnum = '0';
+    //blue_mutex.lock();
     if (bluemod.getc() == '!')
     {
         if (bluemod.getc() == 'B')
@@ -338,21 +376,21 @@
             {
                 if (bhit == '1')
                 {
-                    pc.printf("%c\r\n", bnum);
+                    //pc.printf("%c\r\n", bnum);
                     blue_mutex.unlock();
                     return false;
                 }
             }
         }
     }
-    blue_mutex.unlock();
+    //blue_mutex.unlock();
     return true;
 }
 
 void get_button()
 {
-    int timer = 10;
-    timeout = true;
+    int timer = new_game.new_diff.ans_time;
+    new_game.is_timeout = true;
     while (timer != 0)
     {
         uLCD.locate(15, 1);
@@ -360,8 +398,8 @@
         uLCD.printf("%i", timer);
         if (bluemod.readable())
         {
-            timeout = get_bluetooth_button();
-            if(timeout == false){
+            new_game.is_timeout = get_bluetooth_button();
+            if(new_game.is_timeout == false){
                 break;
             }
         }
@@ -370,12 +408,10 @@
         uLCD.color(BLACK);
         uLCD.printf("%i", timer);
         timer = timer - 1;
-        //pc.printf("%i\r\n", x);
+
     }
 }
 
-
-
 void bluetooth_thread()
 {
     while (true)
@@ -394,22 +430,44 @@
 
 void rgb_led_difficulty()
 {
-    difficulty = bnum - 48;
-    //pc.printf("%i\r\n",difficulty);
-    if (difficulty == 1)
+    //pc.printf("%i\r\n",bnum - 48);
+    new_game.new_diff.level = static_cast<DIFF_LEVEL>(bnum - 48);
+    //pc.printf("%i\r\n",new_game.new_diff.level);
+    if (new_game.new_diff.level == EASY)
     {
         myRGBled.write(0.0, 1.0, 0.0); //green
-        diff_selected = true;
+        new_game.new_diff.is_selected = true;
+        new_game.new_diff.ans_time = 20;
+        new_game.new_diff.max_num = 10;
+        new_game.new_diff.num_of_q = 7; // 7
+        new_game.score = 50;
+        new_game.new_diff.score_mult = 10;
     }
-    else if (difficulty == 2)
+    else if (new_game.new_diff.level == MED)
     {
         myRGBled.write(1.0, 0.2, 0.0); //yellow = red + some green
-        diff_selected = true;
+        new_game.new_diff.is_selected = true;
+        new_game.new_diff.ans_time = 15;
+        new_game.new_diff.max_num = 15;
+        new_game.new_diff.num_of_q = 10;
+        new_game.score = 200;
+        new_game.new_diff.score_mult = 50;
     }
-    else if (difficulty == 3)
+    else if (new_game.new_diff.level == HARD)
     {
         myRGBled.write(1.0, 0.0, 0.0); //red
-        diff_selected = true;
+        new_game.new_diff.is_selected = true;
+        new_game.new_diff.ans_time = 10;
+        new_game.new_diff.max_num = 10;
+        new_game.new_diff.num_of_q = 15;
+        new_game.score = 300;
+        new_game.new_diff.score_mult = 100;
+    }
+    else if (new_game.new_diff.level == SCORE)
+    {
+        myRGBled.write(0.5, 0.5, 0.5);
+        new_game.new_diff.is_selected = true;
+        print_high_score();
     }
 }
 
@@ -417,7 +475,7 @@
 {
     while (true)
     {
-        pc.printf("AUDIO\r\n");
+        //pc.printf("AUDIO\r\n");
         wave_file = fopen("/sd/audio/intro.wav", "r");
         waver.play(wave_file);
         fclose(wave_file);
@@ -446,21 +504,116 @@
     }
 }
 
+void write_high_score(int* score_arr){
+    std::ofstream score_file;
+    score_file.open("/sd/score/score.txt");
+    if (score_file.is_open())
+    {
+            //score_file << "300\n200\n100\n";
+            score_file << score_arr[0] << "\n" << score_arr[1] << "\n" << score_arr[2] << "\n";
+            score_file.close();
+    }
+}
+
+
+int* read_high_score()
+{
+    int* score_val = new int[3];
+    //printf("read_high_score\n\r");
+    std::ifstream infile("/sd/score/score.txt");
+    wait(0.2);
+    if (infile.is_open())
+    {
+        std::string line;
+        int i = 0;
+        while (std::getline(infile, line)) {
+            // using printf() in all tests for consistency
+            //printf("%s", line.c_str());
+            score_val[i] = atoi(line.c_str());
+            i++;
+        }
+        infile.close();
+    }
+    pc.printf("%i \n\r", score_val[0]);
+    pc.printf("%i \n\r", score_val[1]);
+    pc.printf("%i \n\r", score_val[2]);
+    
+    return score_val;
+}
+
+void print_high_score(){
+    
+    int* score_arr= read_high_score();
+        
+    uLCD.cls();
+    uLCD.text_height(1);
+    uLCD.text_width(1);
+    uLCD.color(0xF0F6F7);
+    uLCD.locate(4, 1);
+    uLCD.printf("HIGH SCORES");
+    uLCD.locate(3, 6);
+    uLCD.color(0xFC776A);
+    uLCD.printf("1) %i", score_arr[0]);
+    uLCD.locate(3, 8);
+    uLCD.color(0x669DB2);
+    uLCD.printf("2) %i",  score_arr[1]);
+    uLCD.locate(3, 10);
+    uLCD.color(0xFC776A);
+    uLCD.printf("3) %i",  score_arr[2]);
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+    delete[] score_arr;    
+}
+
+void check_new_highscore(){
+    int* new_score_arr = read_high_score();
+    for (int i = 0; i < 3; i++)
+        {
+            if (new_score_arr[i]< new_game.score){
+                int j = i;
+                while(j<2){
+                    new_score_arr[j+1] = new_score_arr[j];
+                    j++;
+                }
+                new_score_arr[i] = new_game.score;
+                pc.printf("high score found");
+                write_high_score(new_score_arr);
+                break;
+            }
+        }
+    delete[] new_score_arr;
+}
+
+void reset_scores(){
+    mkdir("/sd/score", 0777);
+    std::ofstream score_file;
+    score_file.open("/sd/score/score.txt");
+    if (score_file.is_open())
+    {
+            score_file << "0\n0\n0\n";
+            score_file.close();
+    }
+}
+
 void init()
 {
+//    while(1){
+//        reset_scores();
+//        wait(2);
+//    }
     uLCD.baudrate(3000000);
     srand(time(NULL));
     life[0] = 1;
     life[1] = 1;
     life[2] = 1;
-    thread1.start(boot_video_thread);
+    //thread1.start(boot_video_thread);
+    boot_vid = false;
 }
 
+
 int main()
 {
-
     init();
-    pc.printf("MAIN_INIT\r\n\n");
+//    pc.printf("MAIN_INIT\r\n\n");
     thread2.start(wav_thread);
     while (true)
     {
@@ -475,8 +628,7 @@
                 main_screen();
             }
             //pc.printf("MAIN_PRINT\r\n");
-            //break;
-            if (diff_selected == false)
+            if (new_game.new_diff.is_selected == false)
             {
                 thread3.start(bluetooth_thread);
                 rgb_led_difficulty();
@@ -487,14 +639,33 @@
                 break;
             }
         }
-        Thread::wait(200);
+        Thread::wait(100);
     }
-    while (!game_is_over)
-    {
-        game_questions();
-        get_button();
-        check_correct_ans();
+    if(new_game.new_diff.level != SCORE){
+        while (new_game.q_on <= new_game.new_diff.num_of_q)
+        {
+            thread3.terminate();
+            Gen_Question new_q;
+            game_questions(&new_q);
+            get_button();
+            check_correct_ans(new_q);
+            new_game.q_on++;
+            wait(2.2);
+            life_count_check();
+            if(new_game.is_lose == true){
+                game_over();
+                break;
+            }
+        }
+        if(new_game.is_lose == false){
+            win_game();
+        }
+        wait(2.5);
+        new_game.score = new_game.score + new_game.live_left * 100;
+        score_game();
         wait(2);
-        life_count_check();
+        check_new_highscore();
+        wait(0.5);
+        print_high_score();
     }
 }
\ No newline at end of file