I have finished my game of Tic Tac Toe with MPC class and it all works great except for the handlePotentialTie function. Actually there are zero errors and crashes but the logic behaves oddly when the board is full. Without the handlePotentialTie function the game works perfectly. I added this function later on and it's towards the bottom. I have included my code and a screenshot of the behaviour. I'm totally new to programming and any help would be insanely appreciated. Thanks in advance.
Code:
//
// ViewController.swift
// Tic Tac Toe
import UIKit
import MultipeerConnectivity
class ViewController: UIViewController, MCBrowserViewControllerDelegate {
@IBOutlet var fields: [TTTImageView]!
var currentPlayer: String!
var appDelegate:AppDelegate!
var turn:String!
override func viewDidLoad() {
super.viewDidLoad()
appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
appDelegate.mpcHandler.setupPeerWithDisplayName(UIDevice.currentDevice().name)
appDelegate.mpcHandler.setupSession()
appDelegate.mpcHandler.advertiseSelf(true)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "peerChangedStateWithNotification:", name: "MPC_DidChangeStateNotification", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleReceivedDataWithNotification:", name: "MPC_DidReceiveDataNotification", object: nil)
setupField()
currentPlayer = "letterX"
turn = "yourTurn"
}
@IBAction func connectWithPlayer(sender: AnyObject) {
if appDelegate.mpcHandler.session != nil{
appDelegate.mpcHandler.setupBrowser()
appDelegate.mpcHandler.browser.delegate = self
self.presentViewController(appDelegate.mpcHandler.browser, animated: true, completion: nil)
}
}
func peerChangedStateWithNotification(notification:NSNotification){
let userInfo = NSDictionary(dictionary: notification.userInfo!)
let state = userInfo.objectForKey("state") as Int
if state != MCSessionState.Connecting.rawValue{
self.navigationItem.title = "Connected"
}
}
func handleReceivedDataWithNotification(notification:NSNotification){
let userInfo = notification.userInfo! as Dictionary
let receivedData:NSData = userInfo["data"] as NSData
let message = NSJSONSerialization.JSONObjectWithData(receivedData, options: NSJSONReadingOptions.AllowFragments, error: nil) as NSDictionary
let senderPeerId:MCPeerID = userInfo["peerID"] as MCPeerID
let senderDisplayName = senderPeerId.displayName
println(message)
if message.objectForKey("string")?.isEqualToString("New Game") == true{
turn = "yourTurn"
let alert = UIAlertController(title: "Tic Tac Toe", message: "\(senderDisplayName) has started a new game", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
self.resetField()
}))
self.presentViewController(alert, animated: true, completion: nil)
}else if message.objectForKey("turnString")?.isEqualToString("deviceA") == true{
turn = "deviceA"
var field:Int? = message.objectForKey("field")?.integerValue
var player:String? = message.objectForKey("player")as? String
if field != nil && player != nil{
fields[field!].player = player
fields[field!].setPlayer(player!)
if player == "letterX"{
currentPlayer = "letterO"
}else{
currentPlayer = "letterX"
}
checkResults()
}
}
}
func fieldTapped(recognizer:UITapGestureRecognizer){
let tappedField = recognizer.view as TTTImageView //
if turn == "deviceA" || turn == "yourTurn"{
tappedField.setPlayer(currentPlayer)
let messageDict = ["field":tappedField.tag, "player":currentPlayer, "turnString":"deviceA"]
let messageData = NSJSONSerialization.dataWithJSONObject(messageDict, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
let data = messageData
// do something with the returned data
var error: NSError?
appDelegate.mpcHandler.session.sendData(data, toPeers: appDelegate.mpcHandler.session.connectedPeers, withMode: MCSessionSendDataMode.Unreliable, error:&error)
if error != nil{
println("error:\(error?.localizedDescription)")
}
}
checkResults()
turn = "deviceB"
}
func setupField(){
for index in 0...fields.count - 1{
let gestureRecognizer = UITapGestureRecognizer(target: self, action: "fieldTapped:")
gestureRecognizer.numberOfTapsRequired = 1
fields[index].addGestureRecognizer(gestureRecognizer)
}
}
func resetField(){
for index in 0...fields.count - 1 {
fields[index].image = nil
fields[index].activated = false
fields[index].player = ""
}
currentPlayer = "letterX"
}
@IBAction func newGame(sender: AnyObject) {
resetField()
let messageDict = ["string":"New Game"]
let messageData = NSJSONSerialization.dataWithJSONObject(messageDict, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
var error:NSError?
appDelegate.mpcHandler.session.sendData(messageData, toPeers: appDelegate.mpcHandler.session.connectedPeers, withMode: MCSessionSendDataMode.Reliable, error: &error)
if error != nil{
println("error: \(error?.localizedDescription)")
}
}
func checkResults(){
var winner = ""
if fields[0].player == "letterX" && fields[1].player == "letterX" && fields[2].player == "letterX"{
winner = "letterX"
}else if fields[0].player == "letterO" && fields[1].player == "letterO" && fields[2].player == "letterO"{
winner = "letterO"
}else if fields[3].player == "letterX" && fields[4].player == "letterX" && fields[5].player == "letterX"{
winner = "letterX"
}else if fields[3].player == "letterO" && fields[4].player == "letterO" && fields[5].player == "letterO"{
winner = "letterO"
}else if fields[6].player == "letterX" && fields[7].player == "letterX" && fields[8].player == "letterX"{
winner = "letterX"
}else if fields[6].player == "letterO" && fields[7].player == "letterO" && fields[8].player == "letterO"{
winner = "letterO"
}else if fields[0].player == "letterX" && fields[3].player == "letterX" && fields[6].player == "letterX"{
winner = "letterX"
}else if fields[0].player == "letterO" && fields[3].player == "letterO" && fields[6].player == "letterO"{
winner = "letterO"
}else if fields[1].player == "letterX" && fields[4].player == "letterX" && fields[7].player == "letterX"{
winner = "letterX"
}else if fields[1].player == "letterO" && fields[4].player == "letterO" && fields[7].player == "letterO"{
winner = "letterO"
}else if fields[2].player == "letterX" && fields[5].player == "letterX" && fields[8].player == "letterX"{
winner = "letterX"
}else if fields[2].player == "letterO" && fields[5].player == "letterO" && fields[8].player == "letterO"{
winner = "letterO"
}else if fields[0].player == "letterX" && fields[4].player == "letterX" && fields[8].player == "letterX"{
winner = "letterX"
}else if fields[0].player == "letterO" && fields[4].player == "letterO" && fields[8].player == "letterO"{
winner = "letterO"
}else if fields[2].player == "letterX" && fields[4].player == "letterX" && fields[6].player == "letterX"{
winner = "letterX"
}else if fields[2].player == "letterO" && fields[4].player == "letterO" && fields[6].player == "letterO"{
winner = "letterO"
}
if winner != ""{
let alert = UIAlertController(title: "Tic Tac Toe", message: "The winner is \(winner)", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
self.resetField()
}))
self.presentViewController(alert, animated: true, completion: nil)
}
// This is the area I don't know how to code.
// Thanks for looking
//
//
func handlePotentialTie() -> Bool {
if contains(fields, { $0.player == "" }) {
// An empty field: the game isn't over.
return false
} else {
contains(fields, { $0.player != "" })
// No empty fields: the game is over and must be a tie.
// End game and announce the tie.
let alert = UIAlertController(title: "Tic Tac Toe", message: "Tie Game", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
self.resetField()
}))
self.presentViewController(alert, animated: true, completion: nil)
return true
}
}
}
func browserViewControllerDidFinish(browserViewController: MCBrowserViewController!) {
appDelegate.mpcHandler.browser.dismissViewControllerAnimated(true, completion: nil)
}
func browserViewControllerWasCancelled(browserViewController: MCBrowserViewController!) {
appDelegate.mpcHandler.browser.dismissViewControllerAnimated(true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Last edited: