ECE 2035 Homework
Dependencies: mbed wave_player 4DGL-uLCD-SE MMA8452
Revision 4:e3fbc74a3783, committed 2019-11-14
- Comitter:
- zkang0729
- Date:
- Thu Nov 14 17:14:37 2019 +0000
- Parent:
- 3:e4690ad5a4d2
- Commit message:
- Initial Commit;
Changed in this revision
--- 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 ↦ + // There's only one map + return ↦ } -Map* set_active_map(int m) +Map *set_active_map(int m) { - active_map = m; - return ↦ + active_map = m; + return ↦ } 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) { }