The Random object's constructor takes as its parameter a seed value - this object will output numbers via .Next() which are just as random as any other Random object, but two different Random objects with the same seed that have called .Next() the same number of times will generate the same values.
This is good for example in games played by correspondence, which would allow "random" events to occur on all machines playing the game if the various Random objects had all been seeded with the same number at the start of the game.
Although this is useful, it's probably not what you want in the function you provided. By creating a new Random object and seeding it with the same value every time you call in, you'll end up with the same number being put in "n" every time you call the function.
There are two solutions to this. Either use the parameterless constructor (which actually just seeds with the current system time) or store the Random object. When you call .Next() the second time you'll get a randomly different number to the first time you called it and if you store this Random object across calls you'll end up with different values each time you click the button.
Finally, there are two forms of the Next() function. Next() generates a random number between int.MinValue and int.MaxValue, but Next(m,n) generates a number between m and n (i.e. it can returns either m, m+1, m+2,...n-2, n-1 but not n).
You probably want something like this:
Random myRand = new Random();
privatevoid button1_Click(object sender, EventArgs e)
int n = myRand.Next(1,4); // will return 1, 2 or 3.
this.label1.Text = n.ToString();