I have a interface
interface Dot
{
// protected Random r = new Random();
void createdot(Rectangle clientrectangle, Control.ControlCollection Controls);
}
and I use this interface as a base class for my derived classes as stated
public class BlueDot : Dot
{
public List<Label> bluedot = new List<Label>();
Random r = new Random();
public void createdot(Rectangle ClientRectangle, Control.ControlCollection Controls)
{
for (int i = 0; i < 5; i++)
{
var temp = new Label();
temp.Location = new Point(r.Next(ClientRectangle.Right - 10), r.Next(ClientRectangle.Bottom - 20));
temp.Text = "?";
temp.Width = 10;
temp.Height = 10;
temp.ForeColor = System.Drawing.Color.Blue;
temp.BackColor = System.Drawing.Color.White;
Controls.Add(temp);
temp.Visible = true;
temp.Show();
bluedot.Add(temp);
}
}
}
and
public class RedDot:Dot
{
public List<Label> reddot = new List<Label>();
Random r = new Random();
public void createdot(Rectangle Clientrectangle,Control.ControlCollection Controls)
{
for (int z = 0; z < 10; z++)
{
var temp2 = new Label();
temp2.Location = new Point(r.Next(Clientrectangle.Right - 10), r.Next(Clientrectangle.Bottom - 20));
temp2.Text = "?";
temp2.Width = 10;
temp2.Height = 10;
temp2.ForeColor = System.Drawing.Color.Red;
temp2.BackColor = System.Drawing.Color.White;
Controls.Add(temp2);
temp2.Show();
reddot.Add(temp2);
}
}
and they are called here
BlueDot bdot = new BlueDot();
RedDot rdot = new RedDot();
private void Form1_Load(object sender, EventArgs e)
{
this.Activate();
bdot.createdot(this.ClientRectangle,this.Controls);
rdot.createdot(this.ClientRectangle, this.Controls);
}
Why is it that I keep getting only 5 red dots even if the loop performs 10 iterations?
here is the sample output https://www.facebook.com/photo.php?fbid=2372861522202&set=a.1600508493859.85328.1270463960&type=1 , i just cant figure out what happened to the other 5 red dots, it should be 10 red dots....
There is no inheritance problem here. The problem is the random number generator.
Try this line in your code:
temp2.Location = new Point(10 * z, 10 * z);
Replacing
temp2.Location = new Point(r.Next(Clientrectangle.Right - 10), r.Next(Clientrectangle.Bottom - 20));
You'll see your 5 blue "?"-labels and your 10 red "?"-labels
To solve the problem of the weak random number generator try seeding your random number generator. Example:
Random r = new Random((int)DateTime.Now.Ticks);
I am not that sure, but why aren't you making your temp2 visible ????
temp2.Visible=true
If this dowsn't work can you provide a screen shot of both your output. Sometimes due to the size of the window one dot may reside over another. I mean they actually overlap. Seeing your output may help to sort out your problem
Related
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 WinForms project with MVP pattern (passive view) implemented.
I think that I have a problem with the pattern when it comes to a user control, which I figured out during unit testing
I have a user control that I put on my form as a result of an event fired in my view. That user control adds a certain amount of labels, textboxes, etc. to itsself based on a number it gets from the view. Finally, it tells the view to add the user control to the view.
I want to unit test the logic in this class, since that is what I think is most important to test. I just do not know how to do this, since there is both logic and form controls in this class. I am currently using Moq for creating my unit tests.
I would normally create a Mock object to represent the view and then test the implementation of the methods in the object to be tested in isolation. However, since I create controls in this class, I don't think I can test this like this (without including the .Forms library that is).
I hope someone knows a solution.
EDIT: I have been trying to separate my logic from the control manipulation, but I am struggling with a function from a different user control I have posted below the original user control code. Since I loop through a list of controls, I dont know how to separate this into just logic and just control handling.
User control code
public partial class DetailScreenUserControl : UserControl
{
// Private members.
private readonly IDetailScreenView _view;
private List<ComboBox> maturityInput = new List<ComboBox>();
private List<ComboBox> complianceInput = new List<ComboBox>();
// Public members.
public List<string> MaturityInput
{
get
{
var list = new List<string>();
for (int i = 0; i < maturityInput.Count; i++)
{
list.Add(maturityInput[i].Text);
}
return list;
}
set
{
for (int i = 0; i < maturityInput.Count; i++)
{
maturityInput[i].DataSource = new List<string>(value);
}
}
}
public List<string> ComplianceInput
{
get
{
var list = new List<string>();
for (int i = 0; i < complianceInput.Count; i++)
{
list.Add(complianceInput[i].Text);
}
return list;
}
set
{
for (int i = 0; i < complianceInput.Count; i++)
{
complianceInput[i].DataSource = new List<string>(value);
}
}
}
// Initialize user control with IDetailScreenView. Subscribe to necessary events.
public DetailScreenUserControl(IDetailScreenView view)
{
InitializeComponent();
_view = view;
_view.InitializingUserControl += InitializeUserControl;
}
// Initializes the user control for the detail screen.
public void InitializeUserControl(object sender, EventArgs e)
{
List<string> qStandards = _view.SelectedQuestionStandards;
Controls.Clear();
maturityInput.Clear();
complianceInput.Clear();
int inputSeparation = Height / 2;
int spacing = Width / 20;
Size = new Size(_view.RightUserControlBoundary - Location.X, Size.Height);
for (int i = 0; i < qStandards.Count; i++)
{
Panel inputPanel = new Panel();
inputPanel.BackColor = Color.AliceBlue;
inputPanel.Location = new Point(0, i * inputSeparation);
inputPanel.Size = new Size(Width - spacing, inputSeparation);
Controls.Add(inputPanel);
Label qs_label = new Label();
qs_label.AutoSize = true;
qs_label.Location = new Point(0, 0);
qs_label.Font = new Font("Arial", 12F, FontStyle.Bold);
qs_label.AutoSize = true;
qs_label.Text = qStandards[i].ToString();
inputPanel.Controls.Add(qs_label);
Label m_label = new Label();
m_label.AutoSize = true;
m_label.Location = new Point(0, qs_label.Bounds.Bottom + qs_label.Height / 2);
m_label.Font = new Font("Arial", 12F, FontStyle.Regular);
m_label.Text = "Maturity standard";
inputPanel.Controls.Add(m_label);
Label c_label = new Label();
c_label.AutoSize = true;
c_label.Location = new Point(0, m_label.Bounds.Bottom + qs_label.Height / 2);
c_label.Font = new Font("Arial", 12F, FontStyle.Regular);
c_label.Text = "Compliance standard";
inputPanel.Controls.Add(c_label);
ComboBox m_input = new ComboBox();
m_input.AutoSize = true;
m_input.Location = new Point(c_label.Bounds.Right + 2 * spacing, m_label.Bounds.Top);
m_input.Font = new Font("Arial", 10F, FontStyle.Regular);
m_input.DropDownStyle = ComboBoxStyle.DropDownList;
m_input.Size = new Size(inputPanel.Size.Width - m_input.Bounds.Left, spacing);
maturityInput.Add(m_input);
inputPanel.Controls.Add(m_input);
ComboBox c_input = new ComboBox();
c_input.AutoSize = true;
c_input.Location = new Point(c_label.Bounds.Right + 2 * spacing, c_label.Bounds.Top);
c_input.Font = new Font("Arial", 10F, FontStyle.Regular);
c_input.DropDownStyle = ComboBoxStyle.DropDownList;
c_input.Size = new Size(inputPanel.Size.Width - c_input.Bounds.Left, spacing);
complianceInput.Add(c_input);
inputPanel.Controls.Add(c_input);
}
if(qStandards.Count != 0)
{
saveAssessmentButton.BackColor = System.Drawing.SystemColors.ButtonHighlight;
Controls.Add(saveAssessmentButton);
saveAssessmentButton.Location = new Point(this.Size.Width - saveAssessmentButton.Width - spacing, qStandards.Count * inputSeparation);
}
_view.AddUserControl();
}
// Tells the view to save the assessment.
private void saveAssessmentButton_Click(object sender, EventArgs e)
{
_view.SaveAssessmentButtonClicked();
}
}
Other user control function('answers' is the list of controls)
public void SaveResults()
{
results = new List<string>();
int questionNr = 0;
for (int p = 0; p < questions.Count; p++)
{
for (int i = 0; i < questions[p].Count; i++)
{
bool unanswered = true;
results.Add(questions[p][i]);
for (int j = 1; j <= maturityAnswers[p].Count; j++)
{
var radioButton = (RadioButton)answers[questionNr][j];
if (radioButton.Checked)
{
results.Add(answers[questionNr][j].Text);
unanswered = false;
}
}
if (unanswered == true)
{
results.Add("");
}
unanswered = true;
for (int j = maturityAnswers[p].Count + 1; j <= (maturityAnswers[p].Count + complianceAnswers[p].Count); j++)
{
var radioButton = (RadioButton)answers[questionNr][j];
if (radioButton.Checked)
{
results.Add(answers[questionNr][j].Text);
unanswered = false;
}
}
if (unanswered == true)
{
results.Add("");
}
results.Add(answers[questionNr][0].Text.Replace("'", "''"));
questionNr++;
}
}
I want to unit test the logic in this class, since that is what I
think is most important to test. I just do not know how to do this,
since there is both logic and form controls in this class
So separate them to different classes and test the class which contains only logic
I've got this class fish and I just want to initialize my form with 8 types of fish positioning it in the form. When I run my code the eight fishes never appear. In some case one, two, or three. But when I debug the code the eight fishes appear.
I really don't know what is happening. Hope you could help me to find an answer.
class Fish : Aquaticanimal
{
private int x;
public int X
{
get { return x; }
set { x = value; }
}
private int y;
public int Y
{
get { return y; }
set { y = value; }
}
public Fish(Bitmap fish,Form form)
{
quantity++;
aquaticAnimal.BackColor = Color.Transparent;
aquaticAnimal.Image = fish;
aquaticAnimal.SizeMode = PictureBoxSizeMode.StretchImage;
positioning(form);
}
private void positioning(Form form)
{
Random rnd = new Random();
int FormWidth= Convert.ToInt32( form.Size.Width.ToString());
int FormHeight = Convert.ToInt32(form.Size.Height.ToString());
aquaticAnimal.Parent=form;
aquaticAnimal.Top = rnd.Next(200, FormHeight - 100);
aquaticAnimal.Left = rnd.Next(0, FormWidth - 100);
this.x = aquaticAnimal.Top;
this.y = aquaticAnimal.Left;
}
}
private void Form1_Load(object sender, EventArgs e)
{
Bitmap[] images = new Bitmap[8];
images[0] = Pecera.Properties.Resources.Nemo;
images[1] = Pecera.Properties.Resources.Pez_hembra;
images[2] = Pecera.Properties.Resources.Pez_macho;
images[3] = Pecera.Properties.Resources.tiburon_adulto;
images[4] = Pecera.Properties.Resources.Tiburon_bebe_hembra;
images[5] = Pecera.Properties.Resources.tiburon_macho;
images[6] = Pecera.Properties.Resources.Dorys;
images[7] = Pecera.Properties.Resources.tiburon_hembra;
Fish[] fish = new Fish[8];
for (int x = 0; x < 8; x++)
{
fish[x] = new Fish(images[x], this);
}
}
This is a case of creating a new instance of Random extremely quickly, resulting in not-so-random values. Your fishes are all overlapping each other, because the "random" values are the same.
You'll have to refactor your code in such a way that you only use a single instance of Random.
Here's my suggestion, changing as little of your code as possible:
class Fish : Aquaticanimal
{
...
...
private static Random rnd = new Random();
private void positioning(Form form)
{
int FormWidth= Convert.ToInt32( form.Size.Width.ToString());
int FormHeight = Convert.ToInt32(form.Size.Height.ToString());
aquaticAnimal.Parent=form;
aquaticAnimal.Top = rnd.Next(200, FormHeight - 100);
aquaticAnimal.Left = rnd.Next(0, FormWidth - 100);
this.x = aquaticAnimal.Top;
this.y = aquaticAnimal.Left;
}
}
FWIW, your Fish class really shouldn't be responsible for positioning itself on the Form.
I have created dynamic NumericUpDown. I want to save the values that the user enters. How can i do that. After I am saving the values I want to do some time manipulation with them. Knowing I do not know the number of NumericUpDown the user wants each time?
// To set up the location for the NumericUpDown
int xCoor;
int yCoor;
Random coor = new Random();
// Button to create the NumericUpDown
private void btnRun_Click(object sender, EventArgs e)
{
/// I am assuming that the user choice is 8
int value = 8;
//this calls the method which is going to create NumericUpDown
this.AddNewNumrical(value);
}
//Method to Create NumericUpDown
private void AddNewNumrical(int numiraclNew)
{
for (int x = 0; x < numiraclNew; x++)
{
for (int y = 0; y < 1; y++)
{
NumericUpDown numiNumber = new NumericUpDown();
xCoor = coor.Next(0, 700);
yCoor = coor.Next(0, 710);
numiNumber.Location = new Point(xCoor, yCoor);
numiNumber.Size = new System.Drawing.Size(50, 15);
numiNumber.Maximum = 1000;
numiNumber.Minimum = 1;
this.pnlNodes.Controls.Add(numiNumber);
}
}
}
Just store your new NumericUpDown control in another list! You could also search the Controls collection for NumericUpDown controls but you might pick up some stuff you don't want:
List<NumericUpDown> numberControls = new List<NumericUpDown>();
//Method to Create NumericUpDown
private void AddNewNumrical(int numiraclNew)
{
for (int x = 0; x < numiraclNew; x++)
{
NumericUpDown numiNumber = new NumericUpDown();
xCoor = coor.Next(0, 700);
yCoor = coor.Next(0, 710);
numiNumber.Location = new Point(xCoor, yCoor);
numiNumber.Size = new System.Drawing.Size(50, 15);
numiNumber.Maximum = 1000;
numiNumber.Minimum = 1;
numberControls.Add(numiNumber); //Save the control off for later
this.pnlNodes.Controls.Add(numiNumber);
}
}
Then you can use it later to do whatever you want:
private void Foo()
{
foreach (NumericUpDown userSelection in numberControls)
{
//Do whatever with userSelection.Value
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I wrote a quick implementation of Conway's Game of Life, but it ran awfully slow mostly because my method of checking for neighbouring cells involved looping through the entire grid of cells again, now I've changed my method of checking for neighbouring cells but unfortunately it's not updating correctly anymore, it seems to work fine except that it doesn't create nearly as many new cells as it should.
Now I have spent a good few hours manually debugging the code, going through it with breakpoints and trying to compare the values and calls, but it SEEMS as if my GetNeighbours() method is working, so I concede to you, I can't figure out what's wrong on my own. I've submitted the code below for help.
EDIT: Some of you have pointed out that I can't copy my Grid.cells array the way I am doing it. I've changed it to use Array.Copy() instead but unfortunately it still doesn't work completely. I can't figure it out but it still doesn't seem to create new cells in all cases where it should.
MainForm.cs
public partial class MainFom : Form
{
Grid formGrid;
CancellationTokenSource tokenSrc = new CancellationTokenSource();
public MainFom()
{
InitializeComponent();
}
private void MainFom_Load(object sender, EventArgs e)
{
formGrid = new Grid();
for (int i = 0; i < 50; i++)
{
int xCoord = 10 * i + 12;
Controls.Add(new Label()
{
AutoSize = true,
Text = i.ToString(),
Location = new Point(xCoord, 0),
Font = new Font(Font.FontFamily, 6)
});
for (int s = 0; s < 50; s++)
{
int yCoord = 10 * s + 12;
Controls.Add(new Label()
{
AutoSize = true,
Text = s.ToString(),
Location = new Point(0, yCoord),
Font = new Font(Font.FontFamily, 6)
});
}
}
}
private void MainFom_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(formGrid.toBitmap(), 0, 0);
e.Graphics.Dispose();
}
private void startBtn_Click(object sender, EventArgs e)
{
Task tempTask = Task.Factory.StartNew(
(x) =>
{
while (!tokenSrc.IsCancellationRequested)
{
formGrid.UpdateGrid();
Graphics graphics = this.CreateGraphics();
graphics.Clear(this.BackColor);
graphics.DrawImage(formGrid.toBitmap(), 0, 0);
graphics.Dispose();
}
}, tokenSrc);
startBtn.Hide();
Button stopBtn = new Button() { Text = "Stop", Location = startBtn.Location, Size = startBtn.Size };
this.Controls.Add(stopBtn);
stopBtn.Click += new EventHandler(
(x, y) =>
{
tokenSrc.Cancel();
stopBtn.Hide();
startBtn.Show();
tempTask.Wait();
tokenSrc = new CancellationTokenSource();
});
}
}
Grid.cs
class Grid
{
#region Properties/Fields
const int MAX_CELLS = 50;
Random RNG = new Random();
Cell[,] cells;
int generations = new int();
#endregion
public Grid()
{
cells = new Cell[MAX_CELLS, MAX_CELLS];
for (int x = 0; x < MAX_CELLS; x++)
{
int xCoord = 10 * x + 12;
for (int y = 0; y < MAX_CELLS; y++)
{
int yCoord = 10 * y + 12;
Point point = new Point(xCoord, yCoord);
if (RNG.Next(100) < 20) {
cells[x, y] = new Cell(point, true); }
else {
cells[x, y] = new Cell(point, false);
}
}
}
}
public void UpdateGrid()
{
Cell[,] copy = cells;
for (int x = 0; x < MAX_CELLS; x++)
{
for (int y = 0; y < MAX_CELLS; y++)
{
int neighboursCtr = GetNeighbours(x, y);
//Rule 1: Any live cell with fewer than two live neighbours dies, as if caused by under-population.
if (cells[x, y].IsAlive && neighboursCtr < 2)
{
copy[x, y].Kill();
}
//Rule 2: Any live cell with more than three live neighbours dies, as if by overcrowding.
if (cells[x, y].IsAlive && neighboursCtr > 3)
{
copy[x, y].Kill();
}
//Rule 3: Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if (!cells[x, y].IsAlive && neighboursCtr == 3)
{
copy[x, y].Alive();
}
}
}
cells = copy;
generations++;
}
public Bitmap toBitmap()
{
Bitmap gridBmp = new Bitmap(1000, 1000); // TODO: Find optimal size for bmp
Size cellSize = new Size(10, 10);
using (Graphics gfxObj = Graphics.FromImage(gridBmp))
{
// Draw grid here and Dispose() on Pen, gfxObj is implicitly disposed
Pen myPen = new Pen(Color.LightGray);
SolidBrush myBrush = new SolidBrush(Color.Black);
for (int x = 0; x < MAX_CELLS; x++)
{
for (int y = 0; y < MAX_CELLS; y++)
{
if (!cells[x, y].IsAlive)
{
gfxObj.DrawRectangle(myPen, new Rectangle(cells[x, y].point, cellSize));
} else
{
gfxObj.FillRectangle(myBrush, new Rectangle(cells[x, y].point, cellSize));
}
}
}
myPen.Dispose();
myBrush.Dispose();
}
return gridBmp;
}
private int GetNeighbours(int column, int row)
{
int neighbours = new int();
int[] starts = new int[] { Math.Max(0 ,column - 1), Math.Max(0, row - 1) };
int[] ends = new int[] { Math.Min(49, column + 1), Math.Min(49, row + 1) };
double colAndRow = column + row/10;
for (int x = starts[0]; x < ends[0]+1; x++)
{
for (int y = starts[1]; y < ends[1]+1; y++)
{
double xAndY = x + y/10;
if (cells[x, y].IsAlive && xAndY != colAndRow)
{
neighbours++;
}
}
}
return neighbours;
}
}
Cell.cs
struct Cell
{
public bool IsAlive { get; private set; }
public readonly Point point;
public Cell(Point point, bool isAlive) : this()
{
this.point = point;
IsAlive = isAlive;
}
public void Alive()
{
IsAlive = true;
}
public void Kill()
{
IsAlive = false;
}
}
The problem is in your UpdateGrid() method. You're simply assigning the reference for your original array to a new variable:
Cell[,] copy = cells;
But this is still the same object; in particular, there's no difference between calling copy[x, y].Kill() and cells[x, y].Kill(). So you're modifying your state during calculations, this affects your code's logic.
Make a copy of the original using Array.Copy and it should work correctly (there doesn't seem to be anything else wrong with your algorithm).
Arrays are reference types, which means
Cell[,] copy = cells;
doesn't what you probably intent to do. It's not a copy of the source array, so it will manipulate this whilst analyzing the neighbors which will lead to wrong results.
Use Array.Copy.
There are a lot of improvements that can be done.
Take a look at Optimizing Conway's 'Game of Life' and Hashlife
You can start by using LockBits to work faster with the bitmap.
You can use parallel programming to improve the loops: Save time with parallel FOR loop
You can also improve the algorithm avoiding the whole matrix scan each time, and instead maintain a list of the alive cells, and only step thru these cells and it's neighbors.
I've implemented such algorithm in the following C# Game of Life Code.