I have 5 Picture Boxes in my application, and I update them at the same time.
I want them to display 5 different Images and my programs code is right, but for some reason the picture boxes show all the same image...
Here's the code:
private System.Drawing.Bitmap DiceOne;
private System.Drawing.Bitmap DiceTwo;
private System.Drawing.Bitmap DiceThree;
private System.Drawing.Bitmap DiceFour;
private System.Drawing.Bitmap DiceFive;
private System.Drawing.Bitmap DiceSix;
public void Prepare()
{
for (int i = 0; i < 5; i++)
Dices[i] = new Dice();
DiceOne = Properties.Resources.Würfel_1;
DiceTwo = Properties.Resources.Würfel_2;
DiceThree = Properties.Resources.Würfel_3;
DiceFour = Properties.Resources.Würfel_4;
DiceFive = Properties.Resources.Würfel_5;
DiceSix = Properties.Resources.Würfel_6;
}
public void Roll()
{
foreach (Dice dice in Dices)
dice.RollTheDice();
View.SuspendLayout();
View.diceOnePictureBox.Image = DiceNumberToBmp(Dices[0].GetLastRolled());
View.diceOnePictureBox.Update();
View.diceTwoPictureBox.Image = DiceNumberToBmp(Dices[1].GetLastRolled());
View.diceOnePictureBox.Update();
View.diceThreePictureBox.Image = DiceNumberToBmp(Dices[2].GetLastRolled());
View.diceOnePictureBox.Update();
View.diceFourPictureBox.Image = DiceNumberToBmp(Dices[3].GetLastRolled());
View.diceOnePictureBox.Update();
View.diceFivePictureBox.Image = DiceNumberToBmp(Dices[4].GetLastRolled());
View.diceOnePictureBox.Update();
View.ResumeLayout(false);
}
private System.Drawing.Bitmap DiceNumberToBmp(int number)
{
switch(number)
{
case 1:
return DiceOne;
case 2:
return DiceTwo;
case 3:
return DiceThree;
case 4:
return DiceFour;
case 5:
return DiceFive;
case 6:
return DiceSix;
default:
return null;
}
}
I've read some familier posts on the internet before, and tried to solve with with SuspendLayout, ResumeLayout, Updating the PictureBox.... Nothing worked for me.
My Dice class:
using System;
namespace KniffelGUI.Model
{
public class Dice
{
private int LastRolled;
public Dice()
{
RollTheDice();
}
public Dice(int fakeRoll)
{
LastRolled = fakeRoll;
}
public int RollTheDice()
{
LastRolled = new Random().Next(6) + 1;
return LastRolled;
}
public int GetLastRolled()
{
return LastRolled;
}
}
}
The problem is in your Dice class, as suggested earlier by Barry O'Kane.
Change it to:
public class Dice
{
private int LastRolled;
private static Random R = new Random();
public Dice()
{
RollTheDice();
}
public Dice(int fakeRoll)
{
LastRolled = fakeRoll;
}
public int RollTheDice()
{
LastRolled = R.Next(6) + 1;
return LastRolled;
}
public int GetLastRolled()
{
return LastRolled;
}
}
Your symptom was occurring because of this line:\
LastRolled = new Random().Next(6) + 1;
When you create an instance of Random with the default constructor, it uses the current time as the seed. When you create multiple instances in rapid succession, they end up with the same seed and therefore won't get different numnbers.
By declaring it as static, all instances of your class will use the same Random instance and get a different number upon each call.
Related
I would like to implement the following idea in C# but I am stuck with this and cannot move on.
I want to create more objects from the Class Something and always when I call the method I_Frame I would like to increase the sequence number by 1 (I am trying to test it with a button).
public class Something
{
private int sequenceNumber;
public int SequenceNumber
{
get
{
return this.sequenceNumber;
}
set
{
this.sequenceNumber = value;
}
}
public int I_FRAME(ref byte[] IFrame)
{
IFrame[0] = (byte)((sequenceNumber);
IFrame[1] = 0x00
sequenceNumber=sequenceNumber + 1 % 32768;
return sequenceNumber;
}
and this is my button code.
public partial class VlastniTCP : Form
{
byte[] testbyte = new byte[2];
private void button2_Click(object sender, EventArgs e)
{
Something Test = new Something();
Test.I_Frame(ref testbyte);
textbox1.Text = testbyte[0];
}
}
I would be happy for every advice or explonation how to do it.
Thank you in advance.
Your problem is that you are creating a new Something every time you click the button. Something.sequenceNumber defaults to zero whenever you create a new one. Your options are:
Option 1: Use the same instance of something every time:
public partial class VlastniTCP : Form
{
byte[] testbyte = new byte[2];
private Something test;
private void button2_Click(object sender, EventArgs e)
{
test ??= new Something();
test.I_FRAME(ref testbyte);
textbox1.Text = testbyte[0];
}
}
Option 2: Keep track of the last used sequenceNumber:
public class Something
{
private static int lastSequenceNumber;
public int SequenceNumber { get; set; }
public int I_FRAME(ref byte[] IFrame)
{
var sequenceNumber = (lastSequenceNumber + 1) % 32768;
lastSequenceNumber = sequenceNumber;
SequenceNumber = sequenceNumber;
IFrame[0] = (byte)sequenceNumber;
IFrame[1] = 0x00;
return sequenceNumber;
}
}
This question already has answers here:
question about print List<T> to screen
(5 answers)
Print List of objects to Console
(3 answers)
Print list Object c#
(1 answer)
Why does every line in the .txt-file output end with 'System.int32'? C#
(3 answers)
Closed 2 years ago.
I'm trying to print out the int items inside the list but I get the following output, which is obviously not what I want to print:
YSolution.Dice
YSolution.Dice
YSolution.Dice
YSolution.Dice
YSolution.Dice
Source code:
class Dice
{
//defining variable and properties
private bool _hold = false;
private Random rnd;
public int Current { get; private set; }
public bool IsHolding
{
get { return _hold; }
set { _hold = value; }
}
public Dice()
{
Current = 0;
rnd = new Random(Guid.NewGuid().GetHashCode());
FRoll();
}
public int FRoll()
{
Current = rnd.Next(1, 7);
return Current;
}
class DiceCup
{
public List<Dice> Dices { get; } = new List<Dice>();
public DiceCup(int count)
{
for (int i = 0; i < count; i++)
{
Dices.Add(new Dice());
}
foreach (Dice aDice in Dices)
{
Console.WriteLine(aDice);
}
}
class Program
{
static void Main(string[] args)
{
DiceCup nbd = new DiceCup(count);
}
}
The method FRoll(); seem to not get called in the dice class for some reason, when a new item is added to the list.I really just want to print out the items in the List Dices but I do not get the output/result I want. Anyone who can spot the error?
Currently you're just calling ToString() on your Dice object. Since you haven't overriden ToString() this is just using the default object.ToString() implementation which returns the type name of the object (YSolution.Dice in your case).
You have a Current property on your dice that returns the value of the dice, if you call this method then that will return the value of the dice, which you can then print: change Console.WriteLine(aDice); to Console.WriteLine(aDice.Current);.
Alternatively, as others have pointed out, you can override ToString() on your Dice class to return the current value of the dice:
class Dice
{
//defining variable and properties
private bool _hold = false;
private Random rnd;
public int Current { get; private set; }
public bool IsHolding
{
get { return _hold; }
set { _hold = value; }
}
public Dice()
{
Current = 0;
rnd = new Random(Guid.NewGuid().GetHashCode());
FRoll();
}
public int FRoll()
{
Current = rnd.Next(1, 7);
return Current;
}
public override string ToString()
{
return Current.ToString();
}
}
you want to implement the ToString-method:
public string ToString()
{
return Current.ToString();
}
Besides overriding the ToString method, as mentioned in other answers, you could also collect the results from the dice and print those:
foreach (int result in Dices.Select(d => d.Current))
{
Console.WriteLine(result);
}
The Select method is defined in the System.Linq namespace.
I am attempting to write a program for an assignment that Pops and adds the first 2 items in a Stack. The program has a Pop method, but I would like to know how to call the method within the Add method. This Add is supposed to Pop the top two items in a stack, get their sum, and Push that sum to the stack. In my code below I call the Pop method twice inside the Add method, but when I display the stack, the stack still has all of the original values. Is there something more/else I need to go to get the Pop method to work?
class StackEmptyException : ApplicationException
{
public StackEmptyException(String message) : base(message)
{
}
}
class MathStack
{
private int[] dataStack;
private int size;
private int top = -1;
public bool IsEmpty()
{
return top == -1;
}
public bool IsFull()
{
return top == size - 1;
}
public void Push(int i)
{
dataStack[++top] = i;
}
public int Pop()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- cannot pop");
else
return dataStack[top--];
}
public int Top()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- top undefined");
else
return dataStack[top];
}
public MathStack()
{
dataStack = new int[10];
}
public MathStack(int s)
{
size = 10;
dataStack = new int[size];
}
public void LoadStack(int v)
{
dataStack[++top] = v;
}
public void Display()
{
int[] display = new int[dataStack.Length];
for (int i = 0; i < dataStack.Length; i++)
{
display[i] = dataStack[i];
Console.WriteLine("{0}", display[i]);
}
}
public void Add()
{
int add1 = dataStack[0];
int add2 = dataStack[1];
Pop();
Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
}
}
class Program
{
static void Main(string[] args)
{
MathStack stack1 = new MathStack();
stack1.Push(9);
stack1.Push(8);
stack1.Push(7);
stack1.Push(6);
stack1.Push(5);
stack1.Push(4);
stack1.Push(3);
stack1.Push(2);
stack1.Push(1);
stack1.Push(0);
stack1.Display();
stack1.Add();
stack1.Display();
Console.ReadLine();
}
}
There are two things wrong with your code.
First, the Display method displays the whole array. Except that since you're not physically removing the items from the array, you need to stop at the index top:
public void Display()
{
if (IsEmpty())
{
Console.WriteLine("Empty");
return;
}
for (int i = 0; i <= top; i++)
{
Console.WriteLine(dataStack[i]);
}
}
The second issue is your Add. From what I understand, you want to pop the last two items, sum them, and push the result. In your implementation, you are actually summing the first two items (not the last two). A better version would be:
public void Add()
{
int add1 = Pop();
int add2 = Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
Push(sum);
}
Notice how I do not directly access dataStack. If your API is correctly implemented, it should not be needed.
In my current program I am building an array of objects and then populating it, however I need to then access this populated array from another function within the same class. In C I would do this by making the array global, but global variables dont exist in C# and when I try to use the "Static" parameter it says arrays cant be static.
namespace FormsTest1
{
public partial class Form1 : Form
{
public int AppCount;
public static applications[] appList;
public Form1() //Main Entry point of program
{
IEnumerable<int> apps = VolumeMixer.EnumerateApplications();
AppCount = apps.Count();
int i = 0;
applications[] appList = new applications[AppCount];
foreach (int app in apps)
{
appList[i] = new applications();
appList[i].setProcessID(app);
appList[i].populate();
i++;
}
for (int j = 0; j < AppCount; j++) { ChannelSelect1.Items.Add(appList[j].Name); }
}
private void ChannelSelect1_SelectedIndexChanged(object sender, EventArgs e)
{
for (int k = 0; k < AppCount; k++)
{
if (ChannelSelect1.Text == appList[k].Name) //<-- This array is not the one I populate in Form1()
{ Channels[0] = appList[k].PID; }
}
}
public class applications
{
public int PID;
public string ProcessName;
public string WindowName;
public string Name;
public string Path;
public void setProcessID(int ID) { PID = ID; }
public string getProcessName() { return ProcessName; }
public string getWindowName() { return WindowName; }
public string getName() { return Name; }
public string getPath() { return Path; }
public void populate()
{
//stuff
}
}
}
I cant pass the array into the other functions cause they are event driven, and I need the index-ability of arrays.
How do I declare and populate an array of objects in one function, and then use that array in another function in the same class?
Change your constructor from
applications[] appList = new applications[AppCount];
to
appList = new applications[AppCount];
You should initialize your instance field instead of creating a new local one.
Btw: It is not necessary to make the array static.
I am having a problem return a list so that i would be able to save it in a file and then load it so that the weights are saved and be retrieved another time. Sorry for the stupid question but how can i call and save the weights List from the SaveNetwork method , i cant grasp really what i can do to solve the problem. I know that i havent created a new instance of List weights however if i do that i will loose the current weights which are stored in this list.
public class Neuron
{
private double bias; // Bias value.
private double error; // Sum of error.
private double input; // Sum of inputs.
private double gradient = 5; // Steepness of sigmoid curve.
private double learnRate = 0.01; // Learning rate.
private double output = double.MinValue; // Preset value of neuron.
public List<Weight> weights; // Collection of weights to inputs.
public Neuron() { }
public Neuron(Layer inputs, Random rnd)
{
weights = new List<Weight>();
foreach (Neuron input in inputs)
{
Weight w = new Weight();
w.Input = input;
w.Value = rnd.NextDouble() * 2 - 1;
weights.Add(w);
}
}
public static void SaveNetwork(string path)
{
FileStream FS = new FileStream(path, FileMode.Create);
BinaryFormatter BF = new BinaryFormatter();
BF.Serialize(FS,/* The List in this case is List weights ***/ );
FS.Close();
}
public void LoadNetwork(string path)
{
FileStream FS = new FileStream(path, FileMode.Open);
BinaryFormatter BF = new BinaryFormatter();
weights = (List<Weight>)BF.Deserialize(FS);
FS.Close();
}
Update for this--I am using a similar hierarchical structure as the code below which was taken from Dynamic Notions blog which explains how to create a Neural Network. What i want to achieve is that after that the Neural Network has learnt i want to be able to save the List weights so that i would be able to load the weights if the program is stopped in order to skip the training of the network. So basically from the class network i want to access this list which is in Neural Class without creating a new instance in a new method else i will only get an empty List. Hope that its clearer coz i didnt know how to explain it better... Many thanks
public class Network{
//some variables..
[STAThread]
static void Main()
{
new Network();
}
public Network()
{
LoadPatterns();
Initialise();
Train();
Test();
}
private void Train()
{
double error;
do
{
error = 0;
foreach (Pattern pattern in _patterns)
{
double delta = pattern.Output - Activate(pattern);
AdjustWeights(delta);
error += Math.Pow(delta, 2);
}
Console.WriteLine("Iteration {0}\tError {1:0.000}", _iteration, error);
_iteration++;
if (_iteration > _restartAfter) Initialise();
} while (error > 0.1);
}
private void Test()
{
}
// Must be able to call and save the List<Weight> From here
private double Activate(Pattern pattern)
{
}
private void AdjustWeights(double delta)
{
_output.AdjustWeights(delta);
foreach (Neuron neuron in _hidden)
{
neuron.AdjustWeights(_output.ErrorFeedback(neuron));
}
}
private void Initialise()
{
_inputs = new Layer(_inputDims);
_hidden = new Layer(_hiddenDims, _inputs, _rnd);
_output = new Neuron(_hidden, _rnd);
_iteration = 0;
Console.WriteLine("Network Initialised");
}
private void LoadPatterns()
{
}
}
public class Layer : List<Neuron>
{
public Layer(int size)
{
for (int i = 0; i < size; i++)
base.Add(new Neuron());
}
public Layer(int size, Layer layer, Random rnd)
{
for (int i = 0; i < size; i++)
base.Add(new Neuron(layer, rnd)); //this is where Neuron class is instantiated
}
}
public class Neuron
{
//some other vars
private List<Weight> _weights; // This is the list in question.
public Neuron() { }
public Neuron(Layer inputs, Random rnd)
{
_weights = new List<Weight>();
foreach (Neuron input in inputs)
{
Weight w = new Weight();
w.Input = input;
w.Value = rnd.NextDouble() * 2 - 1;
_weights.Add(w);
}
}
}
public class Weight
{
public Neuron Input;
public double Value;
}
Remove the static keyword from SaveNetwork() and use weights where you have your comment.