Retrieve Best Score Game Center Swift - swift

I'm in trouble, I can't fix a bug related to the func for retrieve the best score from the Game Center. The function is working good if you have a score but it's crashing if the user doesn't have score.
Any suggestions? Code below:
func retrieveBestScore() {
if GKLocalPlayer.localPlayer().isAuthenticated {
// Initialize the leaderboard for the current local player
var gkLeaderboard = GKLeaderboard(players: [GKLocalPlayer.localPlayer()])
gkLeaderboard.identifier = leaderboardID
gkLeaderboard.timeScope = GKLeaderboardTimeScope.allTime
// Load the scores
gkLeaderboard.loadScores(completionHandler: { (scores, error) -> Void in
// Get current score
var currentScore: Int64 = 0
if error == nil {
if (scores?.count)! > 0 {
currentScore = (scores![0] ).value
//We also want to show the best score of the user on the main screen
if self.language.contains("it"){
self.labelBestScore.text = "Miglior Punteggio: " + String(currentScore)
self.bestScore = Int(currentScore)
}else{
self.labelBestScore.text = "Your Best Score: " + String(currentScore)
self.bestScore = Int(currentScore)
}
print("Punteggio attuale",currentScore)
}
}
})
}
}
Thank you!

Based on your code it looks like you may be encountering this issue due to force unwrapping your 'scores' array.
Try something like this in your closure:
var currentScore: Int64 = 0
if error == nil, let scores = scores {
if scores.count > 0 {
currentScore = scores[0].value
//We also want to show the best score of the user on the main screen
if self.language.contains("it"){
self.labelBestScore.text = "Miglior Punteggio: " + String(currentScore)
self.bestScore = Int(currentScore)
}else{
self.labelBestScore.text = "Your Best Score: " + String(currentScore)
self.bestScore = Int(currentScore)
}
print("Punteggio attuale",currentScore)
}
}
Here's a secondary approach that condenses your code even more, I think this should work as well but it's hard to say for sure without seeing more code, it might need a couple minor changes possibly.
guard error == nil, let scores = scores, let currentScore = scores.first?.value else {
print("GameCenter error or no scores: \(String(describing: error)))")
return
}
//We also want to show the best score of the user on the main screen
if self.language.contains("it"){
self.labelBestScore.text = "Miglior Punteggio: " + String(currentScore)
self.bestScore = Int(currentScore)
}else{
self.labelBestScore.text = "Your Best Score: " + String(currentScore)
self.bestScore = Int(currentScore)
}
print("Punteggio attuale",currentScore)

Related

when i append a value the whole array is changing to the appended value

I append in the for loop but for some reason instead of appending at the end it changes all the existing values in the array.
let a = 2
class people {
var name = " "
var height = Int()
}
var trial = " "
var p = [people]()
var user = people()
for i in 0...a-1{
if(i==0){
user.name = "jack"
user.height = 180
}
else {
user.name = "ryan"
user.height = 120
}
p.append(user)
print(p[i].name, p[i].height);
}
for i in 0...a-1 {
print(p[i].name, p[i].height);
}
expectd: -
jack 180
ryan 120
jack 180
ryan 120
result:-
jack 180
ryan 120
ryan 120
ryan 120
You create only one instance of people and add this instance in your array for two times. but the problem is when you assign the value for the second time it replaces the previous value of the same instance.
You have to create new instnse of people inside your for loop for every new user. like below
let a = 2
class people {
var name = " "
var height = Int()
}
var trial = " "
var p = [people]()
//var user = people() remove this line from here and add inside for-loop
for i in 0...a-1{
var user = people() // add this line here.
if(i==0){
user.name = "jack"
user.height = 180
}
else {
user.name = "ryan"
user.height = 120
}
p.append(user)
print(p[i].name, p[i].height);
}
for i in 0...a-1 {
print(p[i].name, p[i].height);
}

Main thread messes up sorting

