ECE 2035 Homework

Dependencies:   mbed wave_player 4DGL-uLCD-SE MMA8452

Files at this revision

API Documentation at this revision

Comitter:
zkang0729
Date:
Thu Nov 14 17:14:37 2019 +0000
Parent:
3:e4690ad5a4d2
Commit message:
Initial Commit;

Changed in this revision

hash_table.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
map.cpp Show annotated file Show diff for this revision Revisions of this file
speech.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/hash_table.cpp	Mon Oct 28 05:26:35 2019 +0000
+++ b/hash_table.cpp	Thu Nov 14 17:14:37 2019 +0000
@@ -1,6 +1,6 @@
 /*
- Student Name:
- Date:
+ Student Name: Zixuan Kang
+ Date: 2019-10-25
 
 =======================
 ECE 2035 Project 2-1:
@@ -126,7 +126,16 @@
 * @return The pointer to the hash table entry
 */
 static HashTableEntry* createHashTableEntry(unsigned int key, void* value) {
+  //Allocate memort for the new HashTableEntry struct on heap
+  HashTableEntry* newHashTableEntry = (HashTableEntry*)malloc(sizeof(HashTableEntry));
+  
+  //Initialize the components of the new HashTableEntry stuct
+  newHashTableEntry->key = key;
+  newHashTableEntry->value = value;
+  newHashTableEntry->next = NULL;
 
+  //Return the HashTableEntry struct.
+  return newHashTableEntry;
 }
 
 /**
@@ -140,7 +149,19 @@
 * @return The pointer to the hash table entry, or NULL if key does not exist
 */
 static HashTableEntry* findItem(HashTable* hashTable, unsigned int key) {
-
+  int i;
+  HashTableEntry *thisHashTableEntry;
+  for(i = 0; i < hashTable->num_buckets; i++) { // Go through each linked lsit
+    thisHashTableEntry = hashTable->buckets[i];
+    while (thisHashTableEntry) {
+      if (thisHashTableEntry->key != key) {
+        thisHashTableEntry = thisHashTableEntry->next; // If the keys don't match go to the next one
+      } else {
+        return thisHashTableEntry;
+      }
+    }
+  }
+  return NULL;
 }
 
 /****************************************************************************
@@ -167,7 +188,7 @@
   newTable->num_buckets = numBuckets;
   newTable->buckets = (HashTableEntry**)malloc(numBuckets*sizeof(HashTableEntry*));
 
-  // As the new buckets are empty, init each bucket as NULL.
+  // As the new buckets contain indeterminant values, init each bucket as NULL.
   unsigned int i;
   for (i=0; i<numBuckets; ++i) {
     newTable->buckets[i] = NULL;
@@ -178,21 +199,71 @@
 }
 
 void destroyHashTable(HashTable* hashTable) {
-
+  int i;
+  HashTableEntry *t1, *t2;
+  for (i = 0; i < hashTable->num_buckets; i++) {
+    t1 = hashTable->buckets[i];
+    while (t1) {
+      t2 = t1; // Sign it to a temporary variable
+      t1 = t1->next; // Assign the next one to t1
+      free(t2->value); // Free the value
+      free(t2); // Free the node
+    }
+  }
+  free(hashTable->buckets); // Free the bucket
+  free(hashTable); // Free the hashtable
 }
 
 void* insertItem(HashTable* hashTable, unsigned int key, void* value) {
-
+  HashTableEntry *thisHashTableEntry;
+  if ((thisHashTableEntry = findItem(hashTable, key))) {
+    //Key in list
+    void *temp = thisHashTableEntry->value; // Get the initial value of the entry point
+    thisHashTableEntry->value = value;
+    return temp;
+  }
+  //Key not in list
+  thisHashTableEntry = createHashTableEntry(key, value);
+  if (!thisHashTableEntry) return NULL; //Malloc failed
+  thisHashTableEntry->next = hashTable->buckets[hashTable->hash(key)];
+  hashTable->buckets[hashTable->hash(key)] = thisHashTableEntry; // Insert the node at the head of the linked list
+  return thisHashTableEntry->value;
 }
 
 void* getItem(HashTable* hashTable, unsigned int key) {
-
+  if (findItem(hashTable, key) == NULL) {
+    return NULL;
+  } else {
+    return findItem(hashTable, key)->value; // return the value of the elemnt that has the key
+  }
 }
 
 void* removeItem(HashTable* hashTable, unsigned int key) {
-
+  HashTableEntry *thisHashTableEntry = hashTable->buckets[hashTable->hash(key)];
+  HashTableEntry *temp;
+  if (!thisHashTableEntry) return NULL;
+  //If the node is at the head of the linked list
+  if (thisHashTableEntry->key == key) {
+    hashTable->buckets[hashTable->hash(key)] = thisHashTableEntry->next;
+    temp = thisHashTableEntry;
+    free(thisHashTableEntry);
+    return temp->value;
+  }
+  // If the node is not at the head of the linked list
+  while (thisHashTableEntry->next) {
+    if (thisHashTableEntry->next->key == key) {
+      //Split the linked list
+      temp = thisHashTableEntry->next;
+      thisHashTableEntry->next = thisHashTableEntry->next->next;
+      free(thisHashTableEntry->next);
+      return temp->value;
+    }
+    thisHashTableEntry = thisHashTableEntry->next;
+  }
+  return NULL;
 }
 
 void deleteItem(HashTable* hashTable, unsigned int key) {
-
-}
\ No newline at end of file
+  free(removeItem(hashTable, key));
+  return;
+}
--- a/main.cpp	Mon Oct 28 05:26:35 2019 +0000
+++ b/main.cpp	Thu Nov 14 17:14:37 2019 +0000
@@ -6,21 +6,22 @@
 #include "speech.h"
 
 // Functions in this file
-int get_action (GameInputs inputs);
-int update_game (int action);
-void draw_game (int init);
-void init_main_map ();
-int main ();
+int get_action(GameInputs inputs);
+int update_game(int action);
+void draw_game(int init);
+void init_main_map();
+int main();
 
 /**
  * The main game state. Must include Player locations and previous locations for
  * drawing to work properly. Other items can be added as needed.
  */
