how to wait Recursion until the function finish executing - swift

I have one Recursion func that executes the actions and on it's last cycle it checks for a condition, and if the condition is true it calls another similar function that Also runs actions. But while second func is executing actions through recursion the first func starts executing. So have two actions now running simultaneously. I Read about GCD and tried it but didn't get results as expected.(Actually I still don't understand how to use it properly)
First main Func movePiece()
Here's my code it's all in the same class :
func movePiece() {
// some Func Calls here.
if ( self.movesRemaining > 0) {
DispatchQueue.global(qos: .userInteractive).async {
self.moveFinished = false
let currentSpace:Int = self.returnPlayerSpace(player: self.whosTurn)
let spaceNumber:Int = currentSpace
var nextSpace:Int = spaceNumber + 1
let moveAction:SKAction = SKAction.move(to: (self.childNode(withName: String(nextSpace))?.position)!, duration: 0.4)
moveAction.timingMode = .easeOut
let wait:SKAction = SKAction.wait(forDuration: 0.2)
let runAction:SKAction = SKAction.run({
if (self.movesRemaining == 1) {
self.KillHim(player:self.whosTurn, nextspace:nextSpace)
DispatchQueue.main.async {
self.moveBackPiece()
}
}
self.setThePlayerSpace(space: nextSpace, player:self.whosTurn)
if (self.movesRemaining == 1) {
self.Adjust(node: self.childNode(withName: String(nextSpace))!)
}
self.movesRemaining = self.movesRemaining - 1
self.movePiece()
})
if self.whosTurn == .Player1 {
self.touchedNode.run(SKAction.sequence([moveAction, wait, runAction]))
} else {
self.playerPiece.run(SKAction.sequence( [moveAction, wait, runAction]))
}
}
}
}
Here is second func moveBackPiece() :
func moveBackPiece() {
if ((killedPiece == self.Player1Piece1 || killedPiece == self.Player1Piece2 || killedPiece == self.Player1Piece3 || killedPiece == self.Player1Piece4) && self.movesRemainingBack != 1) || ((killedPiece == self.Player2Piece1 || killedPiece == self.Player2Piece2 || killedPiece == self.Player2Piece3 || killedPiece == self.Player2Piece4) && self.movesRemainingBack != 5) || ((killedPiece == self.Player3Piece1 || killedPiece == self.Player3Piece2 || killedPiece == self.Player3Piece3 || killedPiece == self.Player3Piece4) && self.movesRemainingBack != 9) || ((killedPiece == self.Player4Piece1 || killedPiece == self.Player4Piece2 || killedPiece == self.Player4Piece3 || killedPiece == self.Player4Piece4) && self.movesRemainingBack != 13) {
self.movesRemainingBack -= 1
let moveAction:SKAction = SKAction.move(to: (self.childNode(withName: String(self.movesRemainingBack))?.position)!, duration: 0.4)
moveAction.timingMode = .easeOut
let runAction:SKAction = SKAction.run({
if ((self.killedPiece == self.Player1Piece1 || self.killedPiece == self.Player1Piece2 || self.killedPiece == self.Player1Piece3 || self.killedPiece == self.Player1Piece4) && self.movesRemainingBack == 1) || ((self.killedPiece == self.Player2Piece1 || self.killedPiece == self.Player2Piece2 || self.killedPiece == self.Player2Piece3 || self.killedPiece == self.Player2Piece4) && self.movesRemainingBack == 5) || ((self.killedPiece == self.Player3Piece1 || self.killedPiece == self.Player3Piece2 || self.killedPiece == self.Player3Piece3 || self.killedPiece == self.Player3Piece4) && self.movesRemainingBack == 9) || ((self.killedPiece == self.Player4Piece1 || self.killedPiece == self.Player4Piece2 || self.killedPiece == self.Player4Piece3 || self.killedPiece == self.Player4Piece4) && self.movesRemainingBack == 13) {
self.setThePlayerSpaceBack(space: self.movesRemainingBack, Killed: self.killedPiece)
}
self.movesRemaining = self.movesRemaining - 1
self.moveBackPiece()
})
self.killedPiece.run(SKAction.sequence([moveAction, runAction]))
}
}
how can I solve it with GCD Or something else?
Thanks for your Time.

You have to use GCD group queues. It will work with async operations also. It's like Go In -> Go Out, Go In ->Go Out, At the end it will notify you , Here is the example
let queue = DispatchQueue(label: "com.your.text", attributes: .concurrent)
let group = DispatchGroup()
group.enter()
queue.async {
print("1st Operation")
Thread.sleep(forTimeInterval: 10)
print("1st Operatio finished")
group.leave()
}
group.enter()
queue.async {
print("2nd Operation")
Thread.sleep(forTimeInterval: 10)
print("2nd Operation finished")
group.leave()
}
group.notify(queue: .main) {
print("Finished")
}
It's quickly written here, so might be syntax error will come. I hope it helps you out on your issue.

Related

Fixing Tic-Tac-Toe Code Error.. Doesn't Run Due to DeclareWinner function bein written later. How can I correct it?

The entire code for my Tic Tac Toe game has been pasted below. It doesn't run due to an error in the Declare Winner function being added after its use. How do I correct this?
Do I simply create it earlier?
Use of local variable 'DeclareWinner' before its declaration. This is what it says. What am I supposed to do?
import UIKit
class GameViewController: UIViewController {
#IBOutlet weak var MainTitle: UILabel!
#IBOutlet weak var Player1Label: UILabel!
#IBOutlet weak var Player2Label: UILabel!
#IBOutlet weak var PlayerTurnLabel: UILabel!
#IBOutlet weak var GameONLabel: UILabel!
var matrix: [[Int]] = [[0,0,0],[0,0,0],[0,0,0]] // 0 - Nothing, 1 - X, 2 - O
var WhosTurn = 0 // 1- Player1, 2- Player2
var Player1 = 0 // 0 - Nothing, 1 - X, 2 - O
var Player2 = 0 // 0 - Nothing, 1 - X, 2 - O
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
StartGame()
}
func StartGame(){
matrix = [[0,0,0],[0,0,0],[0,0,0]] // 0 - Nothing, 1 - X, 2 - O
displayMat(matrix: matrix)
WhosTurn = Int.random(in: 1...2)
if (WhosTurn == 1){ // Player1's Turn and He's X
Player1 = 1
Player2 = 2
Player1Label.text = "Player 1: X"
Player2Label.text = "Player 2: O"
PlayerTurnLabel.text = "Turn: Player 1"
}else {// Player2's Turn and He'll be O
Player1 = 2
Player2 = 1
Player1Label.text = "Player 1: O"
Player2Label.text = "Player 2: X"
PlayerTurnLabel.text = "Turn: Player 2"
}
}
func displayMat(matrix: [[Int]]) {
var TempTag = 1
for i in 0...2 {
for j in 0...2 {
if (matrix[i][j] == 0 ) {
let TempButton = self.view.viewWithTag(TempTag) as? UIButton
TempButton?.setBackgroundImage(nil, for: .normal)
} else if (matrix[i][j] == 1) { //Display X
let TempButton = self.view.viewWithTag(TempTag) as? UIButton
TempButton?.setBackgroundImage(UIImage(named: "X"), for: .normal)
}else if (matrix[i][j] == 2) { //Display O
let TempButton = self.view.viewWithTag(TempTag) as? UIButton
TempButton?.setBackgroundImage(UIImage(named: "O"), for: .normal)
}else {
}
TempTag += 1
}
}
}
#IBAction func ButtonClickedXorO(_ sender: Any) {
var TempObject = 0
if (WhosTurn == 1){ // Player1's Turn and He's X
TempObject = Player1
Player1 = 1
Player2 = 2
Player1Label.text = "Player 1: X"
Player2Label.text = "Player 2: O"
PlayerTurnLabel.text = "Turn: Player 1"
}else {// Player2's Turn and He'll be O
TempObject = Player2
PlayerTurnLabel.text = "Turn: Player 2"
}
guard let button = sender as? UIButton else {
return
}
switch button.tag {
case 1:
if (matrix[0][0] == 0) {
matrix[0][0] = TempObject
JustPlayed()
}
case 2:
if (matrix[0][1] == 0) {
matrix[0][1] = TempObject
JustPlayed()
}
case 3:
if (matrix[0][2] == 0) {
matrix[0][2] = TempObject
JustPlayed()
}
case 4:
if (matrix[1][0] == 0) {
matrix[1][0] = TempObject
JustPlayed()
}
case 5:
if (matrix[1][1] == 0) {
matrix[1][1] = TempObject
JustPlayed()
}
case 6:
if (matrix[1][2] == 0) {
matrix[1][2] = TempObject
JustPlayed()
}
case 7:
if (matrix[2][0] == 0) {
matrix[2][0] = TempObject
JustPlayed()
}
case 8:
if (matrix[2][1] == 0) {
matrix[2][1] = TempObject
JustPlayed()
}
case 9:
if (matrix[2][2] == 0) {
matrix[2][2] = TempObject
JustPlayed()
}
default:
print("Error")
}
}
func JustPlayed(){
displayMat(matrix: matrix)
Winner()
if (WhosTurn == 1) {
WhosTurn = 2
PlayerTurnLabel.text = "Turn: Player 2"
}else {
WhosTurn = 1
PlayerTurnLabel.text = "Turn: Player 1"
}
}
func Winner(){
var Counter = true
if ((matrix[0][0] == matrix[1][1] && matrix[1][1] == matrix[2][2] && matrix[1][1] != 0))
DeclareWinner(WhoWon: matrix[1][1])
}else if ((matrix[2][0] == matrix[1][1] && matrix[1][1] == matrix[0][2] && matrix[1][1] != 0)) {
DeclareWinner(WhoWon: matrix[1][1])
}else {
for i in 0...2{
if (matrix[i][0] == matrix[i][1] && matrix[i][1] == matrix[i][2] && matrix[i][0] != 0){
DeclareWinner(WhoWon: matrix[i][0])
Counter = false
}
}
if Counter{
for i in 0...2{
if (matrix[0][i] == matrix[1][i] && matrix[1][i] == matrix[2][i] && matrix[0][i] != 0){
DeclareWinner(WhoWon: matrix[0][i])
}
}
}
}
func DeclareWinner(WhoWon: Int){
if (WhoWon == Player1) {
// Player1 Won
GameONLabel.text = "Player 1 Won!"
}else if (WhoWon == Player2){
//Player2 Won
GameONLabel.text = "Player 2 Won!"
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
#IBAction func GoBack(_ sender: Any) {
dismiss(animated: true, completion:nil)
}
}

