ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Flutter 플러터] 가위바위보 앱 따라 만들기
    Study/Flutter, Dart 2024. 9. 10. 11:04
    728x90
    반응형

    가위바위보 앱 만들기

     

    main.dart

    import 'package:flutter/material.dart';
    import 'package:rsp_game/game/game_body.dart';
    
    void main() {
      runApp(const RSPAPP());
    }
    
    class RSPAPP extends StatelessWidget {
      const RSPAPP({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('가위 바위 보 게임'), backgroundColor: Colors.blue, titleTextStyle: const TextStyle(color: Colors.white, fontSize: 20), ),
            body: const GameBody(),
          ),
        );
      }
    }

     

     

     

    game_body.dart

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    import 'package:rsp_game/game/enum.dart';
    import 'package:rsp_game/game/widget/cpu_input.dart';
    import 'package:rsp_game/game/widget/game_result.dart';
    import 'package:rsp_game/game/widget/user_input.dart';
    
    class GameBody extends StatefulWidget {
      const GameBody({super.key});
    
      @override
      State<GameBody> createState() => _GameBodyState();
    }
    
    class _GameBodyState extends State<GameBody> {
      late bool isDone;
      InputType? _userInput;
      late InputType _cpuInput;
    
      @override
      void initState() {
        super.initState();
        isDone = false;
        setCpuInput();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Expanded(child: CpuInput(isDone: isDone, cpuInput: _cpuInput)),
            Expanded(
                child: GameResult(
              isDone: isDone,
              result: getResult(),
              callback: reset,
            )),
            Expanded(
                child: UserInput(
                    isDone: isDone, callback: setUserInput, userInput: _userInput)),
          ],
        );
      }
    
      void setUserInput(InputType userInput) {
        setState(() {
          isDone = true;
          _userInput = userInput;
        });
      }
    
      void setCpuInput() {
        final random = Random();
        _cpuInput = InputType.values[random.nextInt(3)];
      }
    
      void reset() {
        setState(() {
          isDone = false;
          setCpuInput();
        });
      }
    
      Result? getResult() {
        if (_userInput == null) return null;
    
        switch (_userInput!) {
          case InputType.rock:
            switch (_cpuInput) {
              case InputType.rock:
                return Result.draw;
              case InputType.scissors:
                return Result.playerWin;
              case InputType.paper:
                return Result.cpuWin;
            }
          case InputType.scissors:
            switch (_cpuInput) {
              case InputType.rock:
                return Result.cpuWin;
              case InputType.scissors:
                return Result.draw;
              case InputType.paper:
                return Result.playerWin;
            }
    
          case InputType.paper:
            switch (_cpuInput) {
              case InputType.rock:
                return Result.playerWin;
              case InputType.scissors:
                return Result.cpuWin;
              case InputType.paper:
                return Result.draw;
            }
        }
      }
    }
    반응형

     

     

    enum.dart

    const assetPath = 'assets/images';
    
    enum InputType {
      rock,
      scissors,
      paper;
    
      String get path => '$assetPath/$name.png';
    }
    
    enum Result {
      playerWin('Player 승리'),
      draw('무승부'),
      cpuWin('Player 패배');
    
      const Result(this.displayString);
      final String displayString;
    }

     

     

     

    user_input.dart

    import 'package:flutter/material.dart';
    import 'package:rsp_game/game/enum.dart';
    import 'package:rsp_game/game/widget/input_card.dart';
    
    class UserInput extends StatelessWidget {
      final bool isDone;
      final InputType? userInput;
      final Function(InputType) callback;
    
      const UserInput(
          {this.userInput,
          required this.isDone,
          required this.callback,
          super.key});
    
      @override
      Widget build(BuildContext context) {
        if (isDone) {
          return Row(
            children: [
              const Expanded(child: SizedBox.shrink()),
              Expanded(child: InputCard(child: Image.asset(userInput!.path))),
              const Expanded(child: SizedBox.shrink()),
            ],
          );
        }
    
        return Row(
          children: _getInputs(callback),
        );
      }
    
      List<Widget> _getInputs(Function(InputType) callback) {
        return InputType.values
            .map(
              (type) => Expanded(
                child: InkWell(
                  onTap: () => callback.call(type),
                  child: InputCard(
                    child: Image.asset(type.path),
                  ),
                ),
              ),
            )
            .toList();
      }
    }
    728x90

     

     

    cpu_input.dart

    import 'package:flutter/material.dart';
    import 'package:rsp_game/game/enum.dart';
    import 'package:rsp_game/game/widget/input_card.dart';
    
    class CpuInput extends StatelessWidget {
      final bool isDone;
      final InputType cpuInput;
    
      const CpuInput({required this.isDone, required this.cpuInput, super.key});
    
      @override
      Widget build(BuildContext context) {
        return Row(
          children: [
            Expanded(child: SizedBox.shrink()),
            Expanded(
              child: InputCard(
                child: getCpuInput(),
              ),
            ),
            Expanded(child: SizedBox.shrink()),
          ],
        );
      }
    
      Widget getCpuInput() {
        if (isDone) {
          return Image.asset(cpuInput.path);
        }
        return const SizedBox(
          height: 80,
          child: Center(
            child: Text(
              '?',
              style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
            ),
          ),
        );
      }
    }

     

     

     

    input_card.dart

    import 'package:flutter/material.dart';
    
    class InputCard extends StatelessWidget {
      final Widget child;
    
      const InputCard({
        super.key,
        required this.child,
      });
    
    
    
      @override
      Widget build(BuildContext context) {
        return Container(
          margin: const EdgeInsets.symmetric(horizontal:  12, vertical: 8),
          padding: const EdgeInsets.symmetric(horizontal:  12, vertical: 8),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(24),
            border: Border.all(color: Colors.grey, width: 8),
          ),
          child: child,
        );
      }
    }

     

     

     

    game_result.dart

    import 'package:flutter/material.dart';
    import 'package:rsp_game/game/enum.dart';
    
    class GameResult extends StatelessWidget {
      final bool isDone;
      final Result? result;
      final VoidCallback callback;
    
      const GameResult({required this.isDone, required this.callback, this.result, super.key});
    
      @override
      Widget build(BuildContext context) {
        if (isDone) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(result!.displayString, style: const TextStyle(fontSize: 32,fontWeight: FontWeight.bold),),
              SizedBox(height: 8,),
              TextButton(onPressed: () => callback.call(), child: const Text('다시 하기', style: TextStyle(fontSize: 24))),]
          );
        }
        return Center(
          child: Text('가위, 바위, 보 중 하나를 선택해주세요.', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),),
        );
      }
    }

     

     

    728x90
    반응형

    댓글

Designed by Tistory.