x


Problems with a forloop never returning true

I am making a program that gennerates a code, as a string of number, then the user inputs a number of the same lenght and the program compares the two sets of numbers. The programme then generates a guitext for each number and colors it according to wether the number is the correct number and place in the code(green), the number is in the code but not at the given place (yellow), or the number is not pressent in the code (red). I want the code to only return as manny yellows of a number as times that the number is prsent in the code. I coded it in c# and I'm using three forloops, but for a reason i can not figur out the innermost forloop never returns true even though it should.

any ideas, solutions are welcome. I'm posten the funtion where the comparring is happening. the var line is used for controlling the spacing of the guiTexts teh var n is the lenght of the code being checked.

void hack () {
    //sets input=the player indput
    input = codeIn.text;
    line++;
    //transforms code and input to char arrays
    code.ToCharArray(0, n);
    input.ToCharArray(0, n);
    //creating array for storing the number of used instances of number
    numberUsed=new int[10];
    //setting each int to 0
    for (int i = 0; i < n; i++){
       numberUsed[i]=0;
    }
    //tjekking input against code
    if (input==code){
       //if the code is correct the output is "code accepted"
       //resets input guiText
       codeIn.text="";
       //prints the correct code in a guiText
       GameObject test01 = new GameObject("GUIText");
       test03 = (GUIText)test01.AddComponent(typeof(GUIText));
       test03.text = input;
       test03.material.color = Color.green;
       test03.transform.position = new Vector3(0.1f,0.8f-line*0.025f,0f);
       line++;
       //prints the "code accepted" in a guiText
       GameObject test04 = new GameObject("GUIText");
       test03 = (GUIText)test04.AddComponent(typeof(GUIText));
       test03.text = "code accepted";
       test03.transform.position = new Vector3(0.1f,0.8f-line*0.025f,0f);

       Log(timer.ToString());
    }else{
       for (int i = 0; i < n; i++){
         string[] inputCorrectness = new string[n];
         for (int j = 0; j < n; j++){
          //if the number is correct the code returns green
          if (code[i]==input[i]){
              inputCorrectness[i] = "green";
              //raises the count of uses of the number by one
              numberUsed[input[i]-48]++;
              break;

          //if the number(input[i]) is present at another location in the code    
          }else if(code[j]==input[i]){

              //cheks the number of used instances of the digit
              if (numberUsed[input[i]-48]>=numberCount[input[i]-48]){
                 inputCorrectness[i] = "red";
                 break;
              } else {
                 for (int k=0; k<n; k++){
                   print("derp");
                   /*if the input[i] is also input at another place in the code (input[k]) 
                   and that input is equal to the code, set current inputcolor to red*/
                   if (code[k]==input[k] && input[k]==input[i]){
                    inputCorrectness[i] = "red";
                    print("herp");
                    break;
                   //else set current inputcolor to yellow  
                   }else{
                    inputCorrectness[i] = "yellow";
                    numberUsed[input[i]-48]++;
                    break;
                   }
                 }
                 //breaks outer forloop else the texts turns back to red.
                 break;
              }
          //if the number is not in the code it returns red   
          } else {

          inputCorrectness[i] = "red";
          }   

         }    
         //print(numberCount[input[i]-48]);
         //print(numberUsed[input[i]-48]);

       //print(input[i]+inputCorrectness[i]);
       codeIn.text="";
       //prints the number with the earlyer given color
       GameObject test01 = new GameObject("GUIText " + i);
       test02[i] = (GUIText)test01.AddComponent(typeof(GUIText));
       test02[i].text = ""+input[i];
       test02[i].transform.position = new Vector3(0.1f+i*0.01f,0.8f-line*0.025f,0f);
       switch(inputCorrectness[i]){
         case "green":
          test02[i].material.color = Color.green;
          break;
         case "yellow":
          test02[i].material.color = Color.yellow;
          break;
         case "red":
          test02[i].material.color = Color.red;
          break;
       }
    }   
}
}   
more ▼

