Check each string value in dictionary for specific characters c# - c#

I am trying to read through a dictionary and get all the values in it then check if the value in the dictionary location is equal to (A) when a button is clicked
if the value in the dictionary ends with (A) then the word "correct" is printed , else "incorrect is printed"
but that happens when i click the button is that the correctness and in-correctness of each value is printed. so it does identify the correct answer and the incorrect answer but i only need it to print out either correct of incorrect
the issue occurs in the OnGUI function.
the code allows for a random key which are questions to be selected on button click and its values which are answers displayed as buttons , you then click a button . correct answers are the values that end with (A) . bu clicking the buttons which are displayed with the value name you will check if you have selected the correct answer but there is a slight problem with it . it prints out the correctness and in-correctness of each value in the selected key
here is the entire code
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class testQuestions : MonoBehaviour {
Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>();
string []vl ;
string ky;
int Qnum;
string A;
int indx;
// Use this for initialization
void Start () {
dictionary.Add("ups", new string[] {"updegree", "popup (A)"});
dictionary.Add("down aroud the place like this ", new string[] {"sun", "bun(A)","art"});
dictionary.Add("left", new string[] {"higi (A)", "migi"});
dictionary.Add("right", new string[] {"een", "yyo(A)"});
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown("q"))
{
GenerateRandoms();
}
}
void GenerateRandoms()
{
string[] keys = new string[dictionary.Count];//get the dictionary count and store in array
dictionary.Keys.CopyTo(keys, 0);
var index = Random.Range(0, keys.Length);
var key = keys[index];
var value = dictionary[key];
ky= key;
vl = value;
foreach (string ku in value)
{
// create buttons with the ku text as the button text
indx = index;
Qnum +=1;
A = ku;
}
//---------- remove each after answer button click
//dictionary.Remove(key); // remove key after it is already displayed. this must only be exicuted at the end of the function
}
void OnGUI ()
{
int charlength = 0;
foreach(char NumOfChar in ky)
{
charlength ++;
}
GUI.TextArea(new Rect (0,0,charlength*10 + 100,20),"Key is " + ky /*+ " value is " + string.Join(",", vl) + " position is " +int.Parse(indx.ToString())*/);
for (int i = 0; i < dictionary[dictionary.Keys.ElementAt(indx)].Length; i++)
{
if (GUI.Button (new Rect(0, 30 + Screen.height-Screen.height + 40* i, 100, 20),dictionary[dictionary.Keys.ElementAt(indx)][i]))
{
for (int i2 = 0; i2 < dictionary[dictionary.Keys.ElementAt(indx)].Length; i2++)
{
string Answer = dictionary[dictionary.Keys.ElementAt(indx)][i2];
if (Answer.EndsWith("(A)"))
{
print ("Correct");
}
else
{
print ("Incorrect");
}
}
}
}
}
}

I assume you're loading the available answers to the form, maybe in labels with buttons beside them or the text of the button. Either way when you load the answers set the tag property of the correct button with an "A". If the tag of the clicked button has an "A" it's correct.
Changing to something this simple that is easily adapted to the structure you already have, would be much better than trying to make something that is inherently flawed work
In the event handler for the button click something like this should work:
void ButtonClck(object sender, eventargs e)
{
Button clickedbutton = (Button)sender;
if ((string)clickedbutton.Tag = "A")
{
print ("Correct");
}
else
{
print ("Incorrect");
}
}

The way to accomplish this is simply use an if statement following the initial buttion click event . you check if the source where that button gets its text is the correct answer .
if (GUI.Button (new Rect(0, 30 + Screen.height-Screen.height + 40* i, 100, 20),dictionary[dictionary.Keys.ElementAt(indx)][i]))
{
if (dictionary[dictionary.Keys.ElementAt(indx)][i].EndsWith ("(A)"))
{
print ("Correct");
}
else
{
print ("Incorrect");
}
}

Related

how to stop text changed texbox from runing contains text code?

