Looking for an example; a 1d array of random numbers


(Kevinabraun) #1

Hi Ardupeople, Has anyone seen an example of 1d arrays of random integers? Any advice is appreciated.

Thank you.

KB


#2

You need to use Arduboy2::initRandomSeed() in the setup() loop to seed the random number generator.

After that you can use the random() function:
https://www.arduino.cc/reference/en/language/functions/random-numbers/random/

Otherwise you might find that your “random” bunch of numbers is always the same random bunch.

You should be able to use direct initialization uniform initialization calling random() for each int in the list. Or you could declare the array and iterate through it assigning the result of random.


(Pharap) #3

It would be interesting to know what you need them for, this could be an X-Y problem.
(I.e. asking how to implement a chosen solution rather than asking what the best solution is to the actual problem.)

What @Freezingsnail says is right, you just need to arduboy.initRandomSeed() (preferably after a titlescreen so there’s a random delay before it’s called), and then fill an array with the result of random.
(I think rand would work too.)

E.g.

constexpr size_t arraySize = 16;
uint8_t array[arraySize];

void randomiseArray()
{
	for(uint8_t index = 0; index < arraySize; ++index)
	{
		array[index] = random();
	}
}

Are you using ‘direct initialisation’ in its technical sense?
If so I’m not sure what you mean by this.


#4

I mean like int randnums[2] {rand(), rand()};
That might not work though I’ve never tried it.
Actually I think I mixed the names up of what type of initialization that is.

Yea I meant uniform, my mistake.


(Pharap) #5

Technically speaking that’s aggregate initialisation, which itself is a form of list initialisation.
But the technical jargon isn’t really important here.
(Frankly I can never remember the difference between initialisation types, I always look it up.)

The important thing is that while that would work if the array was local, if the array were statically allocated (i.e. global) then rand would be being called before main even begins,
so you’d probably get the same sequence every time.

Besides which, if you had a 20 element array, calling rand 20 times would be a bit tedious to type and would probably be compiled into either a loop or (worse in this case) an unrolled loop anyway, so writing a loop is a better option.


(Kevinabraun) #6

Thank you for the replies. As to whether it is an X-Y problem, perhaps. Here’s some more detail: Back in the 80’s in BASIC I wrote a simple graphics routine where I created a 1D array of random integers, then used the graphics commands “plot” and “draw” to use those random integers as X and Y Cartesian coordinates.The result was I was drawing a riverbank, sort of like river raid. So I am looking to re-create that effect.


(Pharap) #7

Ah…

In that case it’s sort of half an X-Y problem.

You can use a 1D array of random numbers like you did back then so asking about that makes sense,
but you still need an equivalent of ‘plot’ and ‘draw’.

I can’t really suggest an equivalent without knowing what those commands do/did.

The ZX81 book I just happen to conviniently have lying around suggests that:

PLOT m, n Blacks in the pixel (|m|, |n); moves the PRINT position to just after that pixel.

But it makes no mention of a DRAW command.

QB64 has a DRAW statement, which seems to be a complex precursor to SVG paths.

I’m guessing on the Arduboy you could use arduboy.drawPixel and arduboy.drawLine to simulate what these would have done, but I can’t be certain.

Also, if the points need to be within a particular range then the random call will need extra arguments.
E.g. to generate points that only appear on screen:

struct Point2
{
	uint8_t x;
	uint8_t y;
};

constexpr size_t pointCount = 16;
Point2 points[pointCount];

void randomisePoints()
{
	for(uint8_t index = 0; index < pointCount; ++index)
	{
		points[index].x = random(0, WIDTH);
		points[index].y = random(0, HEIGHT);
	}
}

(Kevinabraun) #8

Nice. yes, the Arduboy.drawLine is indeed what I intended to use. And you are also correct that I will need to range the values. That said, is my emulating an old technique well, sub-optimal?


(Kevinabraun) #9

I guess I am prototyping in my mind in BASIC, because that’s what I am most familiar with:
store an array of 100 random integers in memory using a for-next loop then use another for-next loop to plot a few x,y points and draw lines connecting them.


(Pharap) #10

Not necessarily.

Drawing shapes can be quite processor intensive,
but at the moment I’m assuming there’s no other way to do it.

I don’t know what the final thing is supposed to look like.
I’m presuming that’s all there is to it - generate a series of random points and then draw lines between them.

In C++ it’s just a for loop.
C++ uses braces to indicate scope rather than an end keyword.

On the Arduboy you won’t need to plot the points, you can just draw the lines using the data.


I’m assuming this is the sort of thing you’re trying to do:

#include <Arduboy2.h>

Arduboy2 arduboy;

struct Point2
{
	uint8_t x;
	uint8_t y;
};

constexpr size_t pointCount = 16;
Point2 points[pointCount];

void randomisePoints()
{
	for(uint8_t index = 0; index < pointCount; ++index)
	{
		points[index].x = random(0, WIDTH);
		points[index].y = random(0, HEIGHT);
	}
}

void drawPoints()
{
	Point2 previousPoint = points[0];
	for(uint8_t index = 1; index < pointCount; ++index)
	{
		Point2 currentPoint = points[index];
		arduboy.drawLine(previousPoint.x, previousPoint.y, currentPoint.x, currentPoint.y);
		previousPoint = currentPoint;
	}
}

void setup()
{
	arduboy.begin();
}

void loop()
{
	if(!arduboy.nextFrame())
		return;
		
	arduboy.pollButtons();
	
	if(arduboy.pressed(A_BUTTON))
	{
		arduboy.initRandomSeed();
		randomisePoints();
	}
	
	arduboy.clear();
	
	drawPoints();
	
	arduboy.display();
}

But I’m guessing you want the points sorted by x so they draw a line across the screen instead of jumping about…
In which case, something more like this:

#include <Arduboy2.h>

Arduboy2 arduboy;

struct Point2
{
	uint8_t x;
	uint8_t y;
};

constexpr size_t pointCount = 16;
Point2 points[pointCount];

void randomisePoints()
{
	constexpr uint8_t xStep = (WIDTH / pointCount);

	int16_t x = 0;
	for(uint8_t index = 0; index < pointCount; ++index)
	{
		points[index].x = (x + random(-4, 4));
		points[index].y = random(0, HEIGHT);
		x += xStep;
	}
	
	points[0].x = 0;
	points[pointCount - 1].x = (WIDTH - 1);
}

void drawPoints()
{
	Point2 previousPoint = points[0];
	for(uint8_t index = 1; index < pointCount; ++index)
	{
		Point2 currentPoint = points[index];
		arduboy.drawLine(previousPoint.x, previousPoint.y, currentPoint.x, currentPoint.y);
		previousPoint = currentPoint;
	}
}

void setup()
{
	arduboy.begin();
}

void loop()
{
	if(!arduboy.nextFrame())
		return;
		
	arduboy.pollButtons();
	
	if(arduboy.pressed(A_BUTTON))
	{
		arduboy.initRandomSeed();
		randomisePoints();
	}
	
	arduboy.clear();
	
	drawPoints();
	
	arduboy.display();
}

(Kevinabraun) #11

Wow, that is excellent. Thank you. Let me poke it, prod it and mess with it in order to understand it fully.