Random results in if-statements

I have this code that gives the wrong result. The combination EE and Aa sometimes gives "black" if I press Aa after selecting EE... Other times it gives the correct result. Any tips?
This is my code:
//genotype
var ext = "ee"
var ago = "aa"
var gre = "gg"
func checkPicture() {
//Base coat regular
if ext == "EE" || ext == "Ee" && ago == "aa" {
baseLayer.image = #imageLiteral(resourceName: "black")
base = String("black")
}
if ago == "Aa" || ago == "AA" && ext == "EE" || ext == "Ee" {
baseLayer.image = #imageLiteral(resourceName: "bay")
base = String("bay")
}
if ext == "ee" {
baseLayer.image = #imageLiteral(resourceName: "chestnut")
base = String("chestnut")
}
//buttons
#IBAction func `extension`(_ sender: UIButton) {
ext = String(sender.titleLabel!.text ?? "ee")
genotype.text = checkGenotype()
eeno.isSelected = false
eema.isSelected = false
eeye.isSelected = false
sender.isSelected = true
checkPicture()
}
#IBAction func agouti(_ sender: UIButton) {
ago = String(sender.titleLabel!.text ?? "aa")
genotype.text = checkGenotype()
aano.isSelected = false
aama.isSelected = false
aaye.isSelected = false
sender.isSelected = true
}
#IBAction func grey(_ sender: UIButton) {
gre = String(sender.titleLabel!.text ?? "gg")
genotype.text = checkGenotype()
ggno.isSelected = false
ggma.isSelected = false
ggye.isSelected = false
sender.isSelected = true
}
It's Simple your condition's are bit confusing
func checkPicture() {
//Base coat regular
if (ext == "EE" || ext == "Ee") && ago == "aa" { // added bracket
baseLayer.image = #imageLiteral(resourceName: "black")
base = String("black")
}
if (ago == "Aa" || ago == "AA") && (ext == "EE" || ext == "Ee") {
baseLayer.image = #imageLiteral(resourceName: "bay")
base = String("bay")
}
if ext == "ee" {
baseLayer.image = #imageLiteral(resourceName: "chestnut")
base = String("chestnut")
}
}
This should resolve your problem. you forgot to add bracket at required places.