asked Mar 19 '12 at 05:37 AM

Dorukim gravatar image

Dorukim
0 1 1

(comments are locked)
10|3000 characters needed characters left

3 answers: sort voted first

I would suggest you re-approach the way you've got this programed. I've been looking at it for a few minutes and I'm reminded that usually I get myself to rethink how I've approached a problem if I've got 3 loops nested. The only time I'd allow myself to do this is for a pre-runtime (in-editor) function.

I would suggest using either a custom datatype that would allow you to store a number value and all of the indexes where it occurs. Or a Dictionary where your number is the key and you have a string value that you could parse for indexes of all of the occurrences.

I needed a break from what I was working on tonight, so I wrote a Dictionary based solution. I think you'll find it pretty easy to read, but let me know if you have any questions. :). I almost always use Lists too for my collections, as I believe they're faster than just an ArrayList.

    using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MasterMind : MonoBehaviour {

    int itemCount = 8;

    int minValue = 0;
    int maxValue = 10;

    int numTries = 0;
    bool hasSolution = false;

    Dictionary<int, int> masterItemIndex = new Dictionary<int, int>();

    //If this flag is true, we'll store our correct answers
    bool storeCorrects = true;
    List<int> correctItems = new List<int>();

    void Awake()
    {
       for( int i = 0; i < itemCount; i++ ) {
         bool goodValue = false;
         while( !goodValue ) {
          int newInt = Random.Range(minValue, maxValue);
          if( !masterItemIndex.ContainsKey(newInt) ) {
              masterItemIndex.Add(newInt, i);
              goodValue = true;
          }
         }
       }

       //verify Dictionary
       foreach (var element in masterItemIndex)
           Debug.Log(element);
    }

    List<int> SimulateGuess()
    {
       List<int> output = new List<int>();
       for( int i=0; i < itemCount; i++ )
       {
         if( storeCorrects && correctItems.Count > i ) {
          if( correctItems[i] != -999 ) {
              output.Add( correctItems[i] );
              continue;
          }
         }
         //roll a unique number for our simulated guess
         bool isUnique = false;
         while( !isUnique ) {
          int newInt = Random.Range( minValue, maxValue );
          if( !output.Contains(newInt) ) {
              output.Add(newInt);
              isUnique = true;
          }
         }
       }

       return output;
    }

    // Update is called once per frame
    void Update () {
       if( hasSolution ) return;

       //Simulate our guesses
       List<int> guesses = SimulateGuess();

       //Check to see how well we did
       CheckGuess(guesses);
    }

    void CheckGuess (List<int> inGuesses)
    {
       List<string> guessFeedback = new List<string>();

       //loop through guesses
       int numberCorrect = 0;
       for(int i=0; i < inGuesses.Count; i++ )
       {
         int currentNumber = inGuesses[i];
         if( masterItemIndex.ContainsKey(currentNumber) ) {
          if( (int)masterItemIndex[currentNumber] == i ) {
              guessFeedback.Add("green");
              ++numberCorrect;
          }
          else {
              guessFeedback.Add ("yellow");
          }
         }
         else {
          guessFeedback.Add("red");
         }
       }

       //Assess how we did
       ++numTries;
       if( numberCorrect == itemCount ) {
         hasSolution = true;
         string solution = "";

         for( int i=0; i < inGuesses.Count; i++ ) {
          solution += inGuesses[i];
          if( i < inGuesses.Count - 1 ) solution += ", ";
         }
         Debug.Log("A WINNER IS YOU! It took you " + numTries + " tries. The correct solution was: " + solution);
       }
       else if( numberCorrect > 0 ){
         Debug.Log("You got " + numberCorrect + " correct. Go again.");
       }
       else {
         Debug.Log("Um. Not. Even. Close...");
       }

       if( !storeCorrects ) return;
       //show guessFeedback List and store green ones (not optimal, but it will get us there eventually)
       correctItems = new List<int>();
       for( int i=0; i < guessFeedback.Count; i++ ) {
         if( guessFeedback[i] == "green" ) {
          correctItems.Add(inGuesses[i]);
         }
         else {
          correctItems.Add(-999);
         }
       }
    }
}
more ▼

