iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
0
Mobile Development

30天手滑用Google Flutter解鎖Hybrid App成就系列 第 18

30天Flutter手滑系列 - 井字遊戲實作(Tic Tac Toe)(5)

  • 分享至 

  • xImage
  •  

截至昨天30天Flutter手滑系列 - 井字遊戲實作(Tic Tac Toe)(4)為止,大致雛型已經有了,但一切都有點雜亂,今天先來整理一下。

重新安排檔案結構

由於我們先前把程式碼都放在main.dart中,這會導致閱讀上越來越混亂,因此基於重構是一直在發生中這件事,我們來調整一下。
首先把抽象類別獨立抽出來,放到lib/const/GameButton的檔案中

GameButton.js

class GameButton {
  final id;
  String text;
  bool enabled;

  GameButton({this.id, this.text = "", this.enabled = false});
}

預留一個components的資料夾,用來新增沒有邏輯,純UI呈現的components。

接下來,我們同樣新增一個pages的資料夾,把TicTacToePage_TicTacToePageState兩個class搬到game.dart內。

class TicTacToePage extends StatefulWidget {
  ...
}

class _TicTacToePageState extends State<TicTacToePage> {
  ...
}


添加開始遊戲頁

接續上一步驟,在pages的資料夾,裡面新增game.dartstart.dart的檔案。

把原先在main.dart中的開始按鈕搬到裡面。

class StartPage extends StatelessWidget {
  StartPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: ButtonTheme(
          minWidth: 200,
          height: 80,
          child: RaisedButton(
            color: Colors.blue,
            child: Text('Start Game'),
            onPressed: () {
              Navigator.of(context).pushNamed('/game');
            },
          ),
        ),
      ),
    );
  }
}

到目前為止我們的檔案結構應該如下:
https://ithelp.ithome.com.tw/upload/images/20190926/20120028VxZBNMjWS2.png

加了開始頁後,讓遊戲畫面更加乾淨,理論上使用者經驗也比較好。
https://upload.cc/i1/2019/09/26/3Zy2n7.gif


添加選擇Player功能

select.js

import 'package:flutter/material.dart';
import 'package:tictactoe/pages/game.dart';

class SelectPage extends StatefulWidget {
  _SelectPageState createState() => _SelectPageState();
}

class _SelectPageState extends State<SelectPage> {
  String player = 'X';
  void setGroupvalue(value) {
    setState(() {
      player = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Container(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Text(
                "Select Player",
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 40,
                ),
              ),
              Row(
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Column(
                    children: <Widget>[
                      Radio(
                        onChanged: (e) => setGroupvalue(e),
                        value: 'X',
                        groupValue: player,
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Text(
                          "X",
                          style: TextStyle(
                              color: Colors.black,
                              fontWeight: FontWeight.w700,
                              fontSize: 32),
                        ),
                      ),
                    ],
                  ),
                  Column(
                    children: <Widget>[
                      Radio(
                        onChanged: (e) => setGroupvalue(e),
                        value: 'O',
                        groupValue: player,
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Text(
                          "O",
                          style: TextStyle(
                              color: Colors.black,
                              fontWeight: FontWeight.w700,
                              fontSize: 32),
                        ),
                      ),
                    ],
                  )
                ],
              ),
              ButtonTheme(
                minWidth: 200,
                height: 80,
                child: RaisedButton(
                  color: Colors.blue,
                  child: Text(
                    'Start Game',
                    style: TextStyle(fontSize: 24),
                  ),
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => TicTacToePage(player: player)),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}


結論

接下來要討論如何加入AI,會介紹在井字遊戲中著名的Minimax演算法。


參考資料

https://zh.wikipedia.org/zh-tw/%E6%9E%81%E5%B0%8F%E5%8C%96%E6%9E%81%E5%A4%A7%E7%AE%97%E6%B3%95
https://www.neverstopbuilding.com/blog/minimax


上一篇
30天Flutter手滑系列 - 井字遊戲實作(Tic Tac Toe)(4)
下一篇
30天Flutter手滑系列 - 井字遊戲實作(Tic Tac Toe)(6)
系列文
30天手滑用Google Flutter解鎖Hybrid App成就30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言