Dispatching the queue messes up the order in the array as noted below. I'm trying to rank the array and then be able to translate it. So far its not working:
let top5 = Array(labels.sorted{ $0.confidence > $1.confidence}.prefix(upTo:5))
for lulu in top5 {
let translator = ROGoogleTranslate()
var params = ROGoogleTranslateParams()
params.source = "en"
params.target = "es"
params.text = "\(String(describing: lulu.label))"
translator.translate(params: params, callback: { (result) in
DispatchQueue.main.async {
self.textUno.text = self.textUno.text! + "\(lulu.label)" + " \(lulu.confidence*100)\n"
self.textDos.text = self.textDos.text! + "\(result)\n"
self.view.addSubview(self.textUno)
self.view.addSubview(self.textDos)
}
})
}
If I try to put the sorting out of DispatchQueue.main.async then the translation won't be lined up with the right word.
How can I fix this so that the array is sorted and the translation matches up ?
Translate the array first before ranking them.
Make it simpler first and make sure it is working and then put all the parts together.
If you really want to do it this way you will need to put them into a temporary array after sorting them and then use that at the end.
This, as you said, will return a jumbled result.
The below example is pretty close, needs a bit of a polish but you should be able to do it from this.
let top5 = Array(labels.sorted{ $0.confidence > $1.confidence}.prefix(upTo:5))
var tmparr : []
var count: Int = 0
for lulu in top5 {
let translator = ROGoogleTranslate()
count = count + 1
var params = ROGoogleTranslateParams()
params.source = "en"
params.target = "es"
params.text = "\(String(describing: lulu.label))"
params.ordernumber = count
translator.translate(params: params, callback: { (result) in
tmparr.append[params]
})
}
DispatchQueue.main.async {
for lulunew in tmparr {
if (lulunew.ordernumber == correctindex){
self.textUno.text = self.textUno.text! + "\(lulu.label)" + " \(lulu.confidence*100)\n"
self.textDos.text = self.textDos.text! + "\(result)\n"
self.view.addSubview(self.textUno)
self.view.addSubview(self.textDos)
}
}
}

Loops for Dictionary key items

How can I fix the code so the loop would ask the question for each of the items in the dictionary?
*Edited the code to make what I am trying to do more clear. I want the code to stop and wait for the input BEFORE moving on to the next item in the dictionary.
import Foundation
import UIKit
var squad = [1:"Arsh", 2:"Arbab", 3:"Ayush", 4:"KC", 5:"Jaski", 6:"Gunny", 7:"Harsh", 8:"Nagib", 9:"Rithin", 10:"Gursh", 11:"Sonny"]
let coming = "Yes"
let notComing = "No"
var attendees = [String]()
for ( key , person) in squad {
// key == 1
// key = counter
// repeat {
print("Are you attending \(person)?")
let response = readLine()
print(response as Any)
if response == coming {
attendees.append(person)
}
else if response == notComing {
print("Sorry to hear that")
}
else {
print("Invalid Input")
}
// } while key <= 11
// key += 1
}
print(attendees)
print(attendees.count)
To experiment keyboard input features like readLine(), create a project by choosing from Xcode menu :
File > New > Project > macOS > Command Line Tool
and run it in Xcode, the Debugging Console pane will work as a terminal. Here the code you're looking for :
import Foundation
var squad = [1:"Arsh", 2:"Arbab", 3:"Ayush", 4:"KC", 5:"Jaski", 6:"Gunny", 7:"Harsh", 8:"Nagib", 9:"Rithin", 10:"Gursh", 11:"Sonny"]
let coming = "yes"
let notComing = "no"
var attendees = [String]()
let array = squad.map {return ($0.key, $0.value)} // Turn the dictionary to an array of tuples
let sortedArray = array.sorted(by: {$0.0 < $1.0 }) // Sort the array by the first element of the tuple
// Ask the squad one by one
for ( _ , person) in sortedArray {
print("Are you attending \(person)?")
if let response = readLine() {
//remove white spaces and all letters lowercased so that "Yes", "yes" and "YES" would all be accepted
if response.lowercased().trimmingCharacters(in: .whitespaces) == coming {
attendees.append(person)
}
else if response.lowercased().trimmingCharacters(in: .whitespaces) == notComing {
print("Sorry to hear that")
}
else {
print("Invalid Input")
}
}
}
print("attendees : \(attendees)")
print("attendees.count = \(attendees.count)")

