0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutterでバトルシップパズルを作成する2

Last updated at Posted at 2021-09-20

概要

Flutterでバトルシップパズルを作成する
前回手動で生成していたセルデータを自動生成する

実行環境

Mac

$ sw_vers
ProductName:    macOS
ProductVersion: 11.6
BuildVersion:   20G165

Flutter

$ flutter --version
Flutter 2.5.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 4cc385b4b8 (11 days ago) • 2021-09-07 23:01:49 -0700
Engine • revision f0826da7ef
Tools • Dart 2.14.0

手順

配置する項目を決める

船1(大きさ1, 数4)
船2(大きさ2, 数3)
船3(大きさ3, 数2)
船4(大きさ4, 数1)
波(大きさ1, 数2)

static const ship1 = Ship(1, 4);
static const ship2 = Ship(2, 3);
static const ship3 = Ship(3, 2);
static const ship4 = Ship(4, 1);
static const wave = 2;

セルデータを初期化する

var cellTypes = List.generate(
        rows, (_) => List.generate(columns, (_) => CellType.None));

船を配置する

var ships = [ship4, ship3, ship2, ship1];
for (var ship in ships) {
  cellTypes = placeShip(cellTypes, ship, rows, columns);
}

波を配置する

cellTypes = placeWave(cellTypes, rows, columns);

アプリの内容

セルデータの作成

static List<List<CellType>> generate(int rows, int columns) {
  var cellTypes = List.generate(
      rows, (_) => List.generate(columns, (_) => CellType.None));

  var ships = [ship4, ship3, ship2, ship1];
  for (var ship in ships) {
    cellTypes = placeShip(cellTypes, ship, rows, columns);
  }
  cellTypes = placeWave(cellTypes, rows, columns);

  return cellTypes;
}

船を配置する

static List<List<CellType>> placeShip(List<List<CellType>> cellTypes, Ship ship, int rows, int columns) {
  for (var numIndex = 0; numIndex < ship.num; numIndex++) {
    var positions = buildPositions(cellTypes, ship, rows, columns);
    if (positions.isEmpty) {
      continue;
    }
    var position = positions[Random().nextInt(positions.length)];
    if (ship.size == 1) {
      cellTypes[position.item2][position.item3] = CellType.ShipCircle;
    } else if (position.item1 == Direction.Horizontal) {
      cellTypes[position.item2][position.item3] = CellType.ShipRoundLeft;
      for (var sizeIndex = 1; sizeIndex < ship.size; sizeIndex++) {
        cellTypes[position.item2][position.item3 + sizeIndex] =
            CellType.ShipSquare;
      }
      cellTypes[position.item2][position.item3 + ship.size - 1] =
          CellType.ShipRoundRight;
    } else {
      cellTypes[position.item2][position.item3] = CellType.ShipRoundTop;
      for (var sizeIndex = 1; sizeIndex < ship.size; sizeIndex++) {
        cellTypes[position.item2 + sizeIndex][position.item3] =
            CellType.ShipSquare;
      }
      cellTypes[position.item2 + ship.size - 1][position.item3] =
          CellType.ShipRoundBottom;
    }
  }
  return cellTypes;
}

波を配置する

static List<List<CellType>> placeWave(List<List<CellType>> cellTypes, int rows, int columns) {
  for (var i = 0; i < wave; i++) {
    List<Tuple2<int, int>> positions = [];
    for (var row = 0; row < rows; row++) {
      for (var column = 0; column < columns; column++) {
        if (cellTypes[row][column] == CellType.None) {
          positions.add(Tuple2(row, column));
        }
      }
    }
    var position = positions[Random().nextInt(positions.length)];
    cellTypes[position.item1][position.item2] = CellType.Wave;
  }
  return cellTypes;
}

波を配置する

static List<Tuple3<Direction, int, int>> buildPositions(List<List<CellType>> cellTypes, Ship ship, int rows, int columns) {
  List<Tuple3<Direction, int, int>> positions = [];
  for (var row = 0; row < rows; row++) {
    for (var column = 0; column < columns; column++) {
      if (canExistsHorizontal(
          cellTypes, ship, rows, row, columns, column)) {
        positions.add(Tuple3(Direction.Horizontal, row, column));
      }
      if (canExistsVertical(
          cellTypes, ship, rows, row, columns, column)) {
        positions.add(Tuple3(Direction.Vertical, row, column));
      }
    }
  }
  return positions;
}

船が配置できるかチェック(横方向)

static bool canExistsHorizontal(List<List<CellType>> cellTypes, Ship ship,
    int rows, int row, int columns, int column) {
  if (columns < column + ship.size) {
    return false;
  }
  // 左側チェック
  if (0 < column) {
    if (0 < row && cellTypes[row - 1][column - 1] != CellType.None) {
      return false;
    }
    if (cellTypes[row][column - 1] != CellType.None) {
      return false;
    }
    if (row + 1 < rows && cellTypes[row + 1][column - 1] != CellType.None) {
      return false;
    }
  }
  // 右側チェック
  if (column + ship.size < columns) {
    if (0 < row && cellTypes[row - 1][column + ship.size] != CellType.None) {
      return false;
    }
    if (cellTypes[row][column + ship.size] != CellType.None) {
      return false;
    }
    if (row + 1 < rows && cellTypes[row + 1][column + ship.size] != CellType.None) {
      return false;
    }
  }
  // 真ん中チェック
  for (var sizeIndex = 0; sizeIndex < ship.size; sizeIndex++) {
    if (0 < row && cellTypes[row - 1][column + sizeIndex] != CellType.None) {
      return false;
    }
    if (cellTypes[row][column + sizeIndex] != CellType.None) {
      return false;
    }
    if (row + 1 < rows &&
        cellTypes[row + 1][column + sizeIndex] != CellType.None) {
      return false;
    }
  }
  return true;
}

船が配置できるかチェック(縦方向)

static bool canExistsVertical(List<List<CellType>> cellTypes, Ship ship,
    int rows, int row, int columns, int column) {
  if (rows < row + ship.size) {
    return false;
  }
  // 上側チェック
  if (0 < row) {
    if (0 < column && cellTypes[row - 1][column - 1] != CellType.None) {
      return false;
    }
    if (cellTypes[row - 1][column] != CellType.None) {
      return false;
    }
    if (column + 1 < columns &&
        cellTypes[row - 1][column + 1] != CellType.None) {
      return false;
    }
  }
  // 下側チェック
  if (row + ship.size < rows) {
    if (0 < column && cellTypes[row + ship.size][column - 1] != CellType.None) {
      return false;
    }
    if (cellTypes[row + ship.size][column] != CellType.None) {
      return false;
    }
    if (column + 1 < columns &&
        cellTypes[row + ship.size][column + 1] != CellType.None) {
      return false;
    }
  }
  // 真ん中チェック
  for (var sizeIndex = 0; sizeIndex < ship.size; sizeIndex++) {
    if (0 < column &&
        cellTypes[row + sizeIndex][column - 1] != CellType.None) {
      return false;
    }
    if (cellTypes[row + sizeIndex][column] != CellType.None) {
      return false;
    }
    if (column + 1 < columns &&
        cellTypes[row + sizeIndex][column + 1] != CellType.None) {
      return false;
    }
  }
  return true;
}

船(数と大きさ)

class Ship {
  final int size, num;

  const Ship(this.size, this.num);
}

船の向き

enum Direction {
  Vertical,
  Horizontal,
}

アプリの実行

アプリを起動

flutter run

実行結果

battleship2.gif

GitHub

Webアプリ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?