I'm having some trouble iterating my array of booleans. The problem is that I have four positions that should activate my if condition but it only detects one. I think it's because I'm iterating through in a bad way. There is my code so you can understand my problem:
Declaration of arrays:
var columns = BooleanArray(Constants.WIDTH){ false }
var lines = BooleanArray(Constants.HEIGHT){false}
Here I'm only checking on which positions shall I enable the true state and as you can see, I'm iterating in deep into the matrix:
fun addNewIPiece(positionX:Int,positionY:Int){
val matrixPositionX = positionX/Constants.WIDTH_BLOCK
val matrixPositionY = positionY/Constants.HEIGHT_BLOCK
columns[matrixPositionX] = true
for(i in 0..4){
lines[matrixPositionY+i] = true
}
}
Here I'm iterating through both columns and lines and drawing some blocks but somewhat, I'm only getting one coincidence(check below the code):
fun drawMap(monoBlock: MonoBlock,canvas: Canvas){
for(columnsList in columns ){
for (linesList in lines){
if (columnsList and linesList) {
Log.d("CoincidenceX",columns.indexOf(columnsList).toString())
Log.d("CoincidenceY",lines.indexOf(linesList).toString()) monoBlock.draw(canvas,columns.indexOf(columnsList),lines.indexOf(linesList))
}
}
}
}
And here is the debug:
D/CoincidenceY: 87
D/CoincidenceX: 20
D/CoincidenceY: 87
D/CoincidenceX: 20
D/CoincidenceY: 87 ...........
So anyone can figure out where my mistake come from? I think its in the way that I iterate but I'm not sure.
Thanks in advance, ask if you have any question.
The data type of the variables columnsList and linesList (totally inappropriate names) is Boolean which is a primitive data type and they have values true or false. So when you use indexOf() it returns the index of the first item that matches the value of columnsList or linesList and not the index of the item you are currently iterating.
Since you are interested in the indexes, use an indexed loop :
for (i in columns.indices) {
for (j in lines.indices) {
if (columns[i] && lines[j]) {
Log.d("CoincidenceX", i.toString())
Log.d("CoincidenceY", j.toString())
}
}
}
Related
Func to see if two arrays have some same values:
func hasAllSame(largeCombinedArry:[Int], wantToKeep: [Int])->Bool{
var howManySame = [Int]()
for intElement in largeCombinedArry{
if wantToKeep.contains(intElement){
howManySame.append(intElement)
}
}
howManySame.sort()
if wantToKeep == howManySame{
print("These are the same!")
return true
}
else{
print("These are NOT same!")
return false
}
}
Array of tuples declared like this:
var TuplesArry:[(score: Double, value: [Int])] = []
Array filled thusly:
for (arry1, score) in zip(arryOfArrays, AllScores) {
let calculatedDiff = otherValue - score
TuplesArry.append((score: calculatedDiff, value: arry1))
}
var arrayForComparison = [8,9,7,6]
arrayForComparison.sort()
Error occurs here after several iteration at function call hasAllSame()
for i in 0..<TuplesArry.count{
if hasAllSame(largeCombinedArry: TuplesArry[i].value, wantToKeep:
arrayForComparison){
//do nothing
}
else{
/*
want to remove tuple that does not have all elements that are
in arrayForComparison
*/
TuplesArry.remove(at: i)
}
}
This code seems to be working but it seems like tuplesArry.count continues to decrease and iterator i continues to increase until error occurs "fatal index out of range"
My goal is to remove a tuple from the array of tuples if it's value does not meet criteria.
I've also tried something like:
for tuple in TuplesArry{
if hasAllSame(largeCombinedArry: tuple.value, wantToKeep:
arrayForComparison){
//do nothing
}
else{
//this does NOT work
let index = TuplesArry.index(of:tuple)
TuplesArry.remove(at: index)
}
}
The immediate issue is that you need to iterate in reverse to avoid the "index out of range" issue.
The much simpler solution is to use filter on your array. Then you entire for loop can be replaced with:
TouplesArry = TouplesArry.filter { hasAllSame(largeCombinedArry: $0.value, wantToKeep: arrayForComparison) }
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.
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.
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 {
}
}
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.
I'm making a simple game in swift and xcode and I ran into this problem that I can't figure out. Because I have so many levels, the code locks up indexing and slows down the whole program. I get a color wheel spinning for a few minutes but it never crashes. Just takes several minutes everytime I type in a few characters. Strange, but xcode has always had it's bugs right?
Each Button ("button1, button2..." below) gets a single number from "level1:Array". It's like a code that fills in the button's value for the game. There are only 4 buttons, but the numbers should be able to change as they each have their own variables.
I want to generate this for every level. I should be able to generate something like "button1 = level#[0]" where # is replaced by "userLevel". Changing to a string and doing something like "button1 = ("level(userLevel)") as! Array... doesn't seem to work. Look below and use my terminology when giving examples if you can. Thanks!
Here's the example:
let level1:Array = [9,7,4,1] // current puzzle, to go directly into button vars below (button1,button2,ect)
var userLevel = 1 // current user's level
if userLevel == 1 {
print("making Level 1, setting buttons to value from array")
button1 = level1[0]
button2 = level1[1]
button3 = level1[2]
button4 = level1[3]
}
Now, since level# is repeated so often (for each level as the number progresses) I would rather just make it something like this:
//this doesn't work in swift, but what else can I do?
if userLevel > 0 {
button1 = level\(userLevel)[0]
button2 = level\(userLevel)[1]
button3 = level\(userLevel)[2]
button4 = level\(userLevel)[3]
}
Is there an easy way to do this? Thanks!
-GG
Try using a for-in loop. Create an array of the buttons, and then
var index = 0
for button in buttons {
button = level1[index]
index++
}
EDIT since you want both the user level and the level number to increase, I suggest you define the levels like this. (Make sure that the number of buttons is equal to the number of userLevels, otherwise you will have problems)
var array = [1,2,3]
let levels = [1:[1,3,8],2:[3,6,4],3:[4,2,5]]
var index = 0
if array.count == levels.count {
for number in array {
array[index] = levels[index+1]![index]//The second index can be 0 if you want
index++
}
}
//array = [1,6,5]
// You could create a second index to match the number of levels within the main user level.
In this case, assume array to be your array of buttons
EDIT 2 :)
I've made a function that will allow you to assign all the levels to your array for a specific userLevel, since I see that is what you want
let levels = [1:[1,3,8],2:[3,6,4],3:[4,2,5]]
func assignValuesToArray(levelNo:Int) -> [Int] {
var array: [Int] = []
if (levelNo > 0) && (levelNo <= levels.count) {
for (level,levelArray) in levels {
if level == levelNo {
for value in levelArray {
array.append(value)
}
}
}
return array
} else {
print("This Level number does not exist")
return []
}
}
var finalArray = assignValuesToArray(2)
print(finalArray) // Returns [3,6,4]
As you can see from this example, you will return your array of buttons from the function, and you can assign the returned array values to whatever you like.
my test array has multiple objects in them that I want to iterate over and if a condition is not met I want to pop it from main array.
I am using foreach loop. so
so I am using a foreach loop and doing
$.foreach(test, function(idx, val){
if(true){
test.splice(idx, 1);
}
});
problem is that it doesn’t work as if there are two objects for example, as shown below, it will reindex the array after the first iteration and then the second iteration which will be idx 1, will not be able to do
test.spice(1,1) since index 1 does not exist in the array anymore.
Now I know that I can create a temporary place holder and the indexes there and then run another foreach but thats what I am trying to avoid. Any ideas will be appreciated
[
email: “testemail#emailcom”
firstName: “Test"
]
[
email: “testemail2#emailcom”
firstName: “Test"
]
If you want to remove elements from an array, I recommend you to use filter function
test = test.filter(function(val, idx) {
if(true) { // a condition about val
return false; // return false to EXCLUDE
} else {
return true; // return false to INCLUDE
}
});
Just iterate through the array backwards. Then, removing elements from the array only affects the indices of elements that the loop has already dealt with:
for (var idx = test.length-1; idx>=0; idx--){
if(true){
test.splice(idx, 1);
}
}
I want to Loop through the array of integers and want to remove the items in the TLToProcess list which i have stored in the array of integers
here is the code
I want to remove only the selected in the list integer
iSize.add(TLToProcess.size());
if(TLToProcess[i].Scan_In1__c==null)
{
if(TLToProcess[i].typew__c=='Pending')
{
TLForMissingHHhh.add(TLToProcess[i]);
}
}
else if ( c[i].Scan_In1__c!=null)
{
if (TLToProcess[i].typew__c=='Pending' )
{
TLToProcess[i].typew__c='Processed';
}
}
}
Now i want to remove record 1 by 1 from TLToProcess using
remove() can any body tell me how to do it.
Thanks
Anu
Not sure I understand your problem, but if what you're trying to avoid is modifying your List of integers inside a loop and getting this error: {"Collection was modified; enumeration operation may not execute."} you can create a copy of your List(.ToList()) and use it to iterate, and this way you can call Remove() safely.
List<Int32> arr = new List<Int32>();
for (int i = 0; i < 10; i++)
{
arr.Add(i);
}
foreach(var o in arr.ToList())
{
arr.Remove(o);
}
Is that the intent?