0

I'm using SpriteKit and Swift 3 to create a simple game. I have an array of Rings/Circles:

mRings = [mRingOne, mRingTwo, mRingThree, mRingFour, mRingFive]

each object in the array has a different color, In some point in the game I want to change the color of each ring, but I have 2 condition for this to happen: 1. a ring should not have the color it had one iteration before. 2. each ring should be in a different color from the others.

for the first condition I did this:

func changeRingsColor(){
    var previousColor: UIColor?
    for ring in mRings {
        previousColor = ring.fillColor
        repeat{
            ring.fillColor = hexStringToUIColor(hex: mColors[Int(arc4random_uniform(UInt32(5)))])
        }while(ring.fillColor.isEqual(previousColor))
    }
}

and it is working, however, I couldn't figure out a way to answer the second condition. In Java I would probably do something like this:

    for (int i=0; i<mRings.length; i++){
      for( int j=1; j<mRings.length; j++){
        if (ring[i].fillColor == ring[j].fillColor){
            generate another color for 'j' ring.
        }
    }
 }

but nothing I tried worked. Hope you guys can help me, Thanks in advance!

btw, mColors is an array of 5 different colors, from there I pick the colors.

swiftnewbie
  • 201
  • 3
  • 12
  • What you might be looking for is a "random derangement", i.e. a random permutation which changes every element. – Martin R Jan 13 '17 at 13:11
  • The simplest algorithm is to generate a random order of elements and then pass the colors to the next element in that order. – Sulthan Jan 13 '17 at 13:25

3 Answers3

1

I'm going to ignore some of the implementation details and focus on the core of the question, which is:

  • Loop through an array
  • Within each loop, start a new loop at the current index to the end of the array.

Let me know if I'm misunderstanding the above. But I would do it like this:

for (index, ring) in mRings.enumerated() {
    let remainingRings = mRings[index+1..<mRings.count]
    for otherRing in remainingRings {
        print("Now comparing \(ring) to \(otherRing)")
    }
}

First, enumerated() gives you both the current ring, and the index, on each iteration of the first for loop. Then, we slice the array from the current index to the end (remainingRings), and loop through those.

Connor Neville
  • 7,291
  • 4
  • 28
  • 44
0

It is possible to rewrite Java code in this way :

let mRings = ["mRingOne", "mRingTwo", "mRingThree", "mRingFour", "mRingFive"]

for (index, item) in mRings.enumerated() {
    for item in index + 1..<mRings.count {

    }
}
Oleg Gordiichuk
  • 15,240
  • 7
  • 60
  • 100
0

Something like this will work:

func changeRingsColor(){
    // extract the previous colors
    let colors = rings.map { $0.fillColor }
    // the order in which the rings will pass color to each other
    let passOrder = mRings.indices.shuffled()

    for i in mRings.indices {
        let previous = i == 0 ? mRings.count - 1 : i - 1        
        mRings[passOrder[i]].fillColor = colors[passOrder[previous]]
    }
}

Using this implementation of shuffled

How does it work?

Instead of randomly choosing a color for each individual ring, I am randomly generating an order in which the rings will swap the colors (passOrder). Since every ring will pass its color to a different ring in that order, you can be sure no color will stay the same.

Community
  • 1
  • 1
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • That is an interesting approach to get a random "derangement" (permutation without fixed point). However, it will not produce *all possible* derangements. For example, ABCD will never be permuted to BADC. (No criticism, just a remark.) – Martin R Jan 15 '17 at 09:31
  • @MartinR Very true, for 4 items there is exactly 1 permutation that is missed :) I wanted to illustrate the point that the algorithm shouldn't be done for every element separately. – Sulthan Jan 15 '17 at 09:57
  • All permutations with more than one cycle are missing, for 4 items that should be BADC, CDAB, DCBA unless I am mistaken. – But this is going off-topic now :) – Martin R Jan 15 '17 at 10:01
  • @MartinR Oh yes, I forgot that a cycle with 3 items is also possible if the last item is not identity. I will have to calculate if this algorithm does not remove too many options. – Sulthan Jan 15 '17 at 10:06