概要
Flutterでバトルシップパズルを作成する
縦横サイズ、船の種類と数、波の数を引数で渡せるようにする
表示を改善(クリアメッセージを表示する、下に船の種類と数を表示する)
セルデータを自動生成ロジックの改善
- [Flutterでバトルシップパズルを作成する2]
(https://qiita.com/iharakenji/items/137d02f3d045af3d68ff) - [Flutterでバトルシップパズルを作成する4]
(https://qiita.com/iharakenji/items/6e0e199cf4ab608c5dc0)
実行環境
Mac
$ sw_vers
ProductName: macOS
ProductVersion: 11.6
BuildVersion: 20G165
Flutter
$ flutter --version
Flutter 2.5.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision ffb2ecea52 (5 days ago) • 2021-09-17 15:26:33 -0400
Engine • revision b3af521a05
Tools • Dart 2.14.2
修正内容
縦横サイズ、船の種類と数、波の数を引数で渡せるようにする
class BattleshipApp extends StatelessWidget {
final int rows, columns, waves;
late final List<Ship> ships;
BattleshipApp({this.columns = 10, this.rows = 10, this.waves = 2}) {
ships = [
const Ship(4, 1),
const Ship(3, 2),
const Ship(2, 3),
const Ship(1, 4)
];
}
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('BattleshipPuzzle'),
),
body: _BattleshipHome(rows, columns, ships, waves),
),
);
}
表示改善
共通部分
Widget _buildContainer() => Center(
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
const SizedBox(height: 20),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
ElevatedButton(
onPressed: () => _pushReset(),
child: const Text('Reset'),
),
const SizedBox(width: 20),
Text('TapCount: $_tapCount'),
]),
const SizedBox(height: 20),
SizedBox(
width: 440,
height: 440,
child: Stack(
children: [
Center(
child: Container(
child: _buildClearText(),
),
),
_buildColumn(),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: _buildBottom(),
),
]),
);
クリアメッセージを表示する
Widget? _buildClearText() {
if (_remainCount == 0) {
return Text(
"Clear!!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 50.0,
color: Colors.pink[500],
),
);
} else {
return null;
}
}
下に船の種類と数を表示する
Widget _buildBottom() {
final column = Column(
children:
List.generate(_ships.length, (index) => _buildShips(_ships[index])));
return SizedBox(
width: 440,
height: 160,
child: column,
);
}
Widget _buildShips(Ship ship) {
return Row(
children: List.generate(ship.num, (index) => _buildShip(ship.size)),
);
}
Widget _buildShip(int size) {
if (size == 1) {
return SizedBox(
width: 40,
height: 40,
child: _buildShipCircle(),
);
} else {
List<Widget> row = [];
row.add(
SizedBox(
width: 40,
height: 40,
child: _buildShipRoundLeft(),
),
);
for (var sizeIndex = 2; sizeIndex < size; sizeIndex++) {
row.add(
SizedBox(
width: 40,
height: 40,
child: _buildShipSquare(),
),
);
}
row.add(
SizedBox(
width: 40,
height: 40,
child: _buildShipRoundRight(),
),
);
return SizedBox(
width: size * 40,
height: 40,
child: Row(children: row),
);
}
}
セルデータを自動生成ロジックの改善
船が配置できるかチェック(横方向)
bool canExistsHorizontal(
List<List<CellType>> cellTypes, Ship ship, int row, int column) {
if (_columns < column + ship.size) {
return false;
}
// 上下チェック
for (var i = column - 1; i <= column + ship.size; i++) {
if (i < 0 || _columns <= i) {
continue;
}
if (0 < row && cellTypes[row - 1][i] != CellType.None) {
return false;
}
if (cellTypes[row][i] != CellType.None) {
return false;
}
if (row + 1 < _rows && cellTypes[row + 1][i] != CellType.None) {
return false;
}
}
return true;
}
船が配置できるかチェック(縦方向)
bool canExistsVertical(
List<List<CellType>> cellTypes, Ship ship, int row, int column) {
if (_rows < row + ship.size) {
return false;
}
// 左右チェック
for (var i = row - 1; i <= row + ship.size; i++) {
if (i < 0 || _rows <= i) {
continue;
}
if (0 < column && cellTypes[i][column - 1] != CellType.None) {
return false;
}
if (cellTypes[i][column] != CellType.None) {
return false;
}
if (column + 1 < _columns && cellTypes[i][column + 1] != CellType.None) {
return false;
}
}
return true;
}
アプリの実行
アプリを起動
flutter run