swift: how to remove randomly from 1 to 3 items? - swift

My code remove randomly only one coin. How i can remove randomly from 1 to 3 coins?
#IBAction func endTurn(sender: UIButton!) {
if coins.count > 0 { // #IBOutlet var coins: [UIButton]! (21 coins)
let index: Int = Int(arc4random_uniform(UInt32(coins.count)))
coins[index].hidden = true
self.coins.removeAtIndex(index)
if coins.isEmpty {
println("GameOver")
}
}
}

For randoms I recommend this extension:
extension Int {
static func random(range: Range<Int> ) -> Int {
var offset = 0
if range.startIndex < 0 {
offset = abs(range.startIndex)
}
let min = UInt32(range.startIndex + offset)
let max = UInt32(range.endIndex + offset)
return Int(min + arc4random_uniform(max - min)) - offset
}
}
And then:
var i = Int.random(1...5)

Try this
let numberToDelete = Int(arc4random_uniform(UInt32(3))) + 1
for i in 0..<numberToDelete{
let indexToDelete = Int(arc4random_uniform(UInt32(coins.count)))
coins.removeAtIndex(indexToDelete)
if coins.isEmpty{
break;
}
}
if coins.isEmpty{
println("GameOver")
}

Related

How do I make a custom completion handler?

How do I make a custom completion handler for the below function? This is writing to a websocket via Starscream and I want to receive a response if it isn't nil.
open func write(string: String, completion: (() -> ())? = nil) {
guard isConnected else { return }
dequeueWrite(string.data(using: String.Encoding.utf8)!, code: .textFrame, writeCompletion: completion)
}
and here is deqeueWrite func:
private func dequeueWrite(_ data: Data, code: OpCode, writeCompletion: (() -> ())? = nil) {
let operation = BlockOperation()
operation.addExecutionBlock { [weak self, weak operation] in
//stream isn't ready, let's wait
guard let s = self else { return }
guard let sOperation = operation else { return }
var offset = 2
var firstByte:UInt8 = s.FinMask | code.rawValue
var data = data
if [.textFrame, .binaryFrame].contains(code), let compressor = s.compressionState.compressor {
do {
data = try compressor.compress(data)
if s.compressionState.clientNoContextTakeover {
try compressor.reset()
}
firstByte |= s.RSV1Mask
} catch {
// TODO: report error? We can just send the uncompressed frame.
}
}
let dataLength = data.count
let frame = NSMutableData(capacity: dataLength + s.MaxFrameSize)
let buffer = UnsafeMutableRawPointer(frame!.mutableBytes).assumingMemoryBound(to: UInt8.self)
buffer[0] = firstByte
if dataLength < 126 {
buffer[1] = CUnsignedChar(dataLength)
} else if dataLength <= Int(UInt16.max) {
buffer[1] = 126
WebSocket.writeUint16(buffer, offset: offset, value: UInt16(dataLength))
offset += MemoryLayout<UInt16>.size
} else {
buffer[1] = 127
WebSocket.writeUint64(buffer, offset: offset, value: UInt64(dataLength))
offset += MemoryLayout<UInt64>.size
}
buffer[1] |= s.MaskMask
let maskKey = UnsafeMutablePointer<UInt8>(buffer + offset)
_ = SecRandomCopyBytes(kSecRandomDefault, Int(MemoryLayout<UInt32>.size), maskKey)
offset += MemoryLayout<UInt32>.size
for i in 0..<dataLength {
buffer[offset] = data[i] ^ maskKey[i % MemoryLayout<UInt32>.size]
offset += 1
}
var total = 0
while !sOperation.isCancelled {
let stream = s.stream
let writeBuffer = UnsafeRawPointer(frame!.bytes+total).assumingMemoryBound(to: UInt8.self)
let len = stream.write(data: Data(bytes: writeBuffer, count: offset-total))
if len <= 0 {
var error: Error?
let errCode = InternalErrorCode.outputStreamWriteError.rawValue
error = s.errorWithDetail("output stream error during write", code: errCode)
s.doDisconnect(error)
break
} else {
total += len
}
if total >= offset {
if let queue = self?.callbackQueue, let callback = writeCompletion {
queue.async {
callback()
}
}
break
}
}
}
writeQueue.addOperation(operation)
}
So right now I can call this function like this:
socket.write(string: frameJSONSring) { () -> Void in
}
But I'd like a response in that handler so that I can read the response data (if there is any) from the socket. Apparently I can pass a custom response handler as a parameter when calling:
socket.write(string: frameJSONSring) { (CUSTOM_HANDLER_HERE) -> Void in
}
open func write(string: String, completion: ((Int) -> ())?) {
guard isConnected else { return }
let someParameter = 5
dequeueWrite(string.data(using: String.Encoding.utf8)!, code: .textFrame, writeCompletion: completion(someParameter))
}
Notice I:
added an Int as a parameter you pass to the handler.
changed completion to completion(someParameter)
You can then use it like such:
socket.write(string: frameJSONSring) { number in
print(number)
}
You can replace the Int with any other type you like.
Also no need to do = nil. When something is an optional then it's already defaulted to nil.

