You also shouldn't need to duplicate tiles in order to achieve wrapping; instead you should just wrap your math. This is just OTOH:
Given:
grid_width //number of tiles in world, horizontally
tile_width //horizontal size of each tile, in pixels
Let:
world_width = grid_width*tile_width; //width of the world, in pixels
max_delta_x = world_width/2; //used for wrapping
In order to collide a tile vs an object (e.g the player), consider the tile from the object's point-of-view:
delta_x = tile_x - object_x;
This is a "raw" delta pointing from the object to the tile; it might be pointing in the wrong direction. We now wrap the delta so that it points from player to tile in the shortest direction (i.e if it's shorter to wrap around one of the edges of the world, this will wrap the delta vector):
if(delta_x > max_delta_x)
{
//delta is pointing right but it's shorter to go left
delta_x -= world_width;
}
else if(delta_x < -max_delta_x)
{
//delta is pointing left but it's shorter to go right
delta_x += world_width;
}
The tile's position along the x axis, relative to the object, is delta_x -- use this as its position for collision/etc. and you won't need to duplicate it, because the vector is wrapped in the correct way. For the y axis, if you want it to wrap just do the same thing, or if you don't want it to wrap just use the "raw" delta.
Note that there may be a simpler/smarter/better way to model the wrapping behaviour, but my example should work; the important concept is that you just need to work in a coordinate system that wraps, you don't need to explicitly duplicate objects or anything like that.
Imagine that positions in x are mapped to points along a circle (i.e you're looking down from above) -- there will always be two ways to get from A to B, clockwise and counter-clockwise; for collision you only need to care about the shortest way. And you know the shortest path has to be at most half the width of the world -- otherwise the other direction is shorter.
I hope this makes sense..