I am kinda stuck and I need help.
My goal is to make a little "game". It should have 3 pictureboxes and it should randomly display/change numbers (pictures) 1 to 6 every 0,5sec. When I hit STOP, it should stop the numbers and I should get points (score) based on nubmers. 3 same numbers = +10 points, 2 same numbers = +5 points, no same numbers = -5 points. Then it should display highest score achieved (Max Score).
http://i.imgur.com/kubQBST.png
Please, give me some tips what to do.
Thanks a lot, regards Peter
You can use a Timer with random something like this :
Random rnd1 = new Random(Environment.TickCount);
Image[] Images = new Image[6];
int[] CurrentStatus = new int [3];
Images[0] = Image.FromFile("FileNameFornumber1");
Images[1] = Image.FromFile("FileNameFornumber2");
Images[2] = Image.FromFile("FileNameFornumber3");
Images[3] = Image.FromFile("FileNameFornumber4");
Images[4] = Image.FromFile("FileNameFornumber5");
Images[5] = Image.FromFile("FileNameFornumber6");
//change numbers every tick
private Timer_TickHandler(object sender, EventArgs e)
{
this.CurrentState[0] = rnd1.Next(1, 6);
this.CurrentState[1] = rnd1.Next(1, 6);
this.CurrentState[2] = rnd1.Next(1, 6);
this.PictureBox1.Image = Images[this.CurrentStatus[0]-1];
this.PictureBox2.Image = Images[this.CurrentStatus[1]-1];
this.PictureBox3.Image = Images[this.CurrentStatus[2]-1];
}
you have to write an event for the stop button to deactivate the timer and calculate the score based on the CurrentStatus Array and I think the calculation alg must be like this :
int score = this.CurrentStatus.Sum();
if (this.CurrentStatus[0] == this.CurrentStatus[1] && this.CurrentStatus[1] == this.CurrentStatus[2])
score +=10;
else
{
for (int i=0; i<3; i++)
{
for (int j=i+1; j<3; j++)
{
if (this.CurrentStatus[i] == this.CurrentStatus[j])
{
score+=5;
break;
}
}
}
}
for start make random picture on button press.
How add images into resources
For example
public partial class Form1 : Form
{
List<Bitmap> picturesList = new List<Bitmap>(); //Array of pictures
Random random = new Random();
public Form1()
{
InitializeComponent();
//Load all pictures from resources into array
picturesList.Add(Properties.Resources.pic1);
picturesList.Add(Properties.Resources.pic2);
picturesList.Add(Properties.Resources.pic3);
//Set random image into picture box
RandomChangeImage();
}
public void RandomChangeImage()
{
//Generate random number. (random index between 0 - array.count )
int randomIndex = random.Next(0, picturesList.Count);
//Set random image from array
YourPictureBoxName.Image = picturesList[randomIndex];
}
}
Now you can use RandomChangeImage(); in your code. Aflter you done you can continue with timer.
Now add Timer from toolbox into designer.
Double click on timer.
It generated this
private void timer1_Tick(object sender, EventArgs e)
{
//Call random change image
RandomChangeImage();
}
in you buttonstart_Click call timer1.Start(); for example
private void btnStart_Click(object sender, EventArgs e)
{
timer1.Start();
}
if you want change tick in timer you can use
timer1.Interval = 500; for 0.5s. where you want.
if you want stop timer use
timer1.Stop();
Related
I have created an array of labels to be visible with a buttons click but yet since I have many buttons I want to assign a button to make only one label visible
I am having trouble with making a button making more than one label visible
This is the code I used :
var labels = Controls.OfType<Label>().ToArray();
//And then randomly make on of them visible.
var random = new Random();
var label = labels[random.Next(0, labels.Count - 1)];
label.Visible = true;
In Winforms you can simply declare a private Random variable, and then in the Click event of one of your buttons, you can choose a random number that's within the valid index range of the label array, something like:
private Label[] labels = new Label[10]; // Presumably this array is filled somewhere
private Random rnd = new Random();
private void Form1_Load(object sender, EventArgs e)
{
for(int i = 0; i < labels.Length; i++)
{
labels[i] = new Label
{
Height = 20,
Left = 10,
Name = $"Label{i}",
Tag = i,
Text = $"Label{i}",
Top = 10 + 20 * i,
Visible = false
};
this.Controls.Add(labels[i]);
}
}
private void button1_Click(object sender, EventArgs e)
{
if (labels != null && labels.Length > 0)
{
// If needed, this will hide any currently visible labels in the array
foreach(var label in labels.Where(label => label != null && label.Visible))
{
label.Visible = false;
}
// Pick a random label and make it visible
labels[rnd.Next(0, labels.Length)].Visible = true;
}
}
My program creates 5 different labels with a cube form and they just drop down. When I press on them, they come invisible. I want to check if all of them are invisible, but don't know how to do so. Tried going through this site, found a solution with bool, but it just doesn't work my way. Also when my labels appear,you can see only 4 of them.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Label [] kubeliai = new Label [5];
int poz = 100;
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < kubeliai.Length; i++)
{
kubeliai[i] = new Label();
Controls.Add(kubeliai[i]);
Random pos = new Random();
kubeliai[i].Top = 50;
kubeliai[i].Left = poz;
poz += pos.Next(50, 200);
kubeliai[i].BackColor = Color.Red;
kubeliai[i].Height = 20;
kubeliai[i].Width = 20;
kubeliai[i].Click += new EventHandler(kubelio_clickas);
}
Timer kritimo_laikrodis = new Timer();
kritimo_laikrodis.Interval = 10;
kritimo_laikrodis.Tick += new EventHandler(laikrodis);
kritimo_laikrodis.Enabled = true;
}
void kubelio_clickas (object sender, EventArgs e)
{
((Label)sender).Visible = false;
}
void laikrodis (object sender, EventArgs e)
{
for (int i = 0; i < kubeliai.Length; i++)
{
kubeliai[i].Top += 1;
if (kubeliai.All.Visible == false) // this is an error
{
kubeliai[i].Visible = true;
kubeliai[i].Top = 50;
Random pos = new Random();
poz += pos.Next(50, 200);
}
}
}
Using Linq you can check if all are invisible in this way
var areAllInvisible = kubeliai.All(l => l.Visible == false);
if (areAllInvisible)
{
// do something
}
when my labels appear you can see only 4 of them.
That's because the way you are picking random numbers is picking the same numbers each time and you are therefore placing your labels on top of each other. Read the first paragraph of the Random() documentation:
Different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. This problem can be avoided by using a single Random object to generate all random numbers.
Use new Random() once in your class definition like this:
Label [] kubeliai = new Label [5];
Random pos = new Random();
And remove it everywhere else in your program.
I have a PictueBox and I have some dice, I would like to play an animation for the "rolling" of the dice, I did a .gif with the dice, but after the dice stop rolling, I want the actual dice number that I got, I have a random funcion that handles that.
My question is, I press the "Roll Dice" button, it plays the animation and after the animation ends I should set int the picturebox the dice that actually came. but it immediately chnages to the dice number that actually came, skipping the animation;
This is how it works:
dice1.Image = Resources.DiceAnimation; //Here the gif is called to be played
int x = rollDice(); //Here I roll the dice
switch (x){
case 1: dice.Image = resources.diceFace1; //Image set depending on x
break
case 2: //etc...
}
There might be two things needed to do that.
Firstly, you may need to ensure that your PictureBox receives a gif image and it knows it. To do this, please check this answer and this answer. The posts have code to show GifImage frame by frame:
public class GifImage
{
private Image gifImage;
private FrameDimension dimension;
private int frameCount;
private int currentFrame = -1;
private bool reverse;
private int step = 1;
public GifImage(string path)
{
gifImage = Image.FromFile(path);
//initialize
dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
//gets the GUID
//total frames in the animation
frameCount = gifImage.GetFrameCount(dimension);
}
public bool ReverseAtEnd {
//whether the gif should play backwards when it reaches the end
get { return reverse; }
set { reverse = value; }
}
public Image GetNextFrame()
{
currentFrame += step;
//if the animation reaches a boundary...
if (currentFrame >= frameCount || currentFrame < 1) {
if (reverse) {
step *= -1;
//...reverse the count
//apply it
currentFrame += step;
}
else {
currentFrame = 0;
//...or start over
}
}
return GetFrame(currentFrame);
}
public Image GetFrame(int index)
{
gifImage.SelectActiveFrame(dimension, index);
//find the frame
return (Image)gifImage.Clone();
//return a copy of it
}
}
Use it like this (note that you need a Timer object):
private GifImage gifImage = null;
private string filePath = #"C:\Users\Jeremy\Desktop\ExampleAnimation.gif";
public Form1()
{
InitializeComponent();
//a) Normal way
//pictureBox1.Image = Image.FromFile(filePath);
//b) We control the animation
gifImage = new GifImage(filePath);
gifImage.ReverseAtEnd = false; //dont reverse at end
}
private void button1_Click(object sender, EventArgs e)
{
//Start the time/animation
timer1.Enabled = true;
}
//The event that is animating the Frames
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Image = gifImage.GetNextFrame();
}
Secondly, to know how long you want to run your GIF image, you may need to Get Frame Duration of GIF image like this:
double delayIn10Ms; //declare somewhere
//Initialize on your form load
PropertyItem item = img.GetPropertyItem (0x5100); // FrameDelay in libgdiplus
// Time is in 1/100th of a second
delayIn10Ms = (item.Value [0] + item.Value [1] * 256) * 10;
Then use the delayIn10Ms time plus, probably, a little bit more time to stop your timer. You may also want to check when was the last time your timer Ticks and store it. If it exceeds the given delay time, then you should stop your timer and start it again on dice roll, after image assignment in your switch case.
DateTime currentTick = DateTime.Min;
DateTime startTick = DateTime.Min;
private void timer1_Tick(object sender, EventArgs e)
{
currentTick = DateTime.Now;
if ((currentTick - startTick).TotalSeconds / 100 < delayIn10Ms)
pictureBox1.Image = gifImage.GetNextFrame();
else
timer1.Stop(); //stop the timer
}
//And somewhere else you have
timer1.Start(); //to start the timer
int x = rollDice(); //Here I roll the dice
switch (x){
case 1: dice.Image = resources.diceFace1; //Image set depending on x
break
case 2: //etc...
}
You can make a timer with the Interval property set to the length of the animation and set it's Tag to 0 and in the timer write the code:
if(timer.Tag == "0")
timer.Tag == "1";
else if(timer.Tag == "1")
{
int x = rollDice();
switch (x)
{
case 1: dice.Image = resources.diceFace1; break;
case 2: //etc...
}
timer.Tag == "0";
timer.Stop();
}
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
I am trying to create a dynamically added array of user-controls where each one will have a random color assigned to it to make the user more able to differentiate it from others, but when I do that it produces pattern of colors. It will create 10 of the user-controls with the same color then it will change the color for the next 10, I want each separate one to have a different color.
The code for the user-control:
public partial class EquationBox : UserControl
{
public EquationBox()
{
InitializeComponent();
this.panel4.BackColor = RandomColor();
}
private void button1_Click(object sender, EventArgs e)
{
this.Visible = false;
this.textBox1.Text = "";
}
private Color RandomColor()
{
Random rnd = new Random();
/*KnownColor[] names = (KnownColor[])Enum.GetValues(typeof(KnownColor));
KnownColor randomColorName = names[r.Next(names.Length)];
Color randomColor = Color.FromKnownColor(randomColorName);
return randomColor;*/
Color randomColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
return randomColor;
}
}
The Code for form1:
public partial class Form1 : Form
{
public static EquationBox[] EquationBoxArray = new EquationBox[100];
public Form1()
{
InitializeComponent();
for (int x = 0; x < 100; x++)
{
EquationBoxArray[x] = new EquationBox();
EquationBoxArray[x].Parent = flowLayoutPanel1;
EquationBoxArray[x].Visible = false;
}
}
private void add_line_Click(object sender, EventArgs e) //Add Line
{
for(int x = 0; x < 100; x++)
{
if(!EquationBoxArray[x].Visible)
{
EquationBoxArray[x].Visible = true;
EquationBoxArray[x].Refresh();
break;
}
}
}
private void clear_Click(object sender, EventArgs e) //Clear Lines
{
for (int x = 0; x < 100; x++)
{
EquationBoxArray[x].Visible = false;
EquationBoxArray[x].ResetText();
}
}
private void Form1_SizeChanged(object sender, EventArgs e) //Window Size Changed
{
}
}
Thanks in advance, any help would be much appreciated!
The Random class is only a pseudo-random number generator, controlled by the seed parameter in the constructor. To achieve a better distribution of random numbers, try putting the creation of the Random object outside of the loop, or seed it with a different value each time.
For example
public partial class EquationBox
{
private static Random rnd;
static EquationBox()
{
rnd = new Random();
}
public EquationBox()
{
this.panel4.BackColor = GetRandomColor();
}
private Color GetRandomColor()
{
Color randomColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
return randomColor;
}
}
You need to create global Random instance, or use another it constructor
https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx
More the Random to a field, then use it in the RandomColor function, as below.
Random _rnd = new Random();
private Color RandomColor()
{
Color randomColor = Color.FromArgb(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
return randomColor;
}
This fixes it because Random uses a seed to initialize the pseudorandom number generator, which is the number of milliseconds since the computer was started. Therefore, if you create more than one Random in the same millisecond, it will start with the same seed.
you should only use one instance of Random Class.The problem could be because you are creating new instance of Random every time you call RandomColor .
You can move it to another class
public class MyRandom
{
private static Random _randColor=new Random();
private Color GetRandomColor()
{
Color randomColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
return randomColor;
}
}
and in your user control call it using
public EquationBox()
{
InitializeComponent();
this.panel4.BackColor = MyRandom.GetRandomColor();
}
Your error comes from creating the Random Number Generator everytime you need a new random colour. The RNG is usually seeded with the current time and because you are creating new ones very quickly the get the same seed.
public partial class EquationBox
{
static Random rnd = new Random();
public EquationBox()
{
InitializeComponent();
lock (rnd)
{
this.panel4.BackColor = Color.FromArgb(rnd.Next(257), rnd.Next(257), rnd.Next(257));
}
}
}
Random.Next is not thread safe, so I have a lock around it. Also it returns a value LESS than the max parameter. So you most likely want to pass 257 instead of 256.
I'm fairly new to OOP and am not sure how I would go about implementing something in my program. My program is pretty much similar to whack a mole and has an array of picture boxes with an image in and an image of a monster moves randomly between the picture boxes with a time interval applied or will move to a new random picture box whenever the user clicks on the monster in time. I have created an monster and a player sub class to try and add some OOP concepts to the program but am not sure how to implement what I want. Basically I have a label for score on my main form and a score variable in my animal class with a value. I want to be able to add the value of score from the label on my form when the user clicks on the picture box with the mole in and take away the value of score from the label when they don't click on it in time.
Here is my code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
PictureBox[] boxes;
int initialscore = 0;
int time = 0;
int randPos;
public Form1()
{
InitializeComponent();
}
private void boxes_MouseClick(object sender, MouseEventArgs e)
{
PictureBox pb2 = new PictureBox() { Image = Image.FromFile("sword2.png") };
this.Cursor = new Cursor(((Bitmap)pb2.Image).GetHicon());
for (int x = 0; x < 27; x++)
{
if (sender.Equals(boxes[x]))
{
Image grass = Image.FromFile("swamp.png");
PictureBox temp = (PictureBox)sender;
temp.Image = grass;
}
if (sender.Equals(boxes[x]))
{
PictureBox pb = (PictureBox)sender;
if (pb.Tag == "skeleton.png")
initialscore++;
}
}
label1.Text = " Score: " +initialscore.ToString();
}
public void timer1_Tick(object sender, EventArgs e)
{
boxes[randPos].Image = Image.FromFile("swamp.png");
boxes[randPos].Tag = "swamp.png";
Random r = new Random();
randPos=r.Next(0, 27);
boxes[randPos].Image = Image.FromFile("skeleton.png");
boxes[randPos].Tag = "skeleton.png";
}
private void Form1_Load(object sender, EventArgs e)
{
boxes = new PictureBox[27];
int top = 100;
int left = 100;
for (int x = 0; x < 27; x++)
{
boxes[x] = new PictureBox();
boxes[x].Image = Image.FromFile("swamp.png");
boxes[x].Height = 100;
boxes[x].Width = 100;
if (x % 9 == 0)
{
top += 120;
left = 120;
}
else
left += 120;
boxes[x].Top = top;
boxes[x].Left = (50 + left);
Controls.Add(boxes[x]);
this.boxes[x].MouseClick += new
System.Windows.Forms.MouseEventHandler(this.boxes_MouseClick);
label1.Text = " Score: " + initialscore.ToString();
label2.Text = " Time: " + time.ToString();
}
}
}
namespace WindowsFormsApplication1
{
class Monster
{
protected int score;
public Monster()
{
score = 10;
}
}
}
namespace WindowsFormsApplication1
{
class Player:Monster
{
}
}
Nothing has been added in the player class yet.
What do I need to add or change to be able to get the initial score to change by the value of the score in the monster class when clicking on the moving image?
To unify the updating/incrementing and visualization of the score you should extract that to a method:
public void incrementScore(int increment)
{
initialscore += increment;
label1.Text = " Score: " + initialscore.ToString();
}
in the Form1_Load you call this like:
incrementScore(0);
for the click on the monster you have different possibilities:
if all the monsters have the same points you can make it a static variable in the Monster class.
protected static int Score = 10;
which allows you to use it in the boxes_MouseClick event handler:
incrementScore(Monster.Score);
in case all monsters have another value you have to hold the score variable as an instance variable, identify somehow the instance of the monster class you clicked on and increment with this value