Anyobject is not a subtype of NSLayoutConstraint

I am upgrading to Swift3, below code was working fine in Swift 2.3 but it is not working with Swift 3
let constraints: NSArray = contentView.constraints as NSArray
let indexOfConstraint = constraints.indexOfObject (passingTest: { (constraint, idx, stop) in
return ((constraint as AnyObject).firstItem as! UIView).tag == bubbleTag && (constraint.firstAttribute == NSLayoutAttribute.left || constraint.firstAttribute == NSLayoutAttribute.right)
})
I am getting following compiler error:
'(AnyObject)' is not a subtype of 'NSLayoutConstraint'
How can I fix this?
I think you might need something like this...
contentView.constraints.index(where: { constraint in
guard let firstItemView = constraint.firstItem as? UIView else {
return false
}
return firstItemView.tag == bubbleTag && (constraint.firstAttribute == .left || constraint.firstAttribute == .right)
})

Expression resolves to an unused function Only instance methods can be declared #IBAction

I'm following a youtube series and I've done exactly as the guy in the film but still i get errors please help. (:
if you know the answer please help.
#IBAction func resetClicked(sender:UIButton) {
func reset() {
}
plays = [:]
img1.image = nil
img2.image = nil
img3.image = nil
img4.image = nil
img5.image = nil
img6.image = nil
img7.image = nil
img8.image = nil
img9.image = nil
}
}
func checkForWin() {
var whoWon = ["I":0,"you":1]
for (key,value) in whoWon {
if((plays[7] == value && plays[8] == value && plays[9] == value))
(plays[4] == value && plays[5] == value && plays[6] == value)
(plays[1] == value && plays[2] == value && plays[3] == value)
(plays[1] == value && plays[4] == value && plays[7] == value)
(plays[2] == value && plays[5] == value && plays[8] == value)
(plays[1] == value && plays[5] == value && plays[9] == value)
(plays[3] == value && plays[5] == value && plays[7] == value)) {
self.userMessage.hidden = false
self.userMessage.text = "Looks like \(key) won"
self.reset.hidden = false
self.done = true
}
}
}
func aiDeciding2() {
}
func aiTurn() {
}
You can't declare a function inside of an IBAction. Your error is the
func reset() {
}
Also make sure your IBAction is inside your view controller code

