截至昨天30天Flutter手滑系列 - 井字遊戲實作(Tic Tac Toe)(4)為止,大致雛型已經有了,但一切都有點雜亂,今天先來整理一下。
由於我們先前把程式碼都放在main.dart
中,這會導致閱讀上越來越混亂,因此基於重構
是一直在發生中這件事,我們來調整一下。
首先把抽象類別獨立抽出來,放到lib/const/GameButton
的檔案中
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.dart
,start.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');
},
),
),
),
);
}
}
到目前為止我們的檔案結構應該如下:
加了開始頁後,讓遊戲畫面更加乾淨,理論上使用者經驗也比較好。
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