【等待补充完整】70课:开发一个井字游戏App吧

这节课我们要开发一个小游戏:Tick Tack Toe 也叫 Noughts & Crosses,翻译过来应该是井字游戏。

我百度了一下,有人这么回答的:

是一种俩人制的棋类游戏,又名为圈圈叉叉,两名游戏者在圈圈(O)和叉叉(X)两种符号中,各选一种,然后在一张3x3格(也就是我们所说九宫格)棋盘上轮流下,一般叉叉先走,当一种符号在棋盘中的空格内,或竖向,或横向,或斜向成3连的情形时,该符号的游戏者胜出,此游戏由于不复杂,一般适用于小朋友们。

课程笔记文集地址:Udemy课程:The Complete iOS 9 Developer Course - Build 18 Apps

也就是从这节视频中,我意识到,编程的思维的重要性。我可以照着作者的方法迅速敲击出来代码,然后实现这个效果,但是,如果规则变了呢?或者规则没变,我没看过这节视频,我该如何实现这样的规则呢?为什么这一步要用这个方法呢?为什么要遍历结果呢?还有没有其他的方法可以实现同样的规则?单单是这些问题,让我在这节视频上困了一个周,继续往下看的进度严重被延后了。

庆幸的是,我在这个周里,接触到了李笑来的书《把时间当朋友》,里面说,卡住了,先继续往前走,只要把这个卡住的记下来就好了,说不定等你往前走到一定程度,回头看,发现这个问题就能轻易解决了呢。

所以,我决定把这节视频先搁置起来,继续往前走,继续看剩下的视频,记得有天要回来。

视频看到了 27:00。

一、布局Storeboard

1.首先布局棋盘背景,使用UIIamgeView控件,设置AutoLayout约束。

2.放置UIButton控件,去掉Button的文字使用图片,放置到正确的位置然后,设置AutoLayout约束。然后依次放置设置剩下的Button控件,一共有9个UIButton控件。实际效果图如下:


实际效果图

3.给Button控件建立Action和Outlet连接,不用给9个Button都建立连接,只给第一个建立连接就可以了。(剩下的8个Button的Action连接后面说怎么做)

    @IBOutlet weak var button: UIButton!
    
    @IBAction func buttonPressed(sender: AnyObject) {
        
    }

二、写代码:初步布局

1. setImage 方法

Button控件上显示哪个图片可以用setImage方法,如下:

    @IBAction func buttonPressed(sender: AnyObject) {
        var image = UIImage(named: "cross.png")
        
        button.setImage(image, forState: UIControlState.Normal)
    }

这样点击一下按钮,按钮外表就变成了叉号。

2.给剩下的8个Button控件创建Action连接

将剩下的8个Button控件用Ctrl拖拽法连接到Action的代码上,如下图:

拖拽8次。这样点击任何一个按钮,第一个按钮外表就变成了叉号。这不是我们想要的效果啊。

3. 参数 sender 的作用

我们想要的效果是,点击哪个按钮,哪个按钮变成叉号。这怎么办?建立八个Outlet连接?太麻烦了!这时候,我们就用到了@IBAction func buttonPressed():方法中参数 sender 的功能:

    @IBAction func buttonPressed(sender: AnyObject) {
        var image = UIImage(named: "cross.png")
        
        sender.setImage(image, forState: UIControlState.Normal)
    }

用了sender,我们可以把一开始创建的Outlet连接删掉了。
这效果对了。

4. Tag 属性的作用

Button控件有个属性叫 tag,如下图:


每个Button控件的Tag是一个单独的数字,这样就给每个Button控件一个唯一的标识符。Tag的作用像是标识符(identifier),不过tag只能是Int类型的数值且正数。

第一个Button控件的tag是0,第二个是2,以此类推,第九个是8。

这样,当我们点击集中某个按钮时,sender.tag就是我们设置的对应的tag值。比如我们给最后一个Button设置的tag值是8,点击最后一个Button时,sender.tag实际上就是数字8。