CANT RESOLVE: unsafeAddressOf is abandoned in Swift 3

I just realized that my old app is not working anymore because unsafeAddressOf is abandoned in Swift 3. I have been searching in Apple documentations and online tutorials but still cant figure out how to change my code to be compliant with Swift 3. Here is my code:
import UIKit
import ImageIO
extension UIImage {
public class func gifWithData(data: NSData) -> UIImage? {
guard let source = CGImageSourceCreateWithData(data, nil) else {
print("SwiftGif: Source for the image does not exist")
return nil
}
return UIImage.animatedImageWithSource(source: source)
}
public class func gifWithName(name: String) -> UIImage? {
guard let bundleURL = Bundle.main.url(forResource: name, withExtension: "gif") else {
print("SwiftGif: This image named \"\(name)\" does not exist")
return nil
}
guard let imageData = NSData(contentsOfURL: bundleURL) else {
print("SwiftGif: Cannot turn image named \"\(name)\" into NSData")
return nil
}
return gifWithData(imageData)
}
class func delayForImageAtIndex(index: Int, source: CGImageSource!) -> Double {
var delay = 0.1
// Get dictionaries
let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)
let gifProperties: CFDictionary = unsafeBitCast(CFDictionaryGetValue(cfProperties, unsafeAddressOf(kCGImagePropertyGIFDictionary)), to: CFDictionary.self)
// Get delay time
var delayObject: AnyObject = unsafeBitCast(
CFDictionaryGetValue(gifProperties,
unsafeAddressOf(kCGImagePropertyGIFUnclampedDelayTime)),
to: AnyObject.self)
if delayObject.doubleValue == 0 {
delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties,
unsafeAddressOf(kCGImagePropertyGIFDelayTime)), to: AnyObject.self)
}
delay = delayObject as! Double
if delay < 0.1 {
delay = 0.1 // Make sure they're not too fast
}
return delay
}
class func gcdForPair( a: Int?, var _ b: Int?) -> Int {
// Check if one of them is nil
var a = a
if b == nil || a == nil {
if b != nil {
return b!
} else if a != nil {
return a!
} else {
return 0
}
}
// Swap for modulo
if a < b {
let c = a
a = b
b = c
}
// Get greatest common divisor
var rest: Int
while true {
rest = a! % b!
if rest == 0 {
return b! // Found it
} else {
a = b
b = rest
}
}
}
class func gcdForArray(array: Array<Int>) -> Int {
if array.isEmpty {
return 1
}
var gcd = array[0]
for val in array {
gcd = UIImage.gcdForPair(val, gcd)
}
return gcd
}
class func animatedImageWithSource(source: CGImageSource) -> UIImage? {
let count = CGImageSourceGetCount(source)
var images = [CGImage]()
var delays = [Int]()
// Fill arrays
for i in 0..<count {
// Add image
if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {
images.append(image)
}
// At it's delay in cs
let delaySeconds = UIImage.delayForImageAtIndex(index: Int(i),
source: source)
delays.append(Int(delaySeconds * 1000.0)) // Seconds to ms
}
// Calculate full duration
let duration: Int = {
var sum = 0
for val: Int in delays {
sum += val
}
return sum
}()
// Get frames
let gcd = gcdForArray(array: delays)
var frames = [UIImage]()
var frame: UIImage
var frameCount: Int
for i in 0..<count {
frame = UIImage(CGImage: images[Int(i)])
frameCount = Int(delays[Int(i)] / gcd)
for _ in 0..<frameCount {
frames.append(frame)
}
}
// Heyhey
let animation = UIImage.animatedImage(with: frames,
duration: Double(duration) / 1000.0)
return animation
}
}
Does anyone have an idea how I can fix this code?

