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
class Puzzle
{
public int PUZZLESIZE = 3;
public int numSteps = 0;
public Button[,] buttons;
public Puzzle(Form1 form1)
{
buttons = new Button[3, 3] { { form1.button1, form1.button2, form1.button3 },
{ form1.button4, form1.button5, form1.button6 },
{ form1.button7, form1.button8, form1.button9 } };
}
public Puzzle Clone()
{
return (Puzzle)this.MemberwiseClone();
}
public void reset()
{
//reset all 9 buttons color
}
public void flipcells()
{
//flip cells in the puzzle with color change
}
class Undo
{
Puzzle newPuzzle; //null value here. Why???
public Undo(Puzzle oldPuzzle)
{
Puzzle newPuzzle = oldPuzzle.Clone();
}
public void undo()
{
//back to previous step, ie the color of the buttons go back to previous color
}
I'm asking to do the undo function for back to previous stages for max four times. "The easiest way to do this is to create a copy of the puzzle and store it in an array of Puzzle. To do this I implemented a Clone method for puzzle. This returns a brand new puzzle set to exactly the same settings as the puzzle that I called Clone on." This is what our instructor says, but i still have no idea of how to implement this.
The easiest way to implement your "Undo" function would probably be with a stack. For each action you take on the puzzle, push an instance onto the stack. When the user opts to undo a move, pop the instance off of the stack.
See this article on Wikipedia for more information on stacks, and this MSDN article on the .NET Stack generic class.
Here's a little example of how to implement the stack mentioned by DBM. In stead of cloning the whole Puzzle class, I would recommend to rather just clone the array of Buttons (that should be enough for your Undo function):
Edit: If you need to keep track of the colors of the buttons in stead of the position of the buttons, you could probably rather just put an array of the buttons' current colors on the stack.
Stack<Button[,]> stack = new Stack<Button[,]>();
private void button4_Click(object sender, EventArgs e)
{
Button[,] buttons = new Button[2, 2] { { button1, button2 }, { button3, button4 } };
stack.Push((Button[,])buttons.Clone());
buttons[0, 0] = button2;
buttons[0, 1] = button1;
stack.Push((Button[,])buttons.Clone());
buttons[1, 0] = button4;
buttons[1, 1] = button3;
stack.Push((Button[,])buttons.Clone());
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
if (stack.Count > 0)
{
Button[,] buttons = stack.Pop();
txtButtonOrder.Text = buttons[0, 0].Text + buttons[0, 1].Text + buttons[1, 0].Text + buttons[1, 1].Text;
}
else
{
timer1.Enabled = false;
}
}
When you declare a variable inside a method, it will hide any variables in the class which have the same name. Instead of redeclaring the variable, you should just reference it:
int myVariable = 0; // Will always be 0
public void SetMyVariable()
{
int myVariable = 5; // Isn't the same as above
}
If you want to be explicit, you can add 'this.' in front of the variable name to always refer to the class variable:
this.myVariable = 5;
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm creating a unity quiz game using input fields.
How can I use text from an input field to match with an answer in a c# script?
hijinxbassist's example is good, however, i made an example that includes the other parts as well, like adding event listeners and declaring the fields.
Checking for single correct answer:
public Button submitAnswerBtn; // assign a UI button object in editor
public InputField answerInput; // assign a UI inputfield object in editor
private string a1_right_answer = "foo"; // make it public and edit the answer in editor if you like
private void Awake()
{
// add event listener when button for submitting answer is clicked
submitAnswerBtn.onClick.AddListener(() => {
// validate the answer
if(answerInput.text.ToLower() == a1_right_answer) {
// success
Debug.Log("Correct");
} else {
Debug.Error("Wrong");
}
});
Checking for multiple correct answers:
public Button submitAnswerBtn; // assign a UI button object in editor
public InputField answerInput; // assign a UI inputfield object in editor
private string[] a1_right_answers = { "foo", "bar", "foo1", "bar1" }; // multiple right answers
private bool is_right_answer = false; // default value
private void Awake()
{
// add event listener when button for submitting answer is clicked
submitAnswerBtn.onClick.AddListener(() => {
// loop through all the right answers
for (int i = 0; i < a1_right_answers.Length; i++)
{
// validate the answer
if(answerInput.text.ToLower() == a1_right_answers[i]) {
// success
is_right_answer = true;
break;
}
}
// check if the user got the right or wrong answer
if(is_right_answer) {
Debug.Log("Correct");
is_right_answer = false; // reset for next guess
}
else {
Debug.Log("Wrong");
// no need to reset 'is_right_answer' since its value is already default
}
});
I am not sure which part of this problem you are stuck on, but I will attempt to answer.
I think the most important thing when comparing an input field with a stored answer is to make sure the comparison is case insensitive. You can do this by converting both texts to either lowercase or uppercase.
var usersAnswer = answerInputField.text.ToLower();
var actualAnswer = "Some Answer".ToLower();
if (usersAnswer == actualAnswer)
{
Debug.Log("You got it right!");
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am working on an desktop application in C# that requires a panel background to be filled using dynamic values.For example if the panel of width 200px and the progress property is currently reached at 50% then 100px of the panel should have green color in it rest 100px will be as it.
here's a simple control that does the job
public partial class ProgressPanel : Panel
{
private float m_progress = 0;
private Color m_progressColor = Color.Green;
public ProgressPanel()
{
InitializeComponent();
}
/// <summary>
/// the progress value is between 0 & 100 inclusively
/// </summary>
public float Progress
{
get
{
return m_progress;
}
set
{
m_progress = value;
this.Invalidate();
}
}
public Color ProgressColor
{
get
{
return m_progressColor;
}
set
{
m_progressColor = value;
this.Invalidate();
}
}
private void ProgressPanel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(BackColor);
e.Graphics.FillRectangle(new SolidBrush(ProgressColor), new Rectangle(new Point(), new Size((int)(Width * Progress / 100), Height)));
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// ProgressPanel
//
this.Paint += new System.Windows.Forms.PaintEventHandler(this.ProgressPanel_Paint);
this.ResumeLayout(false);
}
}
just create a new empty class in your project & name it ProgressPanel then copy the above code into it.
now you can use your newly created ProgressPanel as you would use any other control from the designer
note that this example is a simplified one.
you may notice some flickering, but other than this it's totally functional
if you want to know how to upgrade this example to a professional control, I'd be happy to help
I am writing a piece of code that takes a user through a guided script. The user will have a few seconds to answer before the answer will be displayed.
So far, my code looks like this:
GuidedExercise3 exercise3 = new GuidedExercise3();
string AntonioAnswer = string.Empty; // expected answer
int upperBound = exercise3.Script.Count - 1; // zero-based counting
for(int i = 0; i < upperBound; i += 2)
{
labelInstructions.Text = exercise3.Script[i].TextToSpeak;
AntonioAnswer = exercise3.Script[i+1].TextToSpeak; // answer
SetTimer(AntonioAnswer, txtAntonio); // set timer sending in the answer and the TextBox object.
sysTimer.Start();
}
The odd lines of a List contain the question and the even lines contain the expected answer. My question is how do I display the question for X seconds and then get the user's answer in this WinForms app and then display the answer when the timer elapses, keeping the user from going to the next step of the script but allowing them to answer the question (which is in a Textbox).
I examined this StackOverflow question, but it doesn't match: Implementing a loop using a timer in C#
Here's how I would handle something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MoveNextQuestion();
timerAnswer.Interval = 5000;
timerAnswer.Start();
}
private string[] _questionsAndAnswers = new[]
{
"What colour is the sky?",
"Blue",
"What do chickens lay?",
"Eggs",
};
private int _currentIndex = -2;
private void timerAnswer_Tick(object sender, EventArgs e)
{
MoveNextQuestion();
}
private void buttonAnswer_Click(object sender, EventArgs e)
{
MoveNextQuestion();
}
private void MoveNextQuestion()
{
_currentIndex += 2;
if (_currentIndex < _questionsAndAnswers.Length)
{
labelQuestion.Text = _questionsAndAnswers[_currentIndex];
}
else
{
timerAnswer.Stop();
}
}
}
I was able to get this working fairly easily with a BackgroundWorker object. See the following article at MSDN for the exact coding. BackgroundWorker Class. In particular they have two examples in the documentation and the first example is sufficient. The BackgroundWorker class is allowing my UI to continue to accept user input while waiting on a timed answer. It displays the correct answer on the RunWorkerComplete event. So the BackgroundWorker's RunAsync gets called in my for loop.
I've run into the additional issue of the BackgroundWorker not returning control to my loop. I'm looking into that problem separately.
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 7 years ago.
Improve this question
I am trying to link a random seating code to my User Interface class and I am stumped on how I could call upon this at anytime through my user interface. The below is currently kept inside a FirstClassCarriage class.
{
Random rand = new Random();
bool[] seats = new bool[32];
//To keep a separate list of seats taken
List<int> seatsBooked = new List<int>();
bool quit = false;
do
{
Console.Clear();
//int seatAssignFirstClass = rand.Next(0, 32);-> Moved to switch-case 1: block
int seatAssignThirdClass = rand.Next(32);
int seatAssignFirstClass; //Variable moved from main loop
//Are there any seats booked already or this is the first?
if (seatsBooked.Count == 0) //if this is the first seat to be booked...
{
seatAssignFirstClass = rand.Next(0, 32);
seats[seatAssignFirstClass] = true;
seatsBooked.Add(seatAssignFirstClass); //Add seat to the list of booked seats.
}
else
{
do //while there are available seats and current seat has not being assigned before.
{
seatAssignFirstClass = rand.Next(0, 32);
if (!seatsBooked.Contains(seatAssignFirstClass)) //if seatAssignFirstClass is not booked.
{
seats[seatAssignFirstClass] = true;
}
//repeat while the random seat number is already booked and there are avaialable seats
} while (seatsBooked.Contains(seatAssignFirstClass) && seatsBooked.Count < 32);
//IMPORTANT: Number on line bellow needs tos be one bigger than rest
if (seatsBooked.Count < 34) //if seatsBooked list is not full for First Class
{
seatsBooked.Add(seatAssignFirstClass); //Add current random-generated seat to the list.
}
}
//IMPORTANT: Number on line bellow needs tos be one bigger than rest
if (seatsBooked.Count >= 34) //If all seats are booked
{
Console.WriteLine("All seats for First Class are booked");
Console.WriteLine("Press enter to continue...");
}
else //Give customer their seat nmumber
{
Console.WriteLine("Train seat number: {0}", seatAssignFirstClass + 1);
Console.WriteLine("Press enter to continue to the main menu...");
}
} while (!quit);
The smallest unit of code reuse in C# is a function. You need to put this code in a function, and then you can call it from other places. Easiest would be for that to be a public static function, but as you learn more about design you may find that there are better ways of sharing the functionality.
You can add a reference to classes in other files with the using keyword and the desired class' namespace
Example:
namespace MyProject.MyCore {
public class MyClass {
public void MyMethod() { }
}
}
You would then refer to this namespace in the calling class, like so:
using MyProject.MyCore
Which allows you to instantiate the class object, like so:
var myInstantiatedClass = new MyClass();
And call it's method like so:
myInstantiatedClass.MyMethod();
Methods can also be marked static, which removes the need to instantiate the class, and would be called instead using the Type.Method() syntax, like MyClass.MyMethod().
You can also forgo adding a reference by using a fully qualified path.
var myInstantiatedClass = new MyProject.MyCore.MyClass()
Of course, if this code is in a different project, or assembly, you'll have to add a reference to the project or binary to gain access to the types it provides.
This example may be your answer
Or you can use static methods like
namespace MyProject.MyCore {
public class MyClass {
public static void MyMethod() { }
}
}
And you can use this method from another class
MyProject.MyCore.MyClass.MyMethod();
I am currently taking a beginner's class in c#. We missed 2 consecutive classes because the teacher couldn't be there. So we didn't really see what we needed to do this. He said to just go see on MSDN, but that is usually way too complicated for me. So here is my problem:
I have to create a "Simon Says" program. Here is my current code (sorry for the French variables):
public partial class Form1 : Form
{
const byte LIMITE = 255;
const byte LIMITEBOUTON = 5;
byte[] _abyBouton = new byte[LIMITE];
Random _rand = new Random();
public Form1()
{
InitializeComponent();
}
//Blinks the Button. Works correctly.
void AnimerBouton(Button btnBouton, Color Cocoleur)
{
btnBouton.BackColor = Color.Black;
btnBouton.ForeColor = Color.White;
Update();
System.Threading.Thread.Sleep(500); // C'est inscrit en miliseconde
btnBouton.BackColor = Cocoleur;
btnBouton.ForeColor = Color.Black;
Update();
System.Threading.Thread.Sleep(500); // C'est inscrit en miliseconde
}
private void btnDémarrer_Click(object sender, EventArgs e)
{
//Creates an array with the 255 eventual moves.
for (byte byIndex = 0; byIndex <= LIMITE - 1; byIndex++)
{
_abyBouton[byIndex] = (byte)_rand.Next(1, LIMITEBOUTON);
}
for (byte byIndex = 0; byIndex <= LIMITE - 1; byIndex++)
{
//Takes care of the current progress in the game.
for (byte byIndex2 = 0; byIndex2 <= byIndex; byIndex2++)
{
switch (_abyBouton[byIndex2])
{
case 1:
{
AnimerBouton(btn1, Color.Green);
}
break;
case 2:
{
AnimerBouton(btn2, Color.Red);
}
break;
case 3:
{
AnimerBouton(btn3, Color.Yellow);
}
break;
case 4:
{
AnimerBouton(btn4, Color.Cyan);
}
break;
}
//Wait to see if the click is correct. No idea how to do this.
}
}
}
}
So I have to wait for the user to click a button and see if it is the correct one. I looked around and it was talking about events, but I couldn't grasp what I needed to do. I would appreciate some help on how to do this.
Thanks!
In the designer, on the properties window, click the lightning bolt icon. You will get a list of events for the selected control. Make sure the btnBouton control is selected, and find the Click event in the list. You should see btnDemarrer_Click in the drop down list. Select it. Now when the button is clicked, it should call your btnDemarrer_Click handler.
When you have not already written a handler, you can double-click the event in the list, and it will generate the method skeleton for you automatically. You can also double-click the control itself to generate the default event handler for that control. (In the case of buttons, I think the default event is the click event.)
If you want a particular method to wait until some work is done, you could look into AutoResetEvent. An extremely simplified example might help you get on the right track:
using System.Threading;
public static AutoResetEvent arEvent = new AutoResetEvent(false);
static void Main()
{
DoWork();
arEvent.WaitOne(); //WaitOne() "pauses" Main and waits for some work to be done.
DoWork();
arEvent.WaitOne();
}
static void DoWork();
{
//Some work is done here.
arEvent.Set(); //This lets Main() continue where it left off.
}
Using this, you could have btnDémarrer_Click wait for the user input then continue on after the user has done his clicking.