One ViewController with two segues triggered by an If statement

I am trying to have two segues which are triggered by If statements. Here is the coding I have so far.
func prepareForSegue(segue: UIStoryboardSegue, AnyObject?) {
if segue.identifier == "SomeoneWon" {
var ThirdVC: WinnerViewController = segue.destinationViewController as! WinnerViewController
ThirdVC.WinnerName = Winner}
else if segue.identifier == "PopUp" {
var PopUpVC: PopUpViewController = segue.destinationViewController as! PopUpViewController
PopUpVC.RoundWinnerPop = RoundWinner}
The If statements are as follows:
if firstrandomnumber > secondrandomnumber && firstrandomnumber > thirdrandomnumber && firstrandomnumber > fourthrandomnumber {
Player1ScoreTotal += 1
self.Player1Score.text = String(Player1ScoreTotal)
Winner = receivedString1
RoundWinner = receivedString1
if Player1ScoreTotal == 5{
performSegueWithIdentifier("SomeoneWon", sender: UIButton())}
else {
performSegueWithIdentifier("PopUp", sender: UIButton()) }}
else if secondrandomnumber > firstrandomnumber && secondrandomnumber > thirdrandomnumber && secondrandomnumber > fourthrandomnumber {
Player2ScoreTotal += 1
self.Player2Score.text = String(Player2ScoreTotal)
Winner = receivedString2
RoundWinner = receivedString2
if Player2ScoreTotal == 5{
performSegueWithIdentifier("SomeoneWon", sender: UIButton())}
else {
performSegueWithIdentifier("PopUp", sender: UIButton())}}
else if thirdrandomnumber > firstrandomnumber && thirdrandomnumber > secondrandomnumber && thirdrandomnumber > fourthrandomnumber {
Player3ScoreTotal += 1
self.Player3Score.text = String(Player3ScoreTotal)
Winner = receivedString3
RoundWinner = receivedString3
if Player3ScoreTotal == 5{
performSegueWithIdentifier("SomeoneWon", sender: UIButton())}
else{
performSegueWithIdentifier("PopUp", sender: UIButton())}}
else if fourthrandomnumber > firstrandomnumber && fourthrandomnumber > secondrandomnumber && fourthrandomnumber > thirdrandomnumber {
Player4ScoreTotal += 1
self.Player4Score.text = String(Player4ScoreTotal)
Winner = receivedString4
RoundWinner = receivedString4
if Player4ScoreTotal == 5{
performSegueWithIdentifier("SomeoneWon", sender: UIButton())
}
else{
performSegueWithIdentifier("PopUp", sender: UIButton())}}
}
The segue works but the information for the variables does not get transferred i.e. the label which is suppose to show the values for "Winner" and "RoundWinner" remain blank. I am new so I hope the mistake is simple. Thanks.