How would I stop text changed from running if statement? because after I type {} the code runs, but if I type any letter or press enter after I type {} the code keeps on making new labels in every letter typed or entered.
This is for WPF c#
private void TextBox_TextChanged(object sender, EventArgs e)
{
if (textBox.Text.Contains("{") && textBox.Text.Contains("}"))
{
DraggableLabel ag = new DraggableLabel();
ag.Name = "A";
ag.Content = "you have bracket"; //(i + 1).ToString();
ag.BorderBrush = Brushes.Black;
ag.BorderThickness = new Thickness(2, 2, 2, 2);
DesigningCanvas.Children.Add(ag);
ab = ag;
}
}
Notwithstanding the comments about avoiding creating UI elements in event handlers, what you need is a system that only activates if there are new { } pairs in the textbox. Perhaps something like:
private int brasProcessed = 0;
private void TextBox_TextChanged(object sender, EventArgs e)
{
int countOpenBra = textBox.Text.Count(c => c == '{');
int countCloseBra = textBox.Text.Count(c => c == '}');
//if there is a matched pair of {} (equal counts) and more { have appeared than we know we've processed before...
if (countOpenBra == countCloseBra && countOpenBra > brasProcessed)
{
DraggableLabel ag = new DraggableLabel();
ag.Name = "A";
ag.Content = "you have bracket"; //(i + 1).ToString();
ag.BorderBrush = Brushes.Black;
ag.BorderThickness = new Thickness(2, 2, 2, 2);
DesigningCanvas.Children.Add(ag);
ab = ag;
//mark the current count of {} as processed so the code will not fire again until someone adds a new { } pair
brasProcessed = countOpenBra;
}
}
Now this code will only fire when new pairs of { } are added. Every time you add a { } pair the code will run. It does not cater for deleted. It does not cater for multiples if a large amount of text containing multiple { } is pasted in. It hence likely needs some improvement but as others have noted you didn't tell us what you were trying to do, only that your solution for it was broken, and alas the solution didn't really allow us to infer what you're trying to do

C# increment decrement List values

So sorry for this vague question... its doing my head in...
Basically just a test project, use the [+] key to add a bunch of values into the List.... The arrow keys need to go up and down the List values...
When a new value is added to the list the "historySelected" is reset, so that the 'Up Arrow'.. always selects the last item added in the List first, and then if you keep pressing it, it goes back through the List values. At anytime if the 'Down Arrow' key is pressed it needs to go back to the previous value in the List of values. At no point should a Up Arrow key followed by a Down Arrow key show the same List value, and vice versa..
The behavior I'm looking for is much like a developer console with a command history, where Up arrow goes further back in history, and Down arrow the opposite.
Again apologies for the code, its been through so many test changes, currently this works going Up arrow to the start of the List value, and then using the Down arrow to go all the back to the highest List index... but the problem is if you go half way through the List (or inbetween anyway), and switch from Up arrow.. to Down arrow.. the values increment/decrement don't act accordingly... I can't seem to get the right codelogic for it.
Any help or suggestions thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrowKeys {
class Program {
//public static List<string> cmdHistory = new List<string>() { "1", "2", "3", "4", "5" };
public static List<string> cmdHistory = new List<string>();
public static int cmdHistoryCount = 0;
public static int historySelected = 0;
public static int num = 0;
public static string current = "";
public enum UpDown {
reset,
up,
down
};
public static UpDown LastUpDown;
static void Main(string[] args) {
bool running = true;
while (running) {
ConsoleKeyInfo kb = Console.ReadKey();
switch (kb.Key) {
case ConsoleKey.Escape:
Console.WriteLine("Exit");
running = false;
return;
case ConsoleKey.Add:
cmdHistory.Add(num.ToString());
cmdHistoryCount++;
historySelected= cmdHistoryCount;
LastUpDown = UpDown.reset;
Console.WriteLine(string.Join(" ", cmdHistory.Cast<string>().ToArray()));
num++;
break;
case ConsoleKey.UpArrow:
UpArrow();
LastUpDown = UpDown.up;
Console.WriteLine("UpArrow pressed");
Console.WriteLine(current);
break;
case ConsoleKey.DownArrow:
DownArrow();
LastUpDown = UpDown.down;
Console.WriteLine("DownArrow pressed");
Console.WriteLine(current);
break;
}
}
}
public static int Clamp(int value, int min, int max) {
return (value < min) ? min : (value > max) ? max : value;
}
public static void UpArrow() {
if (cmdHistoryCount != 0) {
if (LastUpDown == UpDown.down) {
if (historySelected - 1 == 0) {
return;
}
}
current = cmdHistory[historySelected - 1];
if (historySelected - 1 == 0) {
return;
}
historySelected--;
}
}
public static void DownArrow() {
if (cmdHistoryCount != 0) {
if (LastUpDown == UpDown.up) {
if (historySelected + 1 > cmdHistoryCount) {
return;
}
}
current = cmdHistory[historySelected - 1];
if (historySelected + 1 > cmdHistoryCount) {
return;
}
historySelected++;
}
}
}
}
It sounds like you simply need to stop your index going out of range. It's not clear what the existing code was intended to do, but your clarification seems to imply it's not necessary. Try this:
public static void UpArrow()
{
historySelected = Math.Max(0, historySelected - 1);
current = cmdHistory[historySelected];
}
public static void DownArrow()
{
var maxIndex = cmdHistory.Count - 1;
historySelected = Math.Min(maxIndex, historySelected + 1);
current = cmdHistory[historySelected];
}
If I'm understanding what you're looking for correctly, a pair of dueling stacks might work for your case. They're going to give you the FILO/LIFO style item access you're looking for. Drop the List and do something like:
var UpStack = new Stack<string>();
var DownStack = new Stack<string>();
On "new item"
UpStack.Push(newItem);
On "Up"
DownStack.Push(UpStack.Pop());
On "Down"
UpStack.Push(DownStack.Pop());
If you wanted a "buffer" item that isn't in either of the stacks, that's easy enough to do by just Popping into the buffer item. It's a little more management, because you'd have to push it onto one stack, then pop the other each time, but it's whatever. There's also the Peek() method, which gets the item on top of a Stack without Popping it, so you use that for your display item, as well.