answered Mar 19 '12 at 07:11 AM

addo gravatar image

addo
51 2 6 8

(comments are locked)
10|3000 characters needed characters left

Hey Burton

Thank you for your reply. I can see its a cleaner and more clear method, so I have rewriten my code based on your solution.

But it dosn't sovle my problem with the returns of more yellows of a number than there is instances in the code.

ex. if the random code contains two instances of the number 7 and the user inputs 7 three times, the returning 7's should be, 2 green and one red, 2 yellow and one red or one green one yellow and one red. But as it is, it return 3 yellow, 2 yellow and one green or 2 green and one yellow.

anyone got an solution for this? code inserted below

using UnityEngine;

using System.Collections; using System.Collections.Generic;

public class hacking : MonoBehaviour {

//used to calculate line spaces float line = 0; //GUItext containing the user intput public GUIText codeIn; public float timer = 0; private GUIText[] outNumber = new GUIText[8]; private GUIText outText = new GUIText();

int n; //used to generate a random number for the code float a; int itemCount = 8;

int minValue = 0; int maxValue = 10;

int numTries = 0; bool hasSolution = false;

Dictionary<int, int> masterItemIndex = new Dictionary<int, int>();

//If this flag is true, we'll store our correct answers bool storeCorrects = true; List correctItems = new List(); List guesses = new List();

 void Awake()
{
   for( int i = 0; i < itemCount; i++ ) {
     bool goodValue = false;
     while( !goodValue ) {
      int newInt = Random.Range(minValue, maxValue);
      if( !masterItemIndex.ContainsKey(newInt) ) {
          masterItemIndex.Add(newInt, i);
          goodValue = true;
      }
     }
   }

   //verify Dictionary
   foreach (var element in masterItemIndex)
       Debug.Log(element);
}


void Start() {

    //n = code.Length;
    //Creating log if none exists and makes an entry in log
    if(!System.IO.File.Exists("C://dataLog/log.txt")){
       System.IO.File.WriteAllText("C://dataLog/log.txt", " New Test Participant:");
    }else{
       string existingText = System.IO.File.ReadAllText("C://dataLog/log.txt");
       System.IO.File.WriteAllText("C://dataLog/log.txt", existingText + " New Test Participant:");
    }
    //sets timer
    timer = 0;
}

