본문 바로가기

춘기IT/춘기개발

Flutter 카드게임 코드 (Score 점수+1 추가 적용)

Flutter로 짝 맞추기 카드게임을 만들었습니다.

//main.dart (변경없음)

import 'package:flutter/material.dart';
import 'package:memory_matching_game/src/home.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: Home(),
    );
  }
}

 

ㄴ main.dart는 기존 코드에서 변경 없음

 

//home.dart

import 'package:flutter/material.dart';
import 'package:memory_matching_game/src/card_boards.dart';
import 'package:memory_matching_game/src/header.dart';

class Home extends StatefulWidget {
  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  int tryCount = 0; // 추가
  void updateTryCount() {
    setState(() {
      tryCount++;
    });
  }

//여기부터 추가(N)
  int scoreCount = 0;
  void updateScoreCount() {
    setState(() {
      scoreCount++;
    });
  } //여기까지

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xffECE7E4),
      appBar: AppBar(
        title: const Text('짝맞추기 게임'),
        backgroundColor: const Color(0xff92CBFF),
      ),
      body: Padding(
        padding: EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Header(scoreCount: scoreCount, tryCount: tryCount),
            SizedBox(height: 20),
            Expanded(
              child: CardBoards(
                updateScoreCount: updateScoreCount, //코드 추가(N)
                updateTryCount: updateTryCount,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

 

 

//header.dart

import 'package:flutter/material.dart';

//여기부터 변경(N)
class Header extends StatelessWidget {
  final int tryCount;
  final int scoreCount;
  Header({
    super.key,
    this.scoreCount = 0,
    this.tryCount = 0,
  }); //여기까지

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 60,
      child: Row(
        children: [
          Expanded(
              child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'Score',
                style: TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.w200,
                  color: Colors.black,
                  letterSpacing: 0,
                  height: 0,
                ),
              ),
              Text(scoreCount.toString(),
                  style: TextStyle(
                      height: 0,
                      fontSize: 30,
                      letterSpacing: -2,
                      fontWeight: FontWeight.bold,
                      color: Colors.black)),
            ],
          )),
          Expanded(
              child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'Try Count',
                style: TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.w200,
                  color: Colors.black,
                  letterSpacing: 0,
                  height: 0,
                ),
              ),
              Text(tryCount.toString(),
                  style: TextStyle(
                      height: 0,
                      fontSize: 30,
                      letterSpacing: -2,
                      fontWeight: FontWeight.bold,
                      color: Colors.black)),
            ],
          )),
          Expanded(
            child: Container(
              margin: EdgeInsets.only(top: 10, bottom: 10, left: 20),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(6),
                color: Color(0xff94BEE5),
              ),
              child: Center(child: Text('새 게임')),
            ),
          ),
        ],
      ),
    );
  }
}
//변경 전
class Header extends StatelessWidget {
  final int tryCount;
  Header({super.key, this.tryCount = 0});

  int score = 100;
  
//변경 후
class Header extends StatelessWidget {
  final int tryCount;
  final int scoreCount;
  Header({
    super.key,
    this.scoreCount = 0,
    this.tryCount = 0,
  });

 

 

//cart_boards.dart

import 'package:flutter/material.dart';
import 'package:memory_matching_game/src/card.dart';
import 'package:memory_matching_game/src/card_model.dart';

//여기부터 변경(N)
class CardBoards extends StatefulWidget {
  final Function() updateTryCount;
  final Function() updateScoreCount;
  CardBoards(
      {super.key,
      required this.updateTryCount,
      required this.updateScoreCount}); //여기까지
      
  @override
  State<CardBoards> createState() => _CardBoardsState();
}

class _CardBoardsState extends State<CardBoards> {
  late List<CardModel> cards;
  @override
  void initState() {
    super.initState();
    List<int> cardsValue = [1, 5, 2, 6, 3, 4, 3, 2, 6, 1, 4, 5];
    cardsValue.shuffle();
    cards = List.generate(cardsValue.length, (index) {
      return CardModel(index: index, cardValue: cardsValue[index]);
    });
  }

  CardModel? instantFirstCard;

  void onTapCard(int cardIndex) {
    print('$cardIndex 번째 카드를 선택하셨습니다.');
    if (instantFirstCard == null) {
      instantFirstCard = cards[cardIndex];
    } else {
      // 두번째 카드가 선택되었을때 로직 추가
      widget.updateTryCount();
      var firstCard = instantFirstCard;
      var secondCard = cards[cardIndex];
      if (firstCard!.cardValue == secondCard.cardValue) {
        print('짝이 맞았습니다.');
        widget.updateScoreCount(); //추가(N) 점수 올리는 코드
        instantFirstCard = null;
      } else {
        resetInstantCards(instantFirstCard!, secondCard);
      }
    }
    setState(() {
      cards[cardIndex].setFlipped(true);
    });
  }

  void resetInstantCards(CardModel firstCard, CardModel secondCard) async {
    await Future.delayed(Duration(seconds: 1));
    setState(() {
      firstCard.setFlipped(false);
      secondCard.setFlipped(false);
    });
    instantFirstCard = null;
    return;
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Wrap(
        spacing: 4,
        runSpacing: 4,
        children: [
          for (var i = 0; i < cards.length; i++)
            CardWidget(
              card: cards[i],
              onTap: () {
                onTapCard(i);
              },
            ),
        ],
      ),
    );
  }
}
//변경 전
class CardBoards extends StatefulWidget {
  final Function() updateTryCount;
  CardBoards({super.key, required this.updateTryCount});
  
//변경 후
class CardBoards extends StatefulWidget {
  final Function() updateTryCount;
  final Function() updateScoreCount;
  CardBoards(
      {super.key,
      required this.updateTryCount,
      required this.updateScoreCount}); //여기까지

 

 

//card.dart

import 'package:flutter/material.dart';
import 'package:memory_matching_game/src/card_model.dart';

class CardWidget extends StatelessWidget {
  final CardModel card;
  final Function()? onTap;
  const CardWidget({
    super.key,
    required this.card,
    this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        if (onTap != null && !card.isFlipped) {
          // 수정
          onTap!();
        }
      },
      child: Container(
        width: 115,
        height: 150,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(12),
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.black.withAlpha(51), //변경(N)전 withOpacity(0.2)권장되지 않아 수정
              offset: Offset(0, 2),
              blurRadius: 4,
            ),
          ],
        ),
        child: card.isFlipped // 수정
            ? Center(
                child: Image.asset('assets/images/${card.cardValue}.png'), // 수정
              )
            : Container(
                margin: EdgeInsets.all(8),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(12),
                  color: Color(0xffBBD0E3),
                ),
                child: Center(child: Image.asset('assets/images/logo.png'))),
      ),
    );
  }
}

 

 

//card_model.dart (변경없음)

class CardModel {
  final int index;
  final int cardValue;
  bool isFlipped;

  CardModel({
    required this.index,
    required this.cardValue,
    this.isFlipped = false,
  });

  void setFlipped(bool state) {
    // 추가
    isFlipped = state;
  }
}

 

ㄴ card_model.dart 기존 코드에서 변경 없음

 

짝 맞추기 카드게임은 두 장의 카드를 뒤집어 같은 그림을 맞추면 점수가 올라가는 기억력 게임입니다.

짝이 맞으면 카드가 그대로 보이는 것에서 -> 점수 1점씩 올리는 것을 추가했고,

틀리면 다시 뒤집혀서 계속 도전하는 방식입니다.