Return value from method

I am creating calculator with 20 textboxes - 10 for input, 10 for output. After creating a method into which I put parameter(defined in the first 10 textboxes) I return value to main method.
To get all 10 values is it really necessary to write code for all 10 or more text boxes as I have already started or there is smarter way how to pass into the method textbox parameters and return multiple values at once?
UPDATE:
As you recomended I created List of Tuples and used foreach loop to loop through them, but now i get error:
Error 1 Cannot implicitly convert type 'int' to 'string'. Could you help me to point out where the problem is?
private void button1_Click(object sender, EventArgs e)
{
List<Tuple<TextBox,TextBox>> tuple1 = new List<Tuple<TextBox,TextBox>>();
tuple1.Add(Tuple.Create(textBox1, textBox2));
tuple1.Add(Tuple.Create(textBox3, textBox4));
tuple1.Add(Tuple.Create(textBox5, textBox6));
tuple1.Add(Tuple.Create(textBox7, textBox8));
foreach (Tuple<TextBox,TextBox> box in tuple1)
{
var inputBox = box.Item1;
var outputBox = box.Item2;
outputBox.Text = MethodA(Convert.ToInt32(inputBox.Text));
}
}
private int MethodA(int Parameter1)
{
int A = Parameter1;
int B = 20;
int C;
if (A == 16 && B == 20) { C = 15; } else if (A == 20 && B == 20) { C = 25; } else { C = 0; };
return C;
}
You could store all the input-output textbox combination in the constructor:
private List<Tuple<TextBox, TextBox>> textBoxes = new List<Tuple<TextBox, TextBox>>();
public Form1() {
InitializeComponents();
textBoxes.add(Tuple.Create(textBox1, textBox4);
// ...
}
And then, in button1_Click, just iterate over all the textboxes:
foreach (Tuple<TextBox, TextBox> boxes in textBoxes) {
var inputBox = boxes.Item1;
var outputBox = boxes.Item2;
outputBox.Text = MethodA(Convert.ToInt32(inputBox.Text));
}
This might not be the best answer, but it would work:
public class Extensions
{
public MethodA(this TextBox tb)
{
tb.Text = (Convert.ToInt32(tb.Text) + 5).ToString();
}
}
now you can just call:
textBox1.MethodA();
textBox2.MethodA();
...etc.
This isn't necessarily recommended, but it's one way you could simply doing this multiple times.
If you won't be repeating this, it'd probably be better to just inline the logic the same way:
textBox1.Text = (Convert.ToInt32(textBox1.Text) + 5).ToString();
textBox2.Text = (Convert.ToInt32(textBox2.Text) + 5).ToString();
textBox3.Text = (Convert.ToInt32(textBox3.Text) + 5).ToString();

Conversion program storing information in array and using a combobox

This is homework (I always try to point that out so it's up front). The program is a conversion program. The user picks a conversion option from a combo box and then enters a length (ie: Feet to meters) when the user hits calculate the program calculates the conversion. I have several questions because the array part is confusing me. I wanted to make sure I am going in the right direction.
I think I am using my array to populate my combo box (I used an example provided although I do not fully understand it). When the user hits the calculate button should I be storing my conversion values in the same array? something like:
string [,] conversions = { {kilometers to miles, .11111}, {miles to kilometers, .11111}}
Or am I heading in the right direction with what I have? To be clear as it is coded the array populates my combobox so if I add the extra data then it will display those numbers in the combobox, which isn't really what I am going for.
My next question, when the user hits calculate button how is it going to know what option the user has selected? I think it has something to do with index but I'm confused as far as what is actually declaring it?
*****Disregard this question. I think I found an answer*********
Answer on Updating Labels
Finally I think my last question is the page has labels next to the textboxes so if the user chooses 'Miles to kilometers" the entry textbox is going to say Miles and then the answer textbox would say Kilometers... What is that called? I need to find it in my book and cannot. I know I'm missing something but I'm trying to find either an example or where in the book it was covered and I'm simply not seeing it.
Below is my code that I currently have.
public partial class FrmConversions : Form
{
const double Miles_To_Kilometers = 1.6093;
const double Kilometers_To_Miles = 0.6214;
const double Feet_To_Meters = 0.3048;
const double Meters_To_Feet = 3.2808;
const double Inches_To_Centimeters = 2.54;
const double Centimeters_To_Inches = 0.3937;
public FrmConversions()
{
InitializeComponent();
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void FrmConversions_Load(object sender, EventArgs e)
{
cboConversions.Items.Clear(); //clear the combobox
string[,] conversions =
{
{"Kilometers to Miles" , "Miles to Kilometers"},
{"Feet to Meters" , "Meters to Feet"},
{"Inches to Centimeters", "Centimeters to Inches"}
};
foreach (string str in conversions)
{
cboConversions.Items.Add(str);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
txtEntry.Clear();
txtAnswer.Clear();
}
public bool IsDecimal(TextBox txtEntry, string name)
{
try
{
Convert.ToDecimal(txtEntry.Text);
return true;
}
catch (FormatException)
{
MessageBox.Show(name + " must be a decimal value.", "Entry Error");
txtEntry.Focus();
return false;
}
}
private void btnCalculate_Click(object sender, EventArgs e)
{
int index = cboConversions.SelectedIndex;
if (index != -1)
{
try
{
if (IsDecimal())
{
txtAnswer.Text = ToString;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" +
ex.GetType().ToString() + "\n" +
ex.StackTrace, "exception");
}
}
}
}
}
}
There are many ways to do this, a Dictionary would be neat?
In this example, the Keys of the dictionary (the strings I specified) are loaded into the combo box. Later, those strings can be used to retrieve the conversion value from the dictionary.
// Declare at the top
Dictionary<string, double> conversions = {
{ "Kilometers to Miles", Kilometers_To_Miles},
{ "Miles to Kilometers", 1 / Kilometers_To_Miles},
{ "Feet to Meters", Feet_To_Meters},
{ "Meters to Feet", 1 / Feet_To_Meters},
etc
};
// In Form Load
foreach (string str in conversions.Keys)
{
cboConversions.Items.Add(str);
}
// In btnCalculate_Click
var conversionValue = conversions[cboConversions.Text];
var convertedValue = (double)txtEntry.Text * conversionValue; // Need to validate is numeric
txtAnswer.Text = convertedValue
If you were hellbent on using arrays then this would work too, but cheats by using LINQ at the end:
// Declare at the top
object[,] conversions = {
{ "Kilometers to Miles", Kilometers_To_Miles},
{ "Miles to Kilometers", 1 / Kilometers_To_Miles},
{ "Feet to Meters", Feet_To_Meters},
{ "Meters to Feet", 1 / Feet_To_Meters},
etc
};
// In Form Load
foreach (string str in conversions)
{
cboConversions.Items.Add(str[0]);
}
// In btnCalculate_Click
var conversionValue = conversions.First(x => x[0] == cboConventions.Text)[1];
var convertedValue = (double)txtEntry.Text * conversionValue; // Need to validate is numeric
txtAnswer.Text = convertedValue

Need help making a list accept multiple user inputs without removing the input before it

I need help making a Score Calculator for my class. The inputs for the scores can't be preset and it has to add up all previous inputs while increasing the count number.
For example say I entered 23 into the text box and hit enter then typed in 45 i need my program to keep the 23 and add it to the 45 and it needs to repeat this for as long as the user inputs numbers.
I know it needs to be a collection and i have the basis for it down i just need the code that will save the input from before and add it to the new one and save that total to add it to the next input.
This is my attempt at solving this problem:
List<decimal> score = new List<decimal>();
score.Add(scoreInput);
decimal scoreTotal = 0;
decimal scoreHolder = 0;
foreach (decimal d in score)
{
scoreTotal = scoreHolder + scoreInput;
scoreHolder = scoreInput;
scoreInput = 0;
txtTotal.Text = scoreTotal.ToString("");
txtCount.Text = score.Count.ToString("");
txtScore.Clear();
txtScore.Focus();
}
Simply add an event handler for the KeyDown event, and use a code like the following:
private void tbEntry_KeyDown(object sender, KeyEventArgs e)
{
Decimal entry;
if (e.KeyCode == Keys.Enter)
{
if (Decimal.TryParse(tbEntry.Text, out entry))
{
score.Add(entry);
}
tbResult.Text = score.Sum(s => s).ToString();
tbEntry.Text = string.Empty;
}
}
This is one way of doing what you want to achieve.
EDIT:
This is assuming that you have your variable "score" declared as a member of your Form:
private List<decimal> score = new List<decimal>();
Cheers

Categories