Home > Net >  Get the user input number and compare that with a simple database on flutter
Get the user input number and compare that with a simple database on flutter

Time:04-13

currently learning flutter and trying to do a simple game.

I have list with prices and product name.

My idea is to display a random image, and someone tries to guess the price.

Currently I'm stuck on the comparing the input price with the price on the list.

This is what I currently have


class MyCustomForm extends StatefulWidget {
  const MyCustomForm({Key? key}) : super(key: key);

  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
  final myController = TextEditingController();

  @override
  void initState() {
    super.initState();

    @override
    void dispose() {
      myController.dispose();
      super.dispose();
    }
  }

  @override
  Widget build(BuildContext context) {
    int randomIndex = Random().nextInt(products.length);
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          "Guess the Price!",
          style: TextStyle(fontFamily: "Pacifico"),
        ),
      ),
      backgroundColor: Colors.white,
      body: InkWell(
        child: Container(
          padding: const EdgeInsets.all(40),
          child: Column(
            children: <Widget>[
              Spacer(),
              Container(
                  child: Text(
                '${products[randomIndex].productName}',
                style: TextStyle(
                  fontSize: 30,
                ),
              )),
              Container(
                  child: TextFormField(
                      controller: myController,
                      keyboardType: TextInputType.number,
                      inputFormatters: <TextInputFormatter>[
                        FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
                      ],
                      decoration: InputDecoration(
                        hintText: "The price is ${products[randomIndex].productPrice}", //debuging 
                      ))),
              Spacer(),
              Container(
                child: Text((() {
                  if ({products[randomIndex].productPrice} == {myController.text}) {
                    return "The price is correct!";
                  }
                  return "The price is wrong!";
                })()),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

What should I add to do the work? Should I add a listener, so when the text changes, he auto updates the value of the myController.text , or should I go through other ways?

Sorry if this is a newbie error, but currently searching for solutions!

CodePudding user response:

First, you need to move randomIndex outside of the build method otherwise it would always change when the state changes and you can't compare it to user input.

I am not sure exactly what you want but I think this will give you a hint how to do it.

 class MyCustomForm extends StatefulWidget {
   const MyCustomForm({Key? key}) : super(key: key);

   @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
 final myController = TextEditingController();
 String guessText = "";
  @override
  void initState() {
    super.initState();
  }
  @override
  void dispose() {
    myController.dispose();
    super.dispose();
  }
 int randomIndex = Random().nextInt(products.length);

 @override
 Widget build(BuildContext context) {
   
  return Scaffold(
    appBar: AppBar(
      title: const Text(
      "Guess the Price!",
      style: TextStyle(fontFamily: "Pacifico"),
     ),
   ),
  backgroundColor: Colors.white,
  body: InkWell(
    child: Container(
      padding: const EdgeInsets.all(40),
      child: Column(
        children: <Widget>[
          Spacer(),
          Container(
              child: Text(
            '${products[randomIndex].productName}',
            style: TextStyle(
              fontSize: 30,
            ),
          )),
          Container(
              child: TextFormField(
                  controller: myController,
               onChanged: (value) {
                 if (products[randomIndex].productPrice == value) {
                   guessText =  "The price is correct!";
                     setState(() {
                     });
                    }
                  },
                  keyboardType: TextInputType.number,
                  inputFormatters: <TextInputFormatter>[
                    FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
                  ],
                  decoration: InputDecoration(
                    hintText: "The price is ${products[randomIndex].productPrice}", //debuging 
                  ))),
          Spacer(),
          Container(
            child: Text(guessText),
          ),
        ],
      ),
    ),
  ),
);
}
} 

CodePudding user response:

Below is a working solution. There were quite a few changes, so have a look.

You need to have a button that gives a user the chance to move to the next product (or random). Also, you call product[..].productPrice--this is unnecessary because you should call product[..].price.

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Product {
  final String name;
  final int price;

  Product(this.name, this.price);
}

class MyCustomForm extends StatefulWidget {
  const MyCustomForm({Key? key}) : super(key: key);

  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
  final myController = TextEditingController();

  List<Product> products = [
    Product('p1', 5),
    Product('p2', 10),
  ];

  int productIndex = 0;

  int enteredPrice = 0;

  @override
  void initState() {
    super.initState();

    @override
    void dispose() {
      myController.dispose();
      super.dispose();
    }
  }

  @override
  Widget build(BuildContext context) {
    int randomIndex = Random().nextInt(products.length);
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          "Guess the Price!",
          style: TextStyle(fontFamily: "Pacifico"),
        ),
      ),
      backgroundColor: Colors.white,
      body: InkWell(
        child: Container(
          padding: const EdgeInsets.all(40),
          child: Column(
            children: <Widget>[
              const Spacer(),
              Text(
                products[productIndex].name,
                style: const TextStyle(
                  fontSize: 30,
                ),
              ),
              TextFormField(
                controller: myController,
                onChanged: (_) {
                  enteredPrice = int.parse(myController.text);
                  setState(() {});
                },
                keyboardType: TextInputType.number,
                inputFormatters: <TextInputFormatter>[
                  FilteringTextInputFormatter.allow(
                    RegExp(r'[0-9]'),
                  ),
                ],
              ),
              const Spacer(),
              Text(
                (() {
                  return checkEnteredPrice(0);
                })(),
                style: const TextStyle(fontSize: 20),
              ),
              const Spacer(),
              ElevatedButton(
                  onPressed: () {
                    productIndex  ;
                    setState(() {});
                  },
                  child: const Text('Next Product'))
            ],
          ),
        ),
      ),
    );
  }

  String checkEnteredPrice(int productIndex) {
    if (products[productIndex].price == enteredPrice) {
      return "The price is correct!";
    } else {
      return "The price is wrong!";
    }
  }
}

CodePudding user response:

I wrote an example here, check the comment for descrition. Check images for demo result.

For your code, i have some advice:

  • do not (){}(), use ? : or something else instead, it look too long and make me confuse.
  • recomend to separate your logic and your render, more specific is put Random in build that cause randomIndex changes everytime widget rendered. put them in some function that caller able.
import 'package:flutter/material.dart';
import 'dart:math';

void main() => runApp(MyApp());

const products = <Map<String, dynamic>>[
  {'name': 'HotDog', 'price': 5},
  {'name': 'Televison', 'price': 699},
  {'name': 'Carrot', 'price': 10},
];

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const App(),
    );
  }
}