-struct {
-    int x,y;    // Current locations
-    int px, py; // Previous locations
-    int has_key;
-    // You can add other properties for the player here
+struct
+{
+  int x, y;   // Current locations
+  int px, py; // Previous locations
+  int has_key;
+  // You can add other properties for the player here
 } Player;
 
 /**
@@ -36,7 +37,7 @@
 #define GO_DOWN 6
 int get_action(GameInputs inputs)
 {
-    return NO_ACTION;
+  return NO_ACTION;
 }
 
 /**
@@ -53,23 +54,34 @@
 #define FULL_DRAW 2
 int update_game(int action)
 {
-    // Save player previous location before updating
-    Player.px = Player.x;
-    Player.py = Player.y;
-    
-    // Do different things based on the each action.
-    // You can define functions like "go_up()" that get called for each case.
-    switch(action)
-    {
-        case GO_UP:     break;
-        case GO_LEFT:   break;            
-        case GO_DOWN:   break;
-        case GO_RIGHT:  break;
-        case ACTION_BUTTON: break;
-        case MENU_BUTTON: break;
-        default:        break;
-    }
-    return NO_RESULT;
+  // Save player previous location before updating
+  Player.px = Player.x;
+  Player.py = Player.y;
+
+  // Do different things based on the each action.
+  // You can define functions like "go_up()" that get called for each case.
+  switch (action)
+  {
+  case GO_UP:
+    Player.y != 0 && Player.y - 1;
+    break;
+  case GO_LEFT:
+    Player.x != 0 && Player.x - 1;
+    break;
+  case GO_DOWN:
+    Player.y != map_height() && Player.y + 1;
+    break;
+  case GO_RIGHT:
+    Player.x != map_width() && Player.x + 1;
+    break;
+  case ACTION_BUTTON:
+    break;
+  case MENU_BUTTON:
+    break;
+  default:
+    break;
+  }
+  return NO_RESULT;
 }
 
 /**
@@ -80,67 +92,68 @@
  */
 void draw_game(int init)
 {
-    // Draw game border first
-    if(init) draw_border();
-    
-    // Iterate over all visible map tiles
-    for (int i = -5; i <= 5; i++) // Iterate over columns of tiles
+  // Draw game border first
+  if (init)
+    draw_border();
+
+  // Iterate over all visible map tiles
+  for (int i = -5; i <= 5; i++) // Iterate over columns of tiles
+  {
+    for (int j = -4; j <= 4; j++) // Iterate over one column of tiles
     {
-        for (int j = -4; j <= 4; j++) // Iterate over one column of tiles
+      // Here, we have a given (i,j)
+
+      // Compute the current map (x,y) of this tile
+      int x = i + Player.x;
+      int y = j + Player.y;
+
+      // Compute the previous map (px, py) of this tile
+      int px = i + Player.px;
+      int py = j + Player.py;
+
+      // Compute u,v coordinates for drawing
+      int u = (i + 5) * 11 + 3;
+      int v = (j + 4) * 11 + 15;
+
+      // Figure out what to draw
+      DrawFunc draw = NULL;
+      if (init && i == 0 && j == 0) // Only draw the player on init
+      {
+        draw_player(u, v, Player.has_key);
+        continue;
+      }
+      else if (x >= 0 && y >= 0 && x < map_width() && y < map_height()) // Current (i,j) in the map
+      {
+        MapItem *curr_item = get_here(x, y);
+        MapItem *prev_item = get_here(px, py);
+        if (init || curr_item != prev_item) // Only draw if they're different
         {
-            // Here, we have a given (i,j)
-            
-            // Compute the current map (x,y) of this tile
-            int x = i + Player.x;
-            int y = j + Player.y;
-            
-            // Compute the previous map (px, py) of this tile
-            int px = i + Player.px;
-            int py = j + Player.py;
-                        
-            // Compute u,v coordinates for drawing
-            int u = (i+5)*11 + 3;
-            int v = (j+4)*11 + 15;
-            
-            // Figure out what to draw
-            DrawFunc draw = NULL;
-            if (init && i == 0 && j == 0) // Only draw the player on init
-            {
-                draw_player(u, v, Player.has_key);
-                continue;
-            }
-            else if (x >= 0 && y >= 0 && x < map_width() && y < map_height()) // Current (i,j) in the map
-            {
-                MapItem* curr_item = get_here(x, y);
-                MapItem* prev_item = get_here(px, py);
-                if (init || curr_item != prev_item) // Only draw if they're different
-                {
-                    if (curr_item) // There's something here! Draw it
-                    {
-                        draw = curr_item->draw;
-                    }
-                    else // There used to be something, but now there isn't
-                    {
-                        draw = draw_nothing;
-                    }
-                }
-            }
-            else if (init) // If doing a full draw, but we're out of bounds, draw the walls.
-            {
-                draw = draw_wall;
-            }
+          if (curr_item) // There's something here! Draw it
+          {
+            draw = curr_item->draw;
+          }
+          else // There used to be something, but now there isn't
+          {
+            draw = draw_nothing;
+          }
+        }
+      }
+      else if (init) // If doing a full draw, but we're out of bounds, draw the walls.
+      {
+        draw = draw_wall;
+      }
 
-            // Actually draw the tile
-            if (draw) draw(u, v);
-        }
+      // Actually draw the tile
+      if (draw)
+        draw(u, v);
     }
+  }
 
-    // Draw status bars    
-    draw_upper_status();
-    draw_lower_status();
+  // Draw status bars
+  draw_upper_status();
+  draw_lower_status();
 }
 