"Attemped to add a SKNode which already has a parent:" in Repeat Loop. Any simple work around?

I am pretty Newbie to programming. And I am trying to pile up the random blocks dynamically till it hits the upper frame. But it seems that Swift doesn't let me to do so. Did I miss anything please? Any input are appreciated.
let blocks =[block1,block2,block3,block4,block5,block6,block7,block8,block9,block10,block11,block12]
var block:SKSpriteNode!
let blockX:Double = 0.0
var blockY:Double = -(self.size.height/2)
repeat{
block = blocks.randomBlock()
block.zPosition = 2
block.position = CGPoint(x:blockX, y:blockY)
block.size.height = 50
block.size.width = 50
self.addChild(block)
blockY += 50
} while( block.position.y < self.size.height)
extension Array {
func randomBlock()-> Element {
let randint = Int(arc4random_uniform(UInt32(self.count)))
return self[randint]
}
}
you need to have someway of tracking which blocks have been selected and ensure that they don't get selected again. The method below uses an array to store the indexes of selected blocks and then uses recursion to find a cycle through until an unused match is found.
private var usedBlocks = [Int]()
func randomBlock() -> Int {
guard usedBlocks.count != blocks.count else { return -1 }
let random = Int(arc4random_uniform(UInt32(blocks.count)))
if usedBlocks.contains(random) {
return randomBlock()
}
usedBlocks.append(random)
return random
}
in your loop change your initializer to
let index = randomBlock()
if index > -1 {
block = blocks[index]
block.zPosition = 2
block.position = CGPoint(x:blockX, y:blockY)
}
remember that if you restart the game or start a new level, etc. you must clear all of the objects from usedBlocks
usedBlocks.removeAll()

Issue with checking new integer against previous one

Im attempting to make something similar to the high low game. So far i can get a new integer between 1-25 to be generated.
Ive tried to write a function that when you press the 'lower' button it checks the new integer against the previous one, and if it is less then text is displayed below saying 'You Were Correct' and updates the users score +1.. and if wrong 'You Were Wrong' displays instead and score is reset to 0.
Whenever i press the lower button it gives me a new int but score is not updated and the message doesn't display. This is my first real attempt at making this so bear with me :)
Lower Button
#IBAction func lower(sender: AnyObject) {
var newNumber = randomIntBetween(2, high: 26)
var oldNumber: Int?
func lowerNumber() -> Int {
if newNumber <= oldNumber {
correctWrong.text = "You Were Correct!"
score.text = "Score: \(countWin++)"
} else {
correctWrong.text = "You Were Wrong!"
score.text = "Score: \(countLose)"
}
return newNumber
}
randomNumbers.text = "\(newNumber)"
}
Random Number Function
func randomIntBetween(low:Int, high:Int) -> Int {
let range = high - (low - 1)
return (Int(arc4random()) % range) + (low - 1)
}
Variables/Constants Used
var countWin = 0
let countLose = 0
Thanks
As far I can see if your code it's formatted correctly you have a nested function but you aren't calling it inside your function so it's impossible that the function lowerNumber() will be called. You need to call the function like the following code:
#IBAction func lower(sender: AnyObject) {
var newNumber = randomIntBetween(2, high: 26)
var oldNumber: Int?
func lowerNumber() -> Int {
if newNumber <= oldNumber {
correctWrong.text = "You Were Correct!"
score.text = "Score: \(countWin++)"
} else {
correctWrong.text = "You Were Wrong!"
score.text = "Score: \(countLose)"
}
return newNumber
}
let newValue = lowerNumber()
randomNumbers.text = "\(newValue)"
}
Nevertheless, nested functions are closures that have a name and can capture values from their enclosing function so you need to be carefully with its use. I recommend this article of #AirSpeedVelocity to learn more about the closures and its capture values A Basic Tutorial on Functions and Closures in Swift
I hope this help you.