Хорошо, наша игра идет хорошо, и вот фото, подтверждающее это.

Если вы только что наткнулись на эту статью, вам нужно сначала прочитать эти, чтобы попасть сюда.

Naked Networking с SwiftUI
Больше Naked Networking, больше SwiftUI
Naked Networking и SwiftUI, план игры
Naked Networking и SwiftUI, геймификация
Naked Networking и SwiftUI, геймификация II

Теперь нам нужно следить за счетом. Мы могли бы сделать две простые метки, с названиями выигранных игр и проигранных игр, но не лучше ли иметь более наглядный индикатор. Давайте поставим в строке o или x, чтобы указать, сколько игр вы сыграли, сколько выиграли и сколько проиграли. Мы будем играть по 7 игр за раунд.

Как только раунд закончится, нам понадобится средство для сброса настроек, чтобы мы могли начать все сначала. Но ладно, забегаю вперед.

SwiftUI

Основные изменения в ContentView.swift. Нам нужен горизонтальный StackView и список индикаторов, чтобы сказать, выиграли ли мы [o] или проиграли [an x].

@State var game = 1
@State var game1 = ""
@State var game2 = ""
@State var game3 = ""
@State var game4 = ""
@State var game5 = ""
@State var game6 = ""
@State var game7 = ""
HStack {
Text(game1)
Text(game2)
Text(game3)
Text(game4)
Text(game5)
Text(game6)
Text(game7)
}

Здесь нам нужно использовать переменные @State, потому что мы будем изменять значения в ContentView.swift во время игры.

Я попытался создать их массив, как в UIKit, но, похоже, на данный момент он не поддерживается в SwiftUI, поэтому я пошел на компромисс и создал функцию для установки каждой из игр в правильное состояние во время игры.

func winWin(game: Int, leader: String) {
switch self.game {
case 1:
self.game1 = leader
case 2:
self.game2 = leader
case 3:
self.game3 = leader
case 4:
self.game4 = leader
case 5:
self.game5 = leader
case 6:
self.game6 = leader
case 7:
self.game7 = leader
default:
break
}
self.game = self.game + 1
}

Каждый раз, когда вы его вызываете, он устанавливает следующую игру в серии. Очевидно, вам нужно вызвать эту функцию на обоих клиентах. Поэтому мы добавляем его в раздел «Вы проиграли» и «Вы выиграли». Я собираюсь вставить весь блок кода, чтобы вы могли перепроверить, что у вас есть все, что мы сделали до сих пор.

...
.onReceive(pingPublisher) { ( data ) in
print("data ",data)
self.hit = false
self.disable = false
self.volley = ""
var countDown = Float(data)
if countDown! > 4 {
countDown = 4
}
self.youLose = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { timer in
countDown = countDown! - 0.1
self.timeToDie = String(countDown!)
if countDown! < 0.0 && !self.disable {
self.disable = true
self.youLose?.invalidate()
self.volley = "You Lose"
self.globalVariable.score = "lose"
self.winWin(game: self.game,leader: "x")
if self.model.state {
makeConnect(port: "1984", message: "win")
} else {
makeConnect(port: "4891", message: "win")
}
}
})
}
...

И для победителя.

... 
.onReceive(winPublisher, perform: {
self.hit = false
self.volley = "You Win"
self.disable = false
self.winWin(game: self.game,leader: "o")
self.globalVariable.score = ""
})
...

Добавьте разделы, скомпилируйте и вперед. Это должно работать с единственным возвратом, ничего не происходит, когда вы подходите к концу раунда, и вы не можете сбросить его. Нам нужно больше. Чувствую, как эти маленькие проекты становятся все больше и больше.

Объявить, кто выиграет, а кто проиграет, мы можем сделать в функции winWin. Добавьте этот код в конец. Новый код выделен полужирным курсивом.

@State var remoteWin = 0
@State var localWin = 0
@State var localLose = 0
@State var remoteLose = 0
@State var newGame = false
....
self.game = self.game + 1
if leader == "o" && !self.model.state {
remoteWin = remoteWin + 1
}
if leader == "o" && self.model.state {
localWin = localWin + 1
}
if leader == "x" && !self.model.state {
remoteLose = remoteLose + 1
}
if leader == "x" && self.model.state {
localLose = localLose + 1
}
if game == 7 {
newGame = true
if self.model.state {
self.volley = "game over yang wins " + " " + String(localWin) + " ying wins " + String(localLose)
} else {
self.volley = "game over ying wins " + " " + String(remoteWin) + " yang wins " + String(remoteLose)
}
}

Но подождите, нам нужен сброс. Нам нужен другой протокол. Давайте ненадолго вернемся к сети и добавим ее.

Сеть

let gamePublisher = PassthroughSubject<Void, Never>()

Нам также нужно изменить нашу функцию приема, теперь у нее есть три разных случая, с которыми нужно иметь дело.

DispatchQueue.main.async {
globalVariable.score = backToString
if backToString == "ping" || backToString == "pong" {
pingPublisher.send(string2Send)
}
if backToString == "win" {
winPublisher.send()
}
if backToString == "game" {
gamePublisher.send()
}
}

Я мог бы использовать оператор case здесь, если я в конечном итоге добавлю что-то еще, я это сделаю. Вернемся к SwiftUI.

SwiftUI

Итак, нам нужна еще одна кнопка. Добавьте его под HStack, который вы только что установили.

@State var newGame = false
...
Button(action: {
self.reset()
self.disable = false
self.remoteWin = 0
self.localWin = 0
self.volley = ""
self.newGame = false
self.game = 1
self.timeToDie = ""
self.globalVariable.score = ""
if self.model.state {
makeConnect(port: "1984", message: "game")
} else {
makeConnect(port: "4891", message: "game")
}
}) {
Text("new game").disabled(newGame ? false: true)
}.onReceive(gamePublisher) { (_) in
self.reset()
self.disable = false
self.remoteWin = 0
self.localWin = 0
self.volley = ""
self.newGame = false
self.game = 1
self.timeToDie = ""
self.globalVariable.score = ""
}

Признаюсь, это немного монструозного кода. Примечательный момент в нем, тот факт, что мы отключаем или активируем кнопку на значении переменной newGame. Я украл этот кусок кода в предыдущем разделе, пока вы не смотрели. Вы же не хотите сбрасывать сериал посреди этого, не так ли?

Хорошо, если у вас все на месте, и я ничего не упустил, вы сможете сыграть одну или две игры даже в несколько раундов.

Давайте остановимся на минутку, подведем итоги и посмотрим, что, как мы сказали, мы могли бы сделать помимо этого. Мы говорили о большем количестве кнопок, мы говорили об анимации. Но когда я перешел к седьмой статье в этой серии, я только что понял, что мы оставили там этот противный жестко закодированный IP-адрес. Нам нужно это исправить. Это должно быть предметом статьи семь.