-
 /**
  * Initialize the main world map. Add walls around the edges, interior chambers,
  * and plants in the background so you can see motion. Note: using the similar
@@ -148,22 +161,22 @@
  */
 void init_main_map()
 {
-    // "Random" plants
-    Map* map = set_active_map(0);
-    for(int i = map_width() + 3; i < map_area(); i += 39)
-    {
-        add_plant(i % map_width(), i / map_width());
-    }
-    pc.printf("plants\r\n");
-        
-    pc.printf("Adding walls!\r\n");
-    add_wall(0,              0,              HORIZONTAL, map_width());
-    add_wall(0,              map_height()-1, HORIZONTAL, map_width());
-    add_wall(0,              0,              VERTICAL,   map_height());
-    add_wall(map_width()-1,  0,              VERTICAL,   map_height());
-    pc.printf("Walls done!\r\n");
+  // "Random" plants
+  Map *map = set_active_map(0);
+  for (int i = map_width() + 3; i < map_area(); i += 39)
+  {
+    add_plant(i % map_width(), i / map_width());
+  }
+  pc.printf("plants\r\n");
 
-    print_map();
+  pc.printf("Adding walls!\r\n");
+  add_wall(0, 0, HORIZONTAL, map_width());
+  add_wall(0, map_height() - 1, HORIZONTAL, map_width());
+  add_wall(0, 0, VERTICAL, map_height());
+  add_wall(map_width() - 1, 0, VERTICAL, map_height());
+  pc.printf("Walls done!\r\n");
+
+  print_map();
 }
 
 /**
@@ -174,36 +187,49 @@
  */
 int main()
 {
-    // First things first: initialize hardware
-    ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");
+  //Game Over Indication
+  unsigned int GameOver = 0;
+  
+  // First things first: initialize hardware
+  ASSERT_P(hardware_init() == ERROR_NONE, "Hardware init failed!");
 
-    // Initialize the maps
-    maps_init();
-    init_main_map();
-    
-    // Initialize game state
-    set_active_map(0);
-    Player.x = Player.y = 5;
+  // Initialize the maps
+  maps_init();
+  init_main_map();
 
-    // Initial drawing
-    draw_game(true);
+  // Initialize game state
+  set_active_map(0);
+  Player.x = Player.y = 5;
+
+  // Initial drawing
+  draw_game(true);
 
-    // Main game loop
-    while(1)
-    {
-        // Timer to measure game update speed
-        Timer t; t.start();
-        
-        // Actuall do the game update:
-        // 1. Read inputs        
-        // 2. Determine action (get_action)        
-        // 3. Update game (update_game)
-        // 3b. Check for game over
-        // 4. Draw frame (draw_game)
-        
-        // 5. Frame delay
-        t.stop();
-        int dt = t.read_ms();
-        if (dt < 100) wait_ms(100 - dt);
-    }
+  // Main game loop
+  while (!GameOver)
+  {
+    // Timer to measure game update speed
+    Timer t;
+    t.start();
+
+    // Actuall do the game update:
+    // 1. Read inputs
+    //inputs = read_inputs();
+    
+    // 2. Determine action (get_action)
+    //action = get_action(input);
+    
+    // 3. Update game (update_game)
+    //next_state = update_game(action);
+    
+    // 3b. Check for game over
+    
+    
+    // 4. Draw frame (draw_game)
+
+    // 5. Frame delay
+    t.stop();
+    int dt = t.read_ms();
+    if (dt < 100)
+      wait_ms(100 - dt);
+  }
 }
