Flutter for OpenHarmony 万能游戏库App实战 - 抽牌游戏实现

抽牌游戏是一个简单但有趣的纸牌游戏。这篇文章我们来实现一个抽牌游戏,包括牌组管理、抽牌功能、洗牌功能、以及牌的网格展示。通过这个功能,我们能展示如何构建一个简单的交互式游戏

页面的基本结构

DrawCardsScreen是抽牌游戏的主页面:

dart 复制代码
class DrawCardsScreen extends StatefulWidget {
  const DrawCardsScreen({super.key});

  @override
  State<DrawCardsScreen> createState() => _DrawCardsScreenState();
}

class _DrawCardsScreenState extends State<DrawCardsScreen> {
  final DeckOfCardsApi _api = DeckOfCardsApi();
  String? _deckId;
  List<dynamic> _drawnCards = [];
  int _remaining = 52;
  bool _isLoading = false;

_deckId存储牌组ID。
_drawnCards存储已抽取的牌。
_remaining记录剩余的牌数。

创建新牌组

_newDeck方法创建新牌组:

dart 复制代码
  Future<void> _newDeck() async {
    setState(() => _isLoading = true);
    try {
      final data = await _api.getNewDeck();
      setState(() {
        _deckId = data['deck_id'];
        _remaining = data['remaining'] ?? 52;
        _drawnCards = [];
        _isLoading = false;
      });
    } catch (e) {
      setState(() => _isLoading = false);
    }
  }

调用API创建新牌组。
重置已抽取的牌和剩余牌数。

抽牌功能

_drawCards方法抽取指定数量的牌:

dart 复制代码
  Future<void> _drawCards(int count) async {
    if (_deckId == null || _remaining < count) return;
    setState(() => _isLoading = true);
    try {
      final data = await _api.drawCards(_deckId!, count: count);
      setState(() {
        _drawnCards = data['cards'] ?? [];
        _remaining = data['remaining'] ?? 0;
        _isLoading = false;
      });
    } catch (e) {
      setState(() => _isLoading = false);
    }
  }

调用API抽取指定数量的牌。
更新已抽取的牌和剩余牌数。

洗牌功能

_shuffle方法重新洗牌:

dart 复制代码
  Future<void> _shuffle() async {
    if (_deckId == null) return;
    setState(() => _isLoading = true);
    try {
      final data = await _api.reshuffleDeck(_deckId!);
      setState(() {
        _remaining = data['remaining'] ?? 52;
        _drawnCards = [];
        _isLoading = false;
      });
    } catch (e) {
      setState(() => _isLoading = false);
    }
  }

调用API重新洗牌。
重置已抽取的牌。

页面UI

页面显示牌组状态、操作按钮和已抽取的牌:

dart 复制代码
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('抽牌游戏')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Card(
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        Column(
                          children: [
                            const Icon(Icons.style, size: 40, color: Colors.blue),
                            const SizedBox(height: 8),
                            Text(_deckId != null ? '牌组已创建' : '未创建牌组', style: const TextStyle(fontWeight: FontWeight.w500)),
                          ],
                        ),
                        Column(
                          children: [
                            Text('$_remaining', style: Theme.of(context).textTheme.headlineMedium?.copyWith(fontWeight: FontWeight.bold)),
                            const Text('剩余牌数', style: TextStyle(color: Colors.grey)),
                          ],
                        ),
                      ],
                    ),

显示牌组状态和剩余牌数。

操作按钮

操作按钮包括创建新牌组、洗牌和抽牌:

dart 复制代码
                    const SizedBox(height: 20),
                    Row(
                      children: [
                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _isLoading ? null : _newDeck,
                            icon: const Icon(Icons.add),
                            label: const Text('新牌组'),
                          ),
                        ),
                        const SizedBox(width: 12),
                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _deckId == null || _isLoading ? null : _shuffle,
                            icon: const Icon(Icons.shuffle),
                            label: const Text('洗牌'),
                          ),
                        ),
                      ],
                    ),

创建新牌组和洗牌按钮。

抽牌按钮:

dart 复制代码
            const SizedBox(height: 16),
            Row(
              children: [
                Expanded(child: _buildDrawButton(1)),
                const SizedBox(width: 8),
                Expanded(child: _buildDrawButton(3)),
                const SizedBox(width: 8),
                Expanded(child: _buildDrawButton(5)),
              ],
            ),

提供抽1张、3张、5张的快捷按钮。

_buildDrawButton方法创建抽牌按钮:

dart 复制代码
  Widget _buildDrawButton(int count) {
    return OutlinedButton(
      onPressed: _deckId == null || _remaining < count || _isLoading ? null : () => _drawCards(count),
      child: Text('抽$count张'),
    );
  }

如果牌组不存在或剩余牌数不足就禁用按钮。

已抽取的牌展示

已抽取的牌用GridView展示:

dart 复制代码
            const SizedBox(height: 24),
            if (_isLoading)
              const Expanded(child: LoadingWidget())
            else if (_drawnCards.isEmpty)
              const Expanded(child: Center(child: Text('点击上方按钮抽牌', style: TextStyle(color: Colors.grey))))
            else
              Expanded(
                child: GridView.builder(
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3,
                    childAspectRatio: 0.7,
                    crossAxisSpacing: 12,
                    mainAxisSpacing: 12,
                  ),
                  itemCount: _drawnCards.length,
                  itemBuilder: (context, index) {
                    final card = _drawnCards[index];
                    return Card(
                      clipBehavior: Clip.antiAlias,
                      child: AppNetworkImage(
                        imageUrl: card['image'] ?? '',
                        fit: BoxFit.contain,
                        borderRadius: BorderRadius.zero,
                      ),
                    );
                  },
                ),
              ),

用GridView展示已抽取的牌。
每行3列,宽高比为0.7。

总结

这篇文章我们实现了一个抽牌游戏。涉及到的知识点包括:

  • API集成 - 使用Deck of Cards API管理牌组
  • 状态管理 - 管理牌组状态和已抽取的牌
  • 网格布局 - 使用GridView展示牌
  • 按钮设计 - 创建快捷操作按钮
  • 网络图片加载 - 从API加载牌的图片
  • 用户反馈 - 显示牌组状态和剩余牌数

抽牌游戏虽然功能简单,但通过清晰的UI设计和流畅的交互 ,能为用户提供一个有趣的游戏体验


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
a程序小傲2 小时前
听说前端又死了?
开发语言·前端·mysql·算法·postgresql·深度优先
副露のmagic2 小时前
python基础复健
python·算法
学Linux的语莫2 小时前
python项目打包为镜像
java·python·spring
夜雨声烦丿2 小时前
Flutter 框架跨平台鸿蒙开发 - 游戏存档管理器应用开发教程
flutter·游戏·华为·harmonyos
Ashley_Amanda2 小时前
Python 进阶:从熟练到精通的核心技能体系
开发语言·python
你怎么知道我是队长2 小时前
C语言---命令行参数
c语言·开发语言
秋刀鱼程序编程2 小时前
Java编程基础入门(四)---选择循环语句
java·开发语言·算法
大大祥2 小时前
穿山甲广告sdk接入
android·kotlin·音视频·视频播放器·广告sdk
不会飞的鲨鱼2 小时前
腾讯语音识别 一句话识别python接口
人工智能·python·语音识别