中秋时节赏明月,五子棋戏月饼趣 — Flutter中秋限定版五子棋

前言

当中秋时节来临,我们都期待着与亲人朋友共度这个美好的节日。这个时候,除了传统的赏月和品尝美味的月饼,我还有一个特别的建议------尝试一款有趣的Flutter五子棋游戏!这款五子棋游戏以中秋为主题,游戏的棋子也可爱地模仿了月饼和玉兔的形状,让我们在这个特别的节日中,一边享受游戏,一边品味团圆的温馨氛围~

效果图:

代码地址:github.com/taxze6/flut...

游戏实现

布局部分

  • 非游戏主体布局部分

游戏引导页的布局非常的简单,通过Column作为主要布局即可,月亮的动画使用自定义的显式动画:AnimatedBuilder+Transform.scale实现即可。该部分内容较为简单,就不贴代码了~

  • 游戏主体界面布局

作为五子棋这样的棋类游戏,棋盘一般都使用GridView.builder来进行构建。我们构建一个15*15的棋盘,格子的总数是225,通过取整和取模来取出每个格子对应的x和y。

dart 复制代码
GridView.builder(
  ...
  itemCount: 225,
  itemBuilder: (context, index) {
    int row = index ~/ 15;
    int col = index % 15;
    return gameButton(row, col);
  },
),

而每个格子(gameButton)则需要加上点击事件用于下棋子:

dart 复制代码
Widget gameButton(int row, int col) {
  return GestureDetector(
    onTap:{
    	...
    }
    child: Container(
      color: Colors.blue,
      child: Center(
        child: gamePiece(row, col),
      ),
    ),
  );
}

而通过gamePiece的坐标点,我们可以从棋盘的数据中判断当前坐标是什么类型,然后展示对应的图标(月饼和玉兔)。

dart 复制代码
gamePiece(int row, int col) {
  if (boardState[row][col] == GameState.Black)
    return Dot(Colors.black);
  else if (boardState[row][col] == GameState.White)
    return Dot(Colors.white);
  else
    return null;
}

逻辑部分

因篇幅原因,只讲解与游戏核心相关的逻辑,其他可查看源码。

  • 第一步 --- 定义每个棋子的状态
dart 复制代码
enum GameState {
  Blank,
  Black,
  White,
}
  • 第二步 --- 定义整个棋盘的数据,通过二维数组
dart 复制代码
var boardState = List<List<GameState>>.generate(
  15,
  (i) => List<GameState>.generate(
    15,
    (j) => GameState.Blank,
  ),
);
  • 第三步 --- 检查获胜条件

每下一颗子触发一次。

dart 复制代码
// 检查游戏胜利条件
void checkWinningCondition(int row, int col, GameState gameState) {
  // 如果移动次数小于5,不可能有获胜者,直接返回
  if (_moveCount < 5) {
    return;
  }

  // 检查当前位置是否包含当前玩家的标记
  if (boardState[row][col] == gameState) {
    // 检查从底部左侧到顶部右侧的对角线
    if (countConsecutiveStones(row, col, 1, -1) +
        countConsecutiveStones(row, col, -1, 1) >=
        4) {
      setWinner(gameState); // 设置获胜者
      return;
    }
    // 检查从顶部左侧到底部右侧的对角线
    if (countConsecutiveStones(row, col, -1, -1) +
        countConsecutiveStones(row, col, 1, 1) >=
        4) {
      setWinner(gameState); // 设置获胜者
      return;
    }
    // 检查水平方向
    if (countConsecutiveStones(row, col, 0, 1) +
        countConsecutiveStones(row, col, 0, -1) >=
        4) {
      setWinner(gameState); // 设置获胜者
      return;
    }
    // 检查垂直方向
    if (countConsecutiveStones(row, col, 1, 0) +
        countConsecutiveStones(row, col, -1, 0) >=
        4) {
      setWinner(gameState); // 设置获胜者
      return;
    }
  }
// 如果移动次数达到225,表示平局
    if (_moveCount == 225) {
      print('平局');
      setWinner(GameState.Blank); // 设置平局
      return;
    }
  }

最核心的检测部分:

dart 复制代码
// 计算在给定位置开始,特定方向上连续相同棋子类型的数量
int countConsecutiveStones(int row, int col, int rowIncrement, int colIncrement) {
  // 初始化一个计数器
  int count = 0;
  // 获取起始位置的棋子类型
  GameState index = boardState[row][col];

  // 遍历最多四个相邻格子,以查找连续相同的棋子类型
  for (int i = 1; i <= 4; i++) {
    // 检查下一个要检查的格子是否在游戏棋盘的有效范围内
    if (inBounds(row + (rowIncrement * i)) && inBounds(col + (colIncrement * i))) {
      // 检查下一个格子上的棋子类型是否与起始位置上的棋子类型相同
      if (boardState[row + (rowIncrement * i)][col + (colIncrement * i)] == index) {
        // 如果相同,增加计数
        count++;
      } else {
        // 如果不同,中断循环,因为我们只关心连续相同棋子类型的数量
        break;
      }
    }
  }
  // 返回在指定方向上连续相同棋子类型的数量
  return count;
}

 // 检查索引是否在有效范围内
bool inBounds(int index) {
    return index >= 0 && index < boardState.length;
}

这样,一个基本的双人对战五子棋就实现啦~

关于我

Hello,我是Taxze,如果您觉得文章对您有价值,希望您能给我的文章点个❤️,有问题需要联系我的话:我在这里 ,也可以通过掘金的新的私信功能联系到我。如果您觉得文章还差了那么点东西,也请通过关注督促我写出更好的文章~万一哪天我进步了呢?😝

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪9 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom11 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试