class App extends StatefulWidget {
  const App({Key? key}) : super(key: key);

  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  final controller = TextEditingController();

  int? randomIndex; // stored random index product
  String? answer; // stored your answer

  bool get submitAnswered =>
      answer != null; // getter check user was answerd yet?
  int? get correctPrice => randomIndex != null
      ? products[randomIndex!]['price']
      : null; // getter to get correct answer

  // function to generate randomIndex, reset your answer
  void getRandomIndex() {
    int? newIndex;
    do {
      newIndex = Random().nextInt(products.length);
    } while (newIndex == randomIndex);

    setState(() {
      randomIndex = newIndex;
      answer = null;
      controller.text = '';
    });
  }

  // function to submit your answer
  void onSubmitted(String value) {
    setState(() {
      answer = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          "Guess the Price!",
          style: TextStyle(fontFamily: "Pacifico"),
        ),
      ),
      backgroundColor: Colors.white,
      body: Container(
          padding: const EdgeInsets.all(20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Button that generate new randomIndex
              ElevatedButton(
                onPressed: getRandomIndex,
                child: const Text('Get random product'),
              ),
              // Only render when have randomIndex
              if (randomIndex != null) ...[
                // Display name of prouct
                Center(
                  child: Text(products[randomIndex!]['name']),
                ),
                // Only render when not answered yet, show text input and submit button
                if (!submitAnswered) ...[
                  TextField(
                    controller: controller,
                    onSubmitted: onSubmitted,
                    decoration: const InputDecoration(
                      hintText: 'your price',
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () => onSubmitted(controller.text),
                    child: const Text('Submit your price'),
                  ),
                ] else
                  // Only render when answered, showing your result, correct or not
                  Center(
                    child: Text(int.tryParse(answer!) == correctPrice
                        ? 'Correct price ($correctPrice)'
                        : 'Wrong price, your price is $answer and correct price is $correctPrice'),
                  ),
              ],
            ],
          )),
    );
  }
}

enter image description here enter image description here enter image description here enter image description here

  • Related