Populating a generator. Is it possible?

I have a generator that generates a circle(SKShapeNode) every 2 seconds from the y-axis. (Moves up). I would like to know if it is possible to populate this generator uniformly(every x number of points.
Here is my code for said generator:
class CircleGen: SKShapeNode {
var circles = [WhiteCircles]()
var circleTracker = [WhiteCircles]()
var generationTimer: NSTimer!
var circ: WhiteCircles!
func generateCircles() {
for var i = 0; i < 4; i++ {
var scale: CGFloat
let rand = arc4random_uniform(10)
if rand == 0 {
scale = -15.0
} else {
scale = 15.0
}
let circle = WhiteCircles()
circle.position.x = lineGen.position.x
circle.physicsBody?.affectedByGravity = false
circle.position.y = 35
self.circles.append(circle)
circleTracker.append(circle)
foregroundNode.addChild(circle)
}
}
func startGeneratingEvery(seconds: NSTimeInterval) {
let callGenerateAction = SKAction.runBlock { () -> Void in
self.generateCircles()
}
let waitOneSecond = SKAction.waitForDuration(seconds)
let sequenceAction = SKAction.sequence([callGenerateAction, waitOneSecond])
let circleGenerateAction = SKAction.repeatActionForever(sequenceAction)
self.runAction(circleGenerateAction, withKey: "generateCircles")
}
}
Will post more code if necessary. Thank you in advance.

Swift - Operators + Variables

I'm not able to do with swift : String1 = - String2 + 2
Actually :
var SetupTimer = "123"
var currentTime = 0
In an other fonction i do this :
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
var itemSelected = food[row]
itemLabel.text = itemSelected
bb = itemSelected
}
SetupTimer = bb
And finally i want to do that :
var currentTime = - SetupTimer + 10
Can someone help me?
Thank you
EDIT :
func CountDown()
{
if let timerAsInt = SetupTimer.toInt()
{
var currentTime = -timerAsInt + 10
}
currentTime = currentTime + 1
self.lbltimer.text = (String(10 - currentTime))
}
I am using the same preconditions of the answer by Craig Otis.
So, if you have a String setupTimer that does represent an integer
let setupTimer = "123"
then you can write:
Swift 2.0
if let timerAsInt = Int(setupTimer) {
var currentTime = -timerAsInt + 10
}
Swift 1.2
if let timerAsInt = setupTimer.toInt() {
var currentTime = -timerAsInt + 10
}
Hope this helps.
Update
If you want to update your own currentTime variable this is the code
if let timerAsInt = setupTimer.toInt() {
currentTime = -timerAsInt + 10
}

How to exclude specific Integers from arc4random

I want to get a random number with arc4random_uniform() but excluding the numbers from an array like this
var numbersArray = [8,15,10,3,7]
var randomNumber = arc4random_uniform(20)
If the arc4random_uniform() gives me any number from the numbersArray I want it to get a new number that is not from the numbersArray
I tried this
func getRandomGroup() -> Int {
for numbers in numbersArray {
if numbers == randomNumber {
var randomNumber = arc4random_uniform(20)
}
}
return randomNumber
}
But it did not seemed to work
Swift 2.0
var numbersArray = [8,15,10,3,7]
var randomNumber : Int
repeat {
randomNumber = Int(arc4random_uniform(20))
} while numbersArray.contains(randomNumber)
print(randomNumber)
In Swift 1.x it is do while
you can try it:
swift 2.
var numbersArray = [8,15,10,3,7]
func getRandomInArray(arr: [Int]) -> Int{
let indexRandom = Int(arc4random() % UInt32(arr.count))
return arr[indexRandom]
}
getRandomInArray(numbersArray)
Another way to do it:
var numbersArray: [UInt32] = [8,15,10,3,7]
func getPseudoRandom() -> UInt32 {
let randomNumber = arc4random_uniform(20)
if numbersArray.contains(randomNumber) {
return getPseudoRandom()
}
return randomNumber
}
for _ in 0..<20 {
print(getPseudoRandom())
}