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)
}
}
Everything appears to be working in this tic tac toe game, except for displaying the "draw" label when there is no winner. The label will switch when Cross or circles wins, but not when there is a tie.
I'm stumped. E
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var count = 1
var activePlayer = 1 //Cross
var gameState = [0,0,0,0,0,0,0,0,0]
var gameIsActive = true
let winningCombinations = [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6]]
#IBAction func action(_ sender: AnyObject) {
if (gameState[sender.tag-1] == 0 && gameIsActive == true) {
gameState[sender.tag-1] = activePlayer
if (activePlayer == 1) {
sender.setImage(UIImage(named: "cross.png"), for: UIControl.State())
activePlayer = 2
} else {
sender.setImage(UIImage(named: "nought.png"), for: UIControl.State())
activePlayer = 1
}
}
for combination in winningCombinations {
if gameState[combination[0]] != 0 &&
gameState[combination[0]] == gameState[combination[1]] &&
gameState[combination[1]] == gameState[combination[2]] {
gameIsActive = false
if gameState[combination[0]] == 1 {
label.text = "Cross has won!"
} else {
label.text = "Circle has won!"
}
if gameIsActive == true {
for i in gameState {
count = i*count
}
if count != 0 {
label.text = "It was a draw."
label.isHidden = false
playAgainButton.isHidden = false
}
}
playAgainButton.isHidden = false
label.isHidden = false
}
}
} // End Button Action
#IBOutlet weak var playAgainButton: UIButton!
#IBAction func playAgain(_ sender: Any) {
gameState = [0,0,0,0,0,0,0,0,0]
gameIsActive = true
activePlayer = 1
playAgainButton.isHidden = true
label.isHidden = true
for i in 1...9 {
let button = view.viewWithTag(i) as! UIButton
button.setImage(nil, for: UIControl.State())
}
}
override func viewDidLoad() {
super.viewDidLoad()
playAgainButton.isHidden = true
label.isHidden = true
}
} // End ViewController
You are saying
gameIsActive = false
// ... some other stuff ...
if gameIsActive == true {
// check for a draw
}
But gameIsActive is not true, because you just set it to false. Therefore we never perform the check for a draw.
Thanks for the help everyone! I finally got it working correctly.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var playAgainButton: UIButton!
#IBOutlet weak var label: UILabel!
var count = 1
var activePlayer = 1 //Cross
var gameState = [0,0,0,0,0,0,0,0,0]
var gameIsActive = true
let winningCombinations = [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6]]
#IBAction func action(_ sender: AnyObject) {
count = 1;
if (gameState[sender.tag-1] == 0 && gameIsActive == true) {
if (activePlayer == 1) {
gameState[sender.tag-1] = activePlayer
sender.setImage(UIImage(named: "cross.png"), for: UIControl.State())
activePlayer = 2
} else {
sender.setImage(UIImage(named: "nought.png"), for: UIControl.State())
gameState[sender.tag-1] = activePlayer
activePlayer = 1
}
}
for combination in winningCombinations {
if gameState[combination[0]] != 0 && gameState[combination[0]] ==
gameState[combination[1]] && gameState[combination[1]] ==
gameState[combination[2]]{
gameIsActive = false
if gameState[combination[0]] == 1 {
label.text = "Cross has won!"
} else {
label.text = "Circle has won!"
}
playAgainButton.isHidden = false
label.isHidden = false
}
}
if gameIsActive == true{
for i in gameState{
count = i * count
}
if count != 0{
label.text = "DRAW!"
playAgainButton.isHidden = false
label.isHidden = false
}
}
}
#IBAction func playAgain(_ sender: Any) {
gameState = [0,0,0,0,0,0,0,0,0]
gameIsActive = true
activePlayer = 1
playAgainButton.isHidden = true
label.isHidden = true
for i in 1...9
{
let button = view.viewWithTag(i) as! UIButton
button.setImage(nil, for: UIControl.State())
}
}
override func viewDidLoad() {
super.viewDidLoad()
playAgainButton.isHidden = true
label.isHidden = true
}
}
I'm making a binary calculator app.
No buildtime issues but in the app only adding binary numbers give the right answer, multiplying, subtracting and dividing don't.
Dividing - every answer = 1 (1010-0001 = 1; 10101010-1010 = 1)
Multiplying - every answer is wrong, (11111 x 101010 = 1111000001, should be 10100010110)
Subtracting - every answer = 0 ( 1010-0001 = 0; 1010101-0001 = 0)
I tried making the code more explanatory and it worked in the playground (ending with print() ) but when I changed the apps code, the answers were the same.
var numberOnScreen:Int = 0;
var previousNumber:Int = 0;
var doingMath = false
var operation = 0;
var decimal = 0;
var decimal1 = 0;
var binary:String = ""
var binary1:String = ""
#IBOutlet weak var label: UILabel!
#IBAction func Numbers(_ sender: UIButton) {
if doingMath == true
{
label.text = String(sender.tag-1)
numberOnScreen = Int(label.text!)!
doingMath = false
}
else
{
label.text = label.text! + String(sender.tag-1)
numberOnScreen = Int(label.text!)!
}
}
#IBAction func buttons(_ sender: UIButton) {
if label.text != "" && sender.tag != 6 && sender.tag != 8
{
previousNumber = Int(label.text!)!
binary = "\(previousNumber)"
decimal = Int(binary, radix: 2)!
binary1 = "\(numberOnScreen)"
decimal1 = Int(binary1, radix: 2)!
operation = sender.tag
doingMath = true;
}
else if sender.tag == 8
{
if operation == 3 //adding
{
label.text = String((decimal + decimal1), radix: 2)
}
else if operation == 4 //subtracting
{
label.text = String((decimal - decimal1), radix: 2)
}
else if operation == 5 //multiplying
{
label.text = String((decimal * decimal1), radix: 2)
}
else if operation == 7 //dividing
{
label.text = String((decimal / decimal1), radix: 2)
}
I built an binary calculator app, For the numbers I have two variables. previousNumber and numberOnScreen. The idea is to convert the binary numbers to decimals, do the calculation and convert the answer back.
Lets say the first (previousNumber)number I pick is 1010 and the second (numberOnScreen) 10100
var numberOnScreen:Int = 0;
var previousNumber:Int = 0;
var doingMath = false
var operation = 0;
var decimal = 0;
var decimal1 = 0;
var binary:String = ""
var binary1:String = ""
#IBOutlet weak var label: UILabel!
#IBAction func Numbers(_ sender: UIButton) {
if doingMath == true
{
label.text = String(sender.tag-1)
numberOnScreen = Int(label.text!)!
doingMath = false
}
else
{
label.text = label.text! + String(sender.tag-1)
numberOnScreen = Int(label.text!)!
}
}
#IBAction func buttons(_ sender: UIButton) {
if label.text != "" && sender.tag != 6 && sender.tag != 8
{
previousNumber = Int(label.text!)!
binary = "\(previousNumber)"
decimal = Int(binary, radix: 2)!
binary1 = "\(numberOnScreen)"
decimal1 = Int(binary1, radix: 2)!
operation = sender.tag
doingMath = true;
}
else if sender.tag == 8
{
if operation == 3 //adding
{
print(previousNumber, numberOnScreen, decimal, decimal1)
It prints [ 1010, 10100, 10, 10 }
Any ideas why this is happening?
When you hit the = key, you need to update the calculation of decimal1. Move that code to the place where you are processing =:
#IBAction func buttons(_ sender: UIButton) {
if label.text != "" && sender.tag != 6 && sender.tag != 8
{
previousNumber = Int(label.text!)!
binary = "\(previousNumber)"
decimal = Int(binary, radix: 2)!
operation = sender.tag
doingMath = true;
}
else if sender.tag == 8
{
binary1 = "\(numberOnScreen)"
decimal1 = Int(binary1, radix: 2)!
if operation == 3 //adding
{
print(previousNumber, numberOnScreen, decimal, decimal1)
Also, I recommend that you get rid of the magic numbers in your code and replace them with constants. For your key tags, you could define a struct like this:
struct Key {
static let clear = 6
static let equals = 8
static let plus = 3
}
and then your code would read:
if label.text != "" && sender.tag != Key.clear && sender.tag != Key.equals {
which is much clearer.
i have quiz app and have 10 sec timer each question. First question timer is fine, but in second question it going faster than before. I try this tutorial to make timer and this tutorial to make quiz app
here's my code :
override func viewDidLoad() {
timerBegin()
}
func timerBegin() {
myTimer.invalidate() // print error `fatal error: unexpectedly found nil while unwrapping an Optional value`
timeLeft = 10
myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(SoalViewController.timerRunning), userInfo: nil, repeats: true)
}
func timerRunning() {
timeLeft -= 1
timeLabel.text = "\(timeLeft)"
if timeLeft == 0 {
myTimer.invalidate()
timeLabel.text = "10"
pickQuestion()
timerBegin()
}
}
here's my option button code :
#IBAction func opsiA(_ sender: Any) {
timeLabel.text = "10"
timerBegin()
if AnswerNumber == 0 {
pickQuestion()
Score += 10
scoreLabel.text = "\(Score)"
} else {
pickQuestion()
print("Wrong")
}
}
#IBAction func opsiB(_ sender: Any) {
timeLabel.text = "10"
timerBegin()
if AnswerNumber == 1 {
pickQuestion()
Score += 10
scoreLabel.text = "\(Score)"
} else {
pickQuestion()
print("Wrong")
}
}
#IBAction func opsiC(_ sender: Any) {
timeLabel.text = "10"
timerBegin()
if AnswerNumber == 2 {
pickQuestion()
Score += 10
scoreLabel.text = "\(Score)"
} else {
pickQuestion()
print("Wrong")
}
}
#IBAction func opsiD(_ sender: Any) {
timeLabel.text = "10"
timerBegin()
if AnswerNumber == 3 {
pickQuestion()
Score += 10
scoreLabel.text = "\(Score)"
} else {
pickQuestion()
print("Wrong")
}
}
and this is my pick question function :
func pickQuestion() {
if Questions.count > 10 {
QNumber = Int(arc4random_uniform(UInt32(10)))
textView.text = Questions[QNumber].Question
AnswerNumber = Questions[QNumber].Answer
for i in 0..<Buttons.count {
Buttons[i].setTitle(Questions[QNumber].Answers[i], for: UIControlState.normal)
}
Questions.remove(at: QNumber)
} else {
darkView.isHidden = false
scoreLabel.text = "\(Score)"
timeLabel.isHidden = true
if Score > standStill {
HighScore = Score
highScoreLabel.text = NSString(format: "Highscore : %i", HighScore) as String
let currentHighScore = UserDefaults.standard
currentHighScore.set(HighScore, forKey: "HighScore")
} else {
let currentHighScore = UserDefaults.standard
currentHighScore.set(standStill, forKey: "HighScore")
}
}
}
i already try to stop timer by adding myTimer.invalidate() in first line of timerBegin function but it print fatal error: unexpectedly found nil while unwrapping an Optional value