Swift: Random number arrays inside images and variables with a for loop - ios

I am creating a game in which, depending on the number of 'swipes' chosen to do, (let's say 3), 3 different patterns show on the screen, one by one. I am working on developing the first pattern.
So I have this:
if (swipes.no_of_swipes) == 3 {
swipeArray = Array<UInt32>(count: 3, repeatedValue: 0)
for i in 0 ..< 3 {
swipeArray[i] = arc4random_uniform(84)}
}
As far as I am aware, this code creates an array with three UInts which can be accessed by doing swipeArray[0], swipeArray[1], and swipeArray[2]. My first question is how long will this swipeArray stay the same? Until the close the view? Should I have a 'refresh button' when the user loses - and if so, how would I make one?
Then I have a property observer. You will notice the for loop, which I am using to keep code concise. I understand that I could do something like x++ somewhere in here so that it will go through each one.
var playBegin: Bool = false{
didSet {
if playBegin == true {
println("\(playBegin)")
var swipes = Menu()
if (swipes.no_of_swipes) == 3 {
for i in 0 ..< 3 {
patternRoom.image = UIImage(named: "pattern\(swipeArray[x])")
//rest of code
}
}
}
The pattern image comes from a set of 84 images named like pattern7 and pattern56. My second question is, how could I code the for loop to go through each swipeArray[x].
Thank you in advance,
Will

how long will this swipeArray stay the same?
This is a bit too open ended. It’ll stay the same until you assign a new value to it, either from this same bit of code or a different part. Only you can know when that will be, by looking at your code.
Since you express an interest in keeping the code concise, here’s a couple of code tips.
You might think about writing your first snippet’s loop like this:
swipeArray = (0..<swipes.no_of_swipes).map { _ in
arc4random_uniform(84)
}
This combines creating a new array and populating the values. By the way, just in case you don’t realize, there’s no guarantee this array won’t contain the same value twice.
It’s also probably better to make swipeArray of type [Int] rather than [UInt32], and to convert the result of arc4random to an Int straight away:
Int(arc4random_uniform(84))
Otherwise the UInt32s will probably be a pain to work with.
For your second for loop, you can do this:
for i in swipeArray {
patternRoom.image = UIImage(named: "pattern\(i)")
// rest of code
}
When writing Swift, usually (but not always), when you find yourself using array[x] there’s a better more expressive way of doing it.

Related

Return/break out of infinite foreach in kotlin

For class I have to make a program that calculates the birthday problem
Now I'm having trying to learn kotlin at the same time and I'm having trouble with a little snippet of code:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
outForeach#
sum += checkSet.size
As you can see I'm trying to do this with an infinite sequence. Kotlin doesn't accept this as outForeach is an unresolved reference. But this doesn't work either:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#forEach
}
}
sum += checkSet.size
This will just start the forEach loop again. Is there a way to implement something as a forEachUntil or so?
p.s. I'm aware that this looks a lot like this question: 'return' doesn't jump out of forEach in Kotlin It's just that I don't really get the answers and I don't know if its applicable here. Also a way to implement forEachUntil seems for me to be far more elegant
Alternatives you may want to consider instead of first:
using a simple while without body:
while (checkSet.add(Random.nextInt(n))); // <- that semicolon is required! otherwise you execute what is coming next within the while
using run with a label:
run outForeach#{
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
}
maybe also takeWhile might be helpful. In this specific case however it is surely not (as it would check against the checkSet and leave us with a sequence that isn't consumed... but if the condition would be different, it may make sense to consider something like take, takeWhile, takeLast, etc.):
generateSequence { Random.nextInt(n) }
.takeWhile(checkSet::add) // as said: for this specific condition it doesn't make sense...
.forEach { /* do nothing except consume the sequence */ } // the same values you added to the set would be available in this step of course
I think I found the solution myself:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.first { !checkSet.add(it) }
sum += checkSet.size
Basically use the function first() and keep returning false until you want to get out of the loop. And just drop the return of the function first()

Is boolean or nil comparison faster?

I am writing a code in Swift where I have a class as follows:
class Note
{
var isDeleted:Bool = false
var deletedDateTime:Date!
}
Suppose there is a data source that is filled with Notes and I want to make a filter based on comparison, then I can either compare by isDeleted or I can compare by deletedDateTime. Which one would be faster from the following two statements:
var dataSource:[Note] = [Note]()
// fill the datasource with objects
dataSource.filter({$0.isDeleted == false}) // 1
dataSource.filter({$0.deletedDateTime == nil}) //2
Can anyone please guide me?
There won't be much of a time difference, if you are talking about the execution time. But your class seem to be a bit obvious since you could remove the unnecessary boolean variable because as you have asked the both mean the same.

Iterate through an optional array in Swift?

I'm using the cocoapod SQLite for this project like so
import SQLite
var db = try! Connection()
var id: Expression<Int>!
var identifier: Expression<String>!
With it I am reading a list of moves from a SQLite database.
Every monster has a moves that they can learn. Some monsters can learn more moves than others.
var monster: Monster!
var monArray = [Monster]()
var dataSource: DataSource!
To get the monsters move ID I use this code. This allows me to grab the first move in the array. Changing the 0 would get me the second, third move ect.
monster.moves![0]["move_id"] as! Int
Now I'm using the SQLite database because I need to match monster ID values in my plist with the ones in the SQLite database. I use this code to do so
override func viewWillAppear(_ animated: Bool) {
let movesArray = Array(try! db.prepare(Table("moves").where(identifier == moves.name!.lowercased())))
for user in movesArray {
monArray = dataSource.mons.filter{ $0.moves![0]["move_id"] as! Int == user[id] }
}
}
Everything works fine until I try to increase the index range.
for user in movesArray {
for i in 0...6 {
monArray = dataSource.mons.filter{ $0.moves![i]["move_id"] as! Int == user[id] }
}
}
See where I replace the 0 with the range i? I do that because since monsters have more than one move, if I leave it at 0 my app will only display the monsters that learn that move as their first move. To better explain, my current code does not look through whether the monster knows the move, it only looks through whether the monsters knows the move as its first move.
In the above code I increase the range thinking it would solve my issue, but my app will crash because some monsters only have 1 move in their index, so anything above index 0 will crash with the error
fatal error: Index out of range
So to recap, I need to iterate through the entire array instead of just the first index, without it crashing. How can I achieve this?
Without all the story arround your just asking how to iterate over an array like here
for item in array as type {
...
}
Your question seems to be more of a logical question. If I'm understanding what you have said, then each monster will have a minimum of 1 move, but not guaranteed to have more. So you would need to account for this.
Having a fixed limit like you do will certainly cause problems if not all monsters have that many moves as the array will not always be that size.
I would do something like:
let monsterMoveCount = user.moves.count
for i in 0...monsterMoveCount
// Do whatever logic here
Hopefully this helps!

How to reduce NSTimeInterval every time the score is increased by 5

I have a variable called duration which is a NSTimeInterval(3). 3 is the number of objects on the screen and the new object begin to fall when the last is at the bottom of the screen. I want this number reduce, because it will fall faster when there will be less objects. I want it reduce every time the score is increased by 5 from last reduce. But if I write there this code it does nothing:
if ((self.score % 5) == 0) {
self.duration--
}
How can I do it?
Thanks
I guess the "Swifty" answer would be something like this:
var score:Int {
didSet {
self.duration--
}
}
That said you haven't really given enough info to say why self.duration-- would not work, so I'm assuming that code just isn't being called.

how do i declare variables, compare them and then use them inside a function

i am developing an ea that requires me to compare the high of previous 2 bars and whichever one is higher, use that as a stop loss value.
same for opposite side trades, i need to compare previous 2 lows and use the lower one as stop loss value.
what i am doing is this:-
void onTick()
{
static int ticket=0;
double ab=(//calculation for ab);
double de=(//calculation for de);
if(Low[1]<Low[2])
double sll=Low[1];
if(Low[1]>Low[2])
double sll=Low[2];
if(buy logic comes here)
{
double entryPrice=////////;
double stoploss=sll-xyz;
double takeprofit=entryPrice+((entryPrice-stoploss)*3);
ticket = OrderSend(Symbol(),...entryPrice,stoploss,takeprofit,.....);
}
if(ticket == false)
{
Alert("Order Sending Failed");
}
}
the problem is i am not able to reference the values of sll and get an error message saying "sll undeclared identifier"
i am fairly new to programming and would appreciate if someone can help me out with this.
I have added most of the code for you to understand the logic.
you would have to declare them outside the scope of the if statements if you want to use variables anywhere else so instead of doing that take a look at this
double sll; // declare sll outside the if statements
if(Low[1]<Low[2])
sll=Low[1];
if(Low[1]>Low[2])
sll=Low[2];
if(buy logic comes here)
{
bool res = OrderSend(..........);
}
Judging by what you wrote, it looks like you may be using res somewhere else too which then you need to define outside of the if statement because scoping.

Resources