上一篇我们实现了绘制棋盘格子以及棋子的功能,这一篇我们来实现黑白子交替落子和判断胜负。
落子
黑白子交替
//我们定义一个bool值,因为五子棋里总是黑子落地切换白子,白子落地切换黑子,所以每当执行完一次落子,就应该取反bool值
var isblackOrWhite: Bool = true
计算落子的point
//我们定义一个结构体,point代表当前子的横竖列坐标,isblackOrWhite代表当前子为黑子还是摆子
struct Piece {
let point: NSPoint
let isblackOrWhite: Bool
}
//我们在鼠标落下来捕捉当前鼠标点击区域
override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)
//获取鼠标在当前窗口的位置
let mousePoint = event.locationInWindow
print("x: \(mousePoint.x), y: \(mousePoint.y)")
//如果鼠标超出了我们固定的棋盘大小,则丢弃此次点击时间
if (mousePoint.x + 23) > 500 || (mousePoint.y + 23) > 500 {
return
}
//判断触摸的位置在棋盘的交叉点
var xPoint: Int
var yPoint: Int
//刚好获取列行点
xPoint = Int((mousePoint.x)/30)
yPoint = Int((mousePoint.y)/30)
if containsDuplicate(NSPoint(x: xPoint, y: yPoint)) { return }
//刷新棋盘,此时会出发draw方法,重绘棋盘
needsDisplay = true
}
功能
判断当前落点是否有相同棋子,并保存
//判断是否有相同坐标棋子并保存,相同坐标棋子则不做处理
private func containsDuplicate(_ point: NSPoint) -> Bool {
//判断是否有相同棋子
for p in points {
let x = p.point.x - point.x
let y = p.point.y - point.y
//判断相同点
if abs(x * x + y * y) < 0.00001 {
return true
}
}
}
//构建棋子结构体
struct Piece {
let point: NSPoint
let isblackOrWhite: Bool
}
//储存棋子数组
var points: Array<Piece> = []
//保存棋子
let piece = Piece.init(point: point, isblackOrWhite: isblackOrWhite)
points.append(piece)
return false
判断输赢
五子棋的输赢极好判断,上下左右及斜边满足五个相同类型棋子就可以获胜,如图所示:
分析
左右分析
右边来讲,棋子x+1,左边来讲棋子x-1。
上下分析
上边来讲,棋子y+1,下边来讲棋子y-1。
斜向分析
左上:棋子x-1,y+1
左下:棋子x-1,y-1
右上:棋子x+1,y+1
右下:棋子x+1,y-1
获得这些信息后,我们可以计算出
override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)
let mousePoint = event.locationInWindow
print("x: \(mousePoint.x), y: \(mousePoint.y)")
if (mousePoint.x + 23) > 500 || (mousePoint.y + 23) > 500 {
return
}
//判断触摸的位置在棋盘的交叉点
var xPoint: Int
var yPoint: Int
xPoint = Int((mousePoint.x)/30)
yPoint = Int((mousePoint.y)/30)
if containsDuplicate(NSPoint(x: xPoint, y: yPoint)) { return }
needsDisplay = true
//判断输赢
if chess_horizontal(xPoint, yPoint, isblackOrWhite) == 5 || chess_vertical(xPoint, yPoint, isblackOrWhite) == 5 || chess_oblique(xPoint, yPoint, isblackOrWhite) == 5 {
let alert = NSAlert()
alert.addButton(withTitle: "确定")
alert.informativeText = "\(isblackOrWhite ? "黑棋" : "白棋")你赢了"
alert.messageText = ""
alert.alertStyle = .informational
alert.beginSheetModal(for: self.view.window!) { handler in
if handler == NSApplication.ModalResponse.alertFirstButtonReturn { }
}
//置空棋盘
isblackOrWhite = true
points.removeAll()
needsDisplay = true
}
//轮到另一位选手
isblackOrWhite = !isblackOrWhite
}
private func containsDuplicate(_ point: NSPoint) -> Bool {
//判断是否有相同棋子
for p in points {
let x = p.point.x - point.x
let y = p.point.y - point.y
if abs(x * x + y * y) < 0.00001 {
return true
}
}
let piece = Piece.init(point: point, isblackOrWhite: isblackOrWhite)
points.append(piece)
return false
}
private func chess_horizontal(_ chessX: Int ,_ chessY: Int, _ isblackOrWhite: Bool) -> Int {
var count = 0 //定义一个棋子的判断器
var pieces: Array<Piece> = []
for p in points {
if p.isblackOrWhite == isblackOrWhite && Int(p.point.y) == chessY { pieces.append(p) }
}
for i in 0..<5 {
//向右判断
for piece in pieces {
if chessX+i == Int(piece.point.x) {
count += 1
if count == 5 {
return count
}
}
}
}
for i in 1..<5 {
//向左判断
for piece in pieces {
if chessX-i == Int(piece.point.x) {
count += 1
if count == 5 {
return count
}
}
}
}
return 0
}
private func chess_vertical(_ chessX: Int ,_ chessY: Int, _ isblackOrWhite: Bool) -> Int {
var count = 0 //定义一个棋子的判断器
var pieces: Array<Piece> = []
for p in points {
if p.isblackOrWhite == isblackOrWhite && Int(p.point.x) == chessX { pieces.append(p) }
}
for i in 0..<5 {
//向上判断
for piece in pieces {
if chessY+i == Int(piece.point.y) {
count += 1
if count == 5 {
return count
}
}
}
}
for i in 1..<5 {
//向左判断
for piece in pieces {
if chessY-i == Int(piece.point.y) {
count += 1
if count == 5 {
return count
}
}
}
}
return 0
}
private func chess_oblique(_ chessX: Int ,_ chessY: Int, _ isblackOrWhite: Bool) -> Int{
var count = 0 //定义一个棋子的判断器
var pieces: Array<Piece> = []
for p in points {
if p.isblackOrWhite == isblackOrWhite { pieces.append(p) }
}
for i in 0..<5 {
//右上方向判断
for piece in pieces {
if chessX+i == Int(piece.point.x) && chessY+i == Int(piece.point.y) {
count += 1
if count == 5 {
return count
}
}
}
}
for i in 1..<5 {
//右下判断
for piece in pieces {
if chessX+i == Int(piece.point.x) && chessY-i == Int(piece.point.y) {
count += 1
if count == 5 {
return count
}
}
}
}
for i in 1..<5 {
//左上判断
for piece in pieces {
if chessX-i == Int(piece.point.x) && chessY+i == Int(piece.point.y) {
count += 1
if count == 5 {
return count
}
}
}
}
for i in 1..<5 {
//左下判断
for piece in pieces {
if chessX-i == Int(piece.point.x) && chessY-i == Int(piece.point.y) {
count += 1
if count == 5 {
return count
}
}
}
}
return 0
}
//合并判断方法
//判断输赢
if chess_horizontal(xPoint, yPoint, isblackOrWhite) == 5 || chess_vertical(xPoint, yPoint, isblackOrWhite) == 5 || chess_oblique(xPoint, yPoint, isblackOrWhite) == 5 {
let alert = NSAlert()
alert.addButton(withTitle: "确定")
alert.informativeText = "\(isblackOrWhite ? "黑棋" : "白棋")你赢了"
alert.messageText = ""
alert.alertStyle = .informational
alert.beginSheetModal(for: self.view.window!) { handler in
if handler == NSApplication.ModalResponse.alertFirstButtonReturn { }
}
//置空棋盘
isblackOrWhite = true
points.removeAll()
needsDisplay = true
}
悔棋
//撤销上一步动作
@IBAction func undoAction(_ sender: Any) {
if points.count != 0 {
//如果棋子数组不为0,删除最后一个棋子并刷新棋盘
points.removeLast()
needsDisplay = true
//记住撤销上一部动作后,白黑棋子必须交替。
isblackOrWhite = !isblackOrWhite
}else {
let alert = NSAlert()
alert.addButton(withTitle: "确定")
alert.informativeText = "没有棋子,无法悔棋"
alert.messageText = ""
alert.alertStyle = .informational
alert.beginSheetModal(for: self.view.window!) { handler in
if handler == NSApplication.ModalResponse.alertFirstButtonReturn { }
}
}
}
重开游戏
@IBAction func reStartAction(_ sender: Any) {
if points.count == 0 { return }
let alert = NSAlert()
alert.addButton(withTitle: "确定")
alert.addButton(withTitle: "取消")
alert.informativeText = "重开游戏"
alert.messageText = ""
alert.alertStyle = .informational
alert.beginSheetModal(for: self.view.window!) { [self] handler in
if handler == NSApplication.ModalResponse.alertFirstButtonReturn {
//清空所有棋子并刷新棋盘
points.removeAll()
isblackOrWhite = true
needsDisplay = true
}
}
}
demo链接
链接: 五子棋