Solved the issue I was having.
Here is a quick summary of how I achieve this for anyone who may stumble across this post in the future, with the same problem.
In the end, I decided to go with storing the map in a 2D array. Previously, I had declared a few boolean fields to specify whether or not there is a block on the player’s left or right hand side. As such, as soon the player entered the left or right column of a block, he could no longer be able move in that direction. This usually left a weird gap between the player’s edge and the block.
How I ended up solving this was to change the boolean fields into integer fields. Now, instead of simply setting the fields to true or false, I instead calculated the first wall on either side of the player object by scanning the row the player is in, and stored the wall’s x value (column * tileSize). Then, whenever moving in either direction, I check if the player’s right edge > the right collision x-coordinate, or if the player’s left edge < the left collision x-coordinate.
I used a similar approach to handle jumping. After writing a gravity function which would make the player drop to the ground if he is not already on the ground, I scanned the column the player is on to get the first block under the player. Setting the top of the block as the y coordinate of the ground was all I needed then.
Special thanks to @Hyperion65 for putting me on the right path. Cheers
P.S. Following is the code I used to convert the player’s position in x and y coordinates to row and column integers I could use in the 2D array to get surrounding tiles.
int row = playerY/tileSize;
int col = playerX/tileSize;