Search Unity

How to compare all string in a List<string>?

Discussion in 'Scripting' started by magnurpai, Jun 19, 2016.

  1. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9
    I am making a slotmachine. And working on the part were I tell if the player has won.

    So, now I have a list (List<String> winLineSymbols) that contrain 5 strings.
    For example:

    0 - Bell
    1 - Seven
    2 - Cherry
    3 - Cherry
    4 - Cherry


    Problem one: How can I compare all of them to see how many is in a row?

    Problem two: The position is also important. Take the example above...
    Even though the results show 3x Cherry, they were on the last 3 reels of
    the slotmachine....hence not giving the player a win.

    If it was:

    0 - Cherry
    1 - Cherry
    2 - Cherry
    3 - Seven
    4 - Bell

    on the otherhand, the player would have 3 in a row, giving him a small win.

    I need to check for 3, 4 and 5 in a row.
     
  2. Severos

    Severos

    Joined:
    Oct 2, 2015
    Posts:
    181
    I'm not an expert in slot machines, but if I understand correctly you want to start checking for same strings in a row starting from first one. Maybe you can use LINQ with Aggregate??
     
  3. CrymX

    CrymX

    Joined:
    Feb 16, 2015
    Posts:
    179
    1. Use Linq like says Severos

    2. Maybe you have a conception problem here, a dictionnary like <[Items][int]> is more easy to use in this case, let us know
     
  4. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9
    Hmm. You guys might be correct. I don't have much experience in either Linq or Dictionnary use in C# Unity.
    Looking into it now. After googling for 5 minutes, Linq looks usefull, but have still not figures out how to solve "problem 2" with it.

    CrymX: The use of dictionnary looks interesting. I'm looking into it.
     
  5. shaderop

    shaderop

    Joined:
    Nov 24, 2010
    Posts:
    942
    You're using the worst possible data structure to represent the slot machine, and that's why you're having issues. Why are you using a single list of strings with this weird, nonsensical definition of adjacency based on an arbitrary choice of positions in the list?

    It would make more sense to have a list for each reel in the slot machine, with and index into each list that indicates the position of the currently showing symbol.

    Or, in code:
    Code (csharp):
    1. string[] reel1 =  {"Cherry", "Seven", "Bell"};
    2. string[] reel2 = {"Cherry", "Seven", "Bell"};
    3. string[] reel3 = {"Cherry", "Seven", "Bell"};
    4.  
    5. int reel1index = Random.Range(0, reel1.Length);
    6. int reel2index = Random.Range(0, reel2.Length);
    7. int reel3index = Random.Range(0, reel3.Length);
    8.  
    9. if (reel1[reel1index] == reel2[reel2index] && reel2[reel2index] == reel3[reel3index])
    10.   Log("We have a winner!");
    11.  
     
    Last edited: Jun 20, 2016
    LeftyRighty likes this.
  6. CrymX

    CrymX

    Joined:
    Feb 16, 2015
    Posts:
    179
    If i have understood you, you need to have at minimum the 3 first elements the same to win right ?
     
  7. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    The sane way to do slot machines is to use a 2D array and simply rotate a row index for each column when the lever is pulled. You can then create a list and add the elements by iterating over the columns at the row index. Then send the list off to a function that can determine the winning condition. Iterate the list and count the number of matching elements. The iterator will also give you the position of where the matches begin.
     
    Last edited: Jun 20, 2016
  8. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9

    Testing this as we speak. I know that my code might be unortodox, but bare with me... I'm quite rusty.
    Anywho, i'm very new to this use of for loops. I usually do the standard for(int i = 0; i < something; i++)

    So when you start a forloop with ; I'm not sure what is going on.
    But, testing it now... stay tuned :p

    Question: I also never used enum that much. What do i send in the function to actually run it?
     
  9. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    I'm just assigning the iterator variable outside the loop instead of inside. It lets you handle extra stuff at the end of method if you wish to.

    P.S. The version you quoted has the matchStartIndex inside the for loop which makes it a little more clear. I'm not sure if you want to do extra stuff at the end or not.
     
  10. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9
    This is more or less what I am doing, just in a bit more complicated weird way.
    I'm a little rusty in my coding, and shoting from the hip sinse i've never done a project like this.
    But thank you very much for you answer :)
     
  11. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9

    So it is kinda like writing:

    for(matchStartIndex = 0; matchStartIndex < row.Count - MinMatchesForWin; ++matchStartIndex) ??

    Also, still not sure what to pass into the function to make it run.
     
  12. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Exactly like that. You pass in your "winLineSymbols" list. I've updated my reply with a better solution.
     
  13. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9
    Again... sorry for all the questions, but there are alot of new code here I am not used to, but super helpfull man!

    With the updated version, are you suggestion that I make a new c# script with:


    1. public class SlotWinnerResult
    2. {
    3. public int MatchStartIndex;
    4. public int MatchCount;

    5. public SlotWinnerResult(int pMatchStartIndex, int pMatchCount)
    6. {
    7. MatchStartIndex = pMatchStartIndex;
    8. MatchCount = pMatchCount;
    9. }
    10. }


      And post the other part of the code into my current script? or?

      I'm getting an error that the out parameter pResult must be assigned to before control leaves the current method.

      Never really used "out" in a function like that so not sure how it works.
     
  14. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Yes, put SlotWinnerResult in its own script file. I assume you have a SlotMachine class. Put the CheckWinner function in there. I updated the code again. CheckWinner is now static and has a new parameter for MinMatchesForWin. I also added an example of how to call the function in the SlotMachine.Awake method. The "out" keyword basically allows multiple return results. The code below seems to be working.

    Code (CSharp):
    1. public class SlotWinnerResult
    2. {
    3.     public int MatchStartIndex;
    4.     public int MatchCount;
    5.  
    6.     public SlotWinnerResult(int pMatchStartIndex, int pMatchCount)
    7.     {
    8.         MatchStartIndex = pMatchStartIndex;
    9.         MatchCount = pMatchCount;
    10.     }
    11. }
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class SlotMachine : MonoBehaviour
    5. {
    6.    public int MinMatchesToWin = 3;
    7.  
    8.    void Awake()
    9.    {
    10.      //Call the method like this
    11.      List<string> rowSymbols = new List<string>() { "Cherry", "Cherry", "Bell", "Bell", "Bell", };
    12.      SlotWinnerResult result = SlotMachine.CheckWinner(MinMatchesToWin, rowSymbols);
    13.      if (result != null)//we have a winner, handle the results
    14.      {
    15.        //if our matches begin at the very left reel
    16.        if (result.MatchStartIndex == 0)
    17.        {
    18.          //reward the player based on the number of matches
    19.          switch (result.MatchCount)
    20.          {
    21.            case 3://3 matches
    22.               //GivePlayerShitReward();
    23.              break;
    24.            case 4://4 matches
    25.               //GivePlayerDecentReward();
    26.              break;
    27.            case 5://5 matches
    28.               //GivePlayerAmazingReward();
    29.              break;
    30.            default: break;
    31.          }
    32.        }
    33.      }
    34.    }
    35.  
    36.    //Returns winner results if you won, null if you lost
    37.    public static SlotWinnerResult CheckWinner(int pMinMatchesForWin, List<string> pRowSymbols)
    38.    {
    39.      const int MIN_MATCHES_FOR_WIN = 1;
    40.  
    41.      int minMatchesForWin = Mathf.Clamp(pMinMatchesForWin, MIN_MATCHES_FOR_WIN, pRowSymbols.Count);//safety
    42.      if (pRowSymbols == null || pRowSymbols.Count < minMatchesForWin)
    43.      {
    44.        throw new System.NullReferenceException("Row symbols are null or count is less than the minimum matches for a win.");
    45.      }
    46.    
    47.      int matchCount = 0;
    48.      int maxIterations = pRowSymbols.Count - minMatchesForWin + 1;
    49.      for (int matchStartIndex = 0; matchStartIndex < maxIterations; ++matchStartIndex)
    50.      {
    51.        for (matchCount = matchStartIndex + 1; matchCount < pRowSymbols.Count; ++matchCount)
    52.        {
    53.          if (pRowSymbols[matchStartIndex] != pRowSymbols[matchCount])
    54.          {
    55.            break;//no match
    56.          }
    57.        }
    58.        matchCount -= matchStartIndex;
    59.        if (matchCount >= minMatchesForWin)
    60.        {
    61.          return new SlotWinnerResult(matchStartIndex, matchCount);
    62.        }
    63.      }
    64.      return null;
    65.    }
    66. }
     
    Last edited: Jun 20, 2016
  15. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    If the given requirements in the first post are the only ones, you'll be fine with a much easier implementation, e.g. the one that @shaderop has already provided, except that I'd personally only have one array with the options and compare the generated indices with each other.
     
  16. magnurpai

    magnurpai

    Joined:
    Jun 19, 2016
    Posts:
    9
    Got the script running now, but It always returns "no match".
     
  17. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    What do you mean it returns "no match"?