5.实现圆圈叉号交替出现的效果

在Storyborad中去掉Button的图片,按钮是叉号还是圆圈全部用代码来控制。

    // 1 是圆圈 2 是叉号
    var activePlayer = 1

    @IBAction func buttonPressed(sender: AnyObject) {
        var image = UIImage()
        
        if activePlayer == 1 {
            image = UIImage(named: "nought.png")!
            activePlayer = 2
        } else {
            image = UIImage(named: "cross.png")!
            activePlayer = 1
        }

        sender.setImage(image, forState: UIControlState.Normal)
    }

运行,点击不同的框,先出现圆圈然后叉号,不错,几乎是我们的效果了。不过,点击出现圆圈,再点击一下,变成叉号了。需要的效果是,在某个框中画了圈或者叉号,就不能再改了。

三、写代码:实现游戏规则

1.数组的力量

现在我们想办法让被点击过一次的按钮再次点击时不会更换图片。这里我们用到数组。

    var gameState = [0,0,0,0,0,0,0,0,0]
    
    @IBAction func buttonPressed(sender: AnyObject) {
        if gameState[sender.tag] == 0 {
            var image = UIImage()
            
            gameState[sender.tag] = activePlayer
            
            if activePlayer == 1 {
                image = UIImage(named: "nought.png")!
                activePlayer = 2
            } else {
                image = UIImage(named: "cross.png")!
                activePlayer = 1
            }
            
            sender.setImage(image, forState: UIControlState.Normal)

        }
    }

妙用了数组的index 和 sender.tag
关键代码:

gameState[sender.tag]

sender.tag可能的值是数字0-8,数组gameState的index也是0-8

2.什么条件就赢了?

这才是一个游戏的关键,涉及到算法,很多游戏的算法才是关键,界面什么的都好弄。
先列出作者的代码,烧脑:

var 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 buttonPressed(sender: AnyObject) {
    ...

    for combination in winningCombinations {
         if gameState[combination[0]] != 0 && gameState[combination[0]] == gameState[combination[1]] && gameState[combination[1]] == gameState[combination[2]] {
                    print("你赢啦!!")
         }
    }
}

想要实现游戏规则,首先我们要判断出什么情况下就算是赢了。比如横着3个连成行,竖着3个连成排,斜着3个连成一条线。
横着3个连成行:[0,1,2],[3,4,5],[6,7,8]
竖着3个连成排[0,3,6],[11,4,7],[2,5,8]
斜着3个连成一条线[0,4,8],[2,4,6]
看代码:

关键代码是:

gameState[combination[0]] != 0 && gameState[combination[0]] == gameState[combination[1]] && gameState[combination[1]] == gameState[combination[2]]

可以拆分成3个条件:
1)首先不等于0
2)第一个数等于第二个
3)第二个数等于第三个数字

只需要遍历所有的情况,然后只要符合这个情况,就算赢啦

3.有人赢了之后就停止游戏

gameActive = false

在你赢了之后,赋值

 @IBAction func buttonPressed(sender: AnyObject) {
        //这里加入 gameActive 状态的判断
        if (gameState[sender.tag] == 0 && gameActive == true) {

4.判断是谁赢了,弹出显示文案

 if gameState[combination[0]] == 1 {
     gameOverLabel.text = "Noughts have won!"
 } else {
    gameOverLabel.text = "Crosses have won!"
 }
endGame()

endGame的方法如下:

    func endGame() {
    
        gameOverLabel.hidden = false
        playAgainButton.hidden = false
    
        UIView.animateWithDuration(0.5, animations: { () -> Void in
    
            self.gameOverLabel.center = CGPointMake(self.gameOverLabel.center.x + 500, self.gameOverLabel.center.y)
    
            self.playAgainButton.center = CGPointMake(self.playAgainButton.center.x + 500, self.playAgainButton.center.y)
        })
    }

四、写代码:

课程笔记记录到了27:00

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容