--- a/map.cpp	Mon Oct 28 05:26:35 2019 +0000
+++ b/map.cpp	Thu Nov 14 17:14:37 2019 +0000
@@ -7,9 +7,10 @@
  * The Map structure. This holds a HashTable for all the MapItems, along with
  * values for the width and height of the Map.
  */
-struct Map {
-    HashTable* items;
-    int w, h;
+struct Map
+{
+  HashTable *items;
+  int w, h;
 };
 
 /**
@@ -25,8 +26,9 @@
  * key information (x, y) into a one-dimensional unsigned integer.
  * This function should uniquely map (x,y) onto the space of unsigned integers.
  */
-static unsigned XY_KEY(int X, int Y) {
-    // TODO: Fix me!
+static unsigned XY_KEY(int X, int Y)
+{
+  return Y * map_width() + X;
 }
 
 /**
@@ -36,103 +38,116 @@
  */
 unsigned map_hash(unsigned key)
 {
-    // TODO: Fix me!
+  return key % map_width();
 }
 
 void maps_init()
 {
-    // TODO: Implement!    
-    // Initialize hash table
-    // Set width & height
+  HashTable *hash_map = createHashTable(map_hash, 50);
+  map.items = hash_map;
+  map.w = 50;
+  map.h = 50;
 }
 
-Map* get_active_map()
+Map *get_active_map()
 {
-    // There's only one map
-    return &map;
+  // There's only one map
+  return &map;
 }
 
-Map* set_active_map(int m)
+Map *set_active_map(int m)
 {
-    active_map = m;
-    return &map;
+  active_map = m;
+  return &map;
 }
 
 void print_map()
 {
-    // As you add more types, you'll need to add more items to this array.
-    char lookup[] = {'W', 'P'};
-    for(int y = 0; y < map_height(); y++)
+  // As you add more types, you'll need to add more items to this array.
+  char lookup[] = {'W', 'P'};
+  for (int y = 0; y < map_height(); y++)
+  {
+    for (int x = 0; x < map_width(); x++)
     {
-        for (int x = 0; x < map_width(); x++)
-        {
-            MapItem* item = get_here(x,y);
-            if (item) pc.printf("%c", lookup[item->type]);
-            else pc.printf(" ");
-        }
-        pc.printf("\r\n");
+      MapItem *item = get_here(x, y);
+      if (item)
+        pc.printf("%c", lookup[item->type]);
+      else
+        pc.printf(" ");
     }
+    pc.printf("\r\n");
+  }
 }
 
 int map_width()
 {
+  return map.w;
 }
 
 int map_height()
 {
+  return map.h;
 }
 
 int map_area()
 {
+  return map_height() * map_width();
 }
 
-MapItem* get_north(int x, int y)
+MapItem *get_north(int x, int y)
 {
+  return (MapItem *)getItem(map.items, XY_KEY(x, y - 1));
 }
 
-MapItem* get_south(int x, int y)
+MapItem *get_south(int x, int y)
 {
+  return (MapItem *)getItem(map.items, XY_KEY(x, y + 1));
 }
 
-MapItem* get_east(int x, int y)
+MapItem *get_east(int x, int y)
 {
+  return (MapItem *)getItem(map.items, XY_KEY(x + 1, y));
 }
 
-MapItem* get_west(int x, int y)
+MapItem *get_west(int x, int y)
 {
+  return (MapItem *)getItem(map.items, XY_KEY(x - 1, y));
 }
 
-MapItem* get_here(int x, int y)
+MapItem *get_here(int x, int y)
 {
+  return (MapItem *)getItem(map.items, XY_KEY(x, y));
 }
 
-
 void map_erase(int x, int y)
 {
+  removeItem(map.items, XY_KEY(x, y));
 }
 
 void add_wall(int x, int y, int dir, int len)
 {
-    for(int i = 0; i < len; i++)
-    {
-        MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
-        w1->type = WALL;
-        w1->draw = draw_wall;
-        w1->walkable = false;
-        w1->data = NULL;
-        unsigned key = (dir == HORIZONTAL) ? XY_KEY(x+i, y) : XY_KEY(x, y+i);
-        void* val = insertItem(get_active_map()->items, key, w1);
-        if (val) free(val); // If something is already there, free it
-    }
+  for (int i = 0; i < len; i++)
+  {
+    MapItem *w1 = (MapItem *)malloc(sizeof(MapItem));
+    w1->type = WALL;
+    w1->draw = draw_wall;
+    w1->walkable = false;
+    w1->data = NULL;
+    unsigned key = (dir == HORIZONTAL) ? XY_KEY(x + i, y) : XY_KEY(x, y + i);
+    void *val = insertItem(get_active_map()->items, key, w1);
+    if (val)
+      free(val); // If something is already there, free it
+  }
 }
 
 void add_plant(int x, int y)
 {
-    MapItem* w1 = (MapItem*) malloc(sizeof(MapItem));
-    w1->type = PLANT;
-    w1->draw = draw_plant;
-    w1->walkable = true;
-    w1->data = NULL;
-    void* val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
-    if (val) free(val); // If something is already there, free it
+  MapItem *w1 = (MapItem *)malloc(sizeof(MapItem));
+  w1->type = PLANT;
+  w1->draw = draw_plant;
+  w1->walkable = true;
+  w1->data = NULL;
+  void *val = insertItem(get_active_map()->items, XY_KEY(x, y), w1);
+  if (val)
+    free(val); // If something is already there, free it
 }
\ No newline at end of file
--- a/speech.cpp	Mon Oct 28 05:26:35 2019 +0000
+++ b/speech.cpp	Thu Nov 14 17:14:37 2019 +0000
@@ -18,9 +18,9 @@
  * @param line The text to display
  * @param which If TOP, the first line; if BOTTOM, the second line.
  */
-#define TOP    0
+#define TOP 0
 #define BOTTOM 1
-static void draw_speech_line(const char* line, int which);
+static void draw_speech_line(const char *line, int which);
 
 /**
  * Delay until it is time to scroll.
@@ -29,29 +29,60 @@
 
 void draw_speech_bubble()
 {
+  uLCD.filled_rectangle(3, 93, 123, 113, GREEN);
+  uLCD.filled_rectangle(4, 94, 122, 112, RED);
 }
 
 void erase_speech_bubble()
 {
 }
 
-void draw_speech_line(const char* line, int which)
+void draw_speech_line(const char *line, int which)
+{
+}
+
+int readPB1(int pb1)
 {
+  GameInputs inputs;
+  inputs = read_inputs();
+  if (inputs.b1 == 0)
+    pb1 = 0;
+  return pb1;
 }
 
 void speech_bubble_wait()
 {
+  int pb1 = 1;
+  while (pb1 == 1)
+  {
+    for (int i = 0; i < 4; i++)
+    {
+      uLCD.filled_circle(120, 15, 4, RED);
+      wait(0.1);
+      pb1 = readPB1(pb1);
+    }
+
+    if (pb1 == 0)
+      break;
+
+    for (int i = 0; i < 4; i++)
+    {
+      uLCD.filled_circle(120, 15, 4, BLACK);
+      wait(0.1);
+      pb1 = readPB1(pb1);
+    }
+  }
 }
 
-void speech(const char* line1, const char* line2)
+void speech(const char *line1, const char *line2)
 {
-    draw_speech_bubble();
-    draw_speech_line(line1, TOP);
-    draw_speech_line(line2, BOTTOM);
-    speech_bubble_wait();
-    erase_speech_bubble();
+  draw_speech_bubble();
+  draw_speech_line(line1, TOP);
+  draw_speech_line(line2, BOTTOM);
+  speech_bubble_wait();
+  erase_speech_bubble();
 }
 
-void long_speech(const char* lines[], int n)
+void long_speech(const char *lines[], int n)
 {
 }