It makes me think about fractals - after the border in a set of julia or something like that.
If N is 1000, use a 2 ^ 500 x 2 ^ 500 fractal bitmap (obviously, do not generate it in advance - you can get each pixel on demand, and most of them will not be needed). Each pixel movement is one pixel up, down, left, or right, following the border between the pixels, as a simple algorithm for tracing a raster image. Until you start from the edge of the bitmap, you should return to the edge of the bitmap sooner or later - after a certain “color” border you should always give a closed curve without self-intersections if you look at an unlimited version of this fractal.
The x and y axes of the bitmap, of course, will need the "gray coding" coordinates, a bit like oversized Carnot maps. Each step in the trace (one pixel up, down, left, or right) corresponds to a one-bit change in one raster coordinate and, therefore, in one bit of the resulting values in a random walk.
EDIT
I just realized that the problem. The more wrinkled the border, the more likely you are to trace to get to the point where you have a choice of directions, for example ...
* | . ---+--- . | *
In which direction you are entering this point, you have a choice of three options. Choose the wrong one of the other two, and you can go back to this point, so this is a possible intersection point and possible repetition. You can eliminate the option of “continuing in one direction” - depending on how you turn, you should keep the same border colors to the left and right of your border path as you trace, but this still leaves choice in two directions.
I think that the problem can be eliminated by making at least three colors in the fractal and always preserving the same color on one specific side (relative to the direction of the trace) of the border. Maybe "while the fractal is not too wrinkled," however.
The final fix is to keep track of the points where this choice was available. If you return to the same point, step back and take another alternative.