    void CheckGuess (List<int> inGuesses)
{
   List<string> guessFeedback = new List<string>();
    line++;
   //loop through guesses
   int numberCorrect = 0;
   for(int i=0; i < inGuesses.Count; i++ )
   {
     int currentNumber = inGuesses[i];
     if( masterItemIndex.ContainsKey(currentNumber) ) {
      if( (int)masterItemIndex[currentNumber] == i ) {
          guessFeedback.Add("green");
          ++numberCorrect;
      }
      else {
          guessFeedback.Add ("yellow");
      }
     }
     else {
      guessFeedback.Add("red");
     }
   }

    codeIn.text="";
    for (int i= 0; i < itemCount; i++){
       //prints the number with the earlyer given color
       GameObject test01 = new GameObject("GUIText " + i);
       outNumber[i] = (GUIText)test01.AddComponent(typeof(GUIText));
       outNumber[i].text = ""+inGuesses[i];
       outNumber[i].transform.position = new Vector3(0.1f+i*0.01f,0.8f-line*0.025f,0f);
       switch(guessFeedback[i]){
         case "green":
          outNumber[i].material.color = Color.green;
          break;
         case "yellow":
          outNumber[i].material.color = Color.yellow;
          break;
         case "red":
          outNumber[i].material.color = Color.red;
          break;
       }
    }
   //Assess how we did
   ++numTries;
   if( numberCorrect == itemCount ) {
     hasSolution = true;
     string solution = "";

     for( int i=0; i < inGuesses.Count; i++ ) {
      solution += inGuesses[i];
      if( i < inGuesses.Count - 1 ) solution += ", ";
     }

       line++;
       //prints the "code accepted" in a guiText
       GameObject test04 = new GameObject("GUIText");
       outText = (GUIText)test04.AddComponent(typeof(GUIText));
       outText.text = "code accepted";
       outText.transform.position = new Vector3(0.1f,0.8f-line*0.025f,0f);
   }
   else if( numberCorrect > 0 ){
     Debug.Log("You got " + numberCorrect + " correct. Go again.");
   }
   else {
     Debug.Log("Um. Not. Even. Close...");
   }

   if( !storeCorrects ) return;
   //show guessFeedback List and store green ones (not optimal, but it will get us there eventually)
   correctItems = new List<int>();
   for( int i=0; i < guessFeedback.Count; i++ ) {
     if( guessFeedback[i] == "green" ) {
      correctItems.Add(inGuesses[i]);
     }
     else {
      correctItems.Add(-999);
     }
   }
guesses.Clear();
}


// Update is called once per frame
void Update () {
    //starts timer
    timer += Time.deltaTime;
           //Simulate our guesses



    codeIn.enabled = true;
    //int n = code.Length;
    string c = Input.inputString;
    //testing input
    switch (Input.inputString){
       //if input is a backspace and the inputstring isn't zero, delete the last number in the string
       //need looking at, doesn't delete the right entry
       case ("\b"):
         if (codeIn.text.Length != 0){
                codeIn.text = codeIn.text.Substring(0, codeIn.text.Length - 1);
          guesses.Remove(guesses.Count);
          print(guesses.Count);
       }
          break;
       //if the input is enter, run the hacking system     
       case ("\r"):
         //Check to see how well we did
         CheckGuess(guesses);
         break;
    //if the input is a nu ber, ad the number to the input string if the string is shorter than n  
    case "0":
    case "1":
    case "2":
    case "3":
    case "4":
    case "5":
    case "6":
    case "7":
    case "8":
    case "9":
          if (codeIn.text.Length<itemCount){
          guesses.Add(int.Parse(c));
          codeIn.text+=c;
          print(guesses.Count);
          }
         break;   
    }  
}

//adding timer to log
public void Log(string text){
    if(System.IO.File.Exists("C://dataLog/log.txt")){
       string existingText = System.IO.File.ReadAllText("C://dataLog/log.txt");
       System.IO.File.WriteAllText("C://dataLog/log.txt", existingText + " " + text + " " + timer.ToString() + ";");
    }
}

}

more ▼

answered Mar 21 '12 at 12:02 PM

Dorukim gravatar image

Dorukim
0 1 1

(comments are locked)
10|3000 characters needed characters left

Sorry I missed the point a bit there, hehe. This is hardly a full solution, but you might want to make another table as you go through and store uniques. When you get a duplicate, you pass over it.

Only issue there is you're not giving them feedback from every number. I think the type of 1:1 feedback you're trying to give is at odds with the duplicates issue. If you give them feedback for each number, you'll have duplicate feedback. If you don't give feedback for duplications, they'll likely ascertain that the number (they'll end up spamming multiples of) exists in the set, actually making the code easier to crack in some regards.

I was going to suggest another color to indicate "correct, but duplicates", but the user can just do 012344456 and if they see the other color they know 4 is there. Maybe that's the point, but it seems like a solution for this case might break the integrity of the challenge.

That's all I've got and it's not much of an answer, but maybe it will give you some things to think about.

more ▼

answered Mar 21 '12 at 12:17 PM

addo gravatar image

addo
51 2 6 8

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x4370
x97
x14

asked: Mar 19 '12 at 05:37 AM

Seen: 381 times

Last Updated: Mar 21 '12 at 12:17 PM