Menu
CoddyTech

Bilgi Yarışması: Sonuç Mesajı

Coddy'nin Flutter Journey'sinin Projeler bölümünün bir parçası. Ders 18 / 36.

“5 sorudan 5’ini doğru yaptın” ifadesi tek başına bir satırdan fazlasını hak ediyor. Testi büyük bir simge ve sonuca uygun bir mesajla tamamla: kusursuz bir tur için kupa, çoğunu doğru yapanlar için başparmak yukarı ve diğer durumlarda biraz cesaretlendirme.

En iyiden başlayarak kontrol edilen üç sonuç, bir if / else if / else yapısıdır. Sıralama önemlidir: kusursuz bir puan, aynı zamanda yarıdan fazlasının doğru olduğu anlamına gelir; bu yüzden önce onu kontrol et.

if (score == total) {
  message = 'Perfect!';
  icon = Icons.emoji_events;
} else if (score * 2 >= total) {
  message = 'Well done!';
  icon = Icons.thumb_up;
} else {
  message = 'Keep practicing!';
  icon = Icons.school;
}

score * 2 >= total herhangi bir yuvarlama yapmadan “en az yarısı” anlamına gelir: 5 sorudan 3’ü geçer, 2’si geçmez.

message, icon ve color değişkenlerini if öncesinde bir değer vermeden tanımla. Dart, onları kullanmadan önce her dalda her birine bir değer atandığını kontrol eder.

Bu, testin son dersi. Kontroller, renkler, puan, sonuçlar ve Yeniden oyna ile tam turlar oynatıyor.

challenge icon

Görev

Orta

Sonuçlar ekranında, puanın üzerinde:

  • tam puan, Perfect! metnini ve kehribar renginde bir Icons.emoji_events simgesini gösterir
  • en az yarım puan, Well done! metnini ve yeşil bir Icons.thumb_up simgesini gösterir
  • daha düşük bir puan, Keep practicing! metnini ve temanın birincil renginde Icons.school simgesini gösterir

Simge 96 piksel boyutundadır; ardından 16 piksel boşluk, headlineMedium ile gösterilen mesaj, 8 piksel boşluk ve artık titleMedium ile gösterilen puan satırı gelir.

Kendin dene

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const QuizScreen(),
    );
  }
}

class Question {
  const Question(this.text, this.answers, this.correct);

  final String text;
  final List<String> answers;
  final int correct;
}

const List<Question> questions = [
  Question('Which widget stacks its children from top to bottom?', ['Row', 'Column', 'Stack', 'Wrap'], 1),
  Question('Which language do you write Flutter apps in?', ['Kotlin', 'Swift', 'Dart', 'JavaScript'], 2),
  Question('What does setState do?', ['Rebuilds the widget', 'Saves the app', 'Closes the screen', 'Plays a sound'], 0),
  Question('Which widget shows a list you can scroll?', ['Container', 'SizedBox', 'Padding', 'ListView'], 3),
  Question('Which widget adds space around its child?', ['Padding', 'Center', 'Icon', 'Text'], 0),
];

class QuizScreen extends StatefulWidget {
  const QuizScreen({super.key});

  @override
  State<QuizScreen> createState() => _QuizScreenState();
}

class _QuizScreenState extends State<QuizScreen> {
  int _index = 0;
  int? _picked;
  int _score = 0;

  Question get _question => questions[_index];
  bool get _answered => _picked != null;
  bool get _isLast => _index == questions.length - 1;

  void _pick(int answer) {
    if (_answered) return;
    setState(() {
      _picked = answer;
      if (answer == _question.correct) {
        _score++;
      }
    });
  }

  Future<void> _next() async {
    if (!_isLast) {
      setState(() {
        _index++;
        _picked = null;
      });
      return;
    }
    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => ResultsScreen(score: _score, total: questions.length),
      ),
    );
    setState(() {
      _index = 0;
      _picked = null;
      _score = 0;
    });
  }

  Color? _colorFor(int answer) {
    if (!_answered) return null;
    if (answer == _question.correct) return Colors.green;
    if (answer == _picked) return Colors.red;
    return null;
  }

  @override
  Widget build(BuildContext context) {
    final question = _question;
    final textTheme = Theme.of(context).textTheme;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Quiz'),
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 16),
            child: Center(
              child: Text('Score: $_score', style: textTheme.titleMedium),
            ),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              'Question ${_index + 1} of ${questions.length}',
              style: textTheme.labelLarge,
            ),
            const SizedBox(height: 8),
            LinearProgressIndicator(
              value: (_index + 1) / questions.length,
              minHeight: 8,
              borderRadius: BorderRadius.circular(4),
            ),
            const SizedBox(height: 24),
            Text(question.text, style: textTheme.headlineSmall),
            const SizedBox(height: 24),
            for (int i = 0; i < question.answers.length; i++)
              Padding(
                padding: const EdgeInsets.only(bottom: 12),
                child: FilledButton.tonal(
                  style: FilledButton.styleFrom(
                    backgroundColor: _colorFor(i),
                    foregroundColor: _colorFor(i) == null ? null : Colors.white,
                    padding: const EdgeInsets.all(16),
                  ),
                  onPressed: () => _pick(i),
                  child: Text(question.answers[i]),
                ),
              ),
            if (_answered) ...[
              const SizedBox(height: 12),
              Text(
                _picked == question.correct
                    ? 'Correct!'
                    : 'The answer is ${question.answers[question.correct]}',
                textAlign: TextAlign.center,
                style: textTheme.titleMedium,
              ),
              const SizedBox(height: 16),
              FilledButton(
                onPressed: _next,
                child: Text(_isLast ? 'See results' : 'Next'),
              ),
            ],
          ],
        ),
      ),
    );
  }
}

class ResultsScreen extends StatelessWidget {
  const ResultsScreen({super.key, required this.score, required this.total});

  final int score;
  final int total;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Results')),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                'You scored $score out of $total',
                style: Theme.of(context).textTheme.headlineSmall,
              ),
              const SizedBox(height: 32),
              FilledButton.icon(
                onPressed: () => Navigator.pop(context),
                icon: const Icon(Icons.replay),
                label: const Text('Play again'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Projeler bölümündeki tüm dersler

Kendi başına pratik yap: Online Flutter derleyicisi