I am designing a game that the scenario is we have a drop-down menu that users can select between items, and a pageview that shows a random item after user choice, if the user's choice and random item were equal, the user wins.
And scrolling the pageView should be something like restarting the game. The drop down menu will set to null and a question mark shows until the user choose an item from the drop-down menu.
My question is about the scrolling part, when I scroll I see the new item changes twice, I don't know how to solve it?
The PageView widget contains some information that came from an API. When I get them from the API, they are in sorted order. I want them to be random, Could anyone help me with this? Here's my code:
import 'package:flutter/material.dart';
import 'webservice/API.dart';
import 'main.dart';
import 'dart:math';
import 'models/pet.dart';
import 'utils/utils.dart';
Random random = new Random();
class Guess_Game extends StatefulWidget {
const Guess_Game({Key? key}) : super(key: key);
@override
State<Guess_Game> createState() => _Guess_GameState();
}
class _Guess_GameState extends State<Guess_Game> {
String? dropdownvalue;
bool resetGame = true;
var id = '';
var name = '';
var category = '';
var status = '';
var photoURL = '';
var items = ['Bunny', 'Fish', 'Hedgehog', 'Kitty', 'Puppy'];
var dropDownIsSelected = false;
var pet_category;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.indigo,
title: const Text('Games'),
leading: GestureDetector(
child: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onTap: () {
// Navigator.pop(context);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const HomePage(),
),
(route) => false,
);
},
),
),
body: Center(
child: Column(
children: [
const Text("Guess Game",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Color.fromARGB(255, 40, 48, 95))),
const Padding(
padding: EdgeInsets.all(15.0),
child: Text("Guess which animal will we generate randomly"),
),
DropdownButton(
hint: const Text("My Guess"),
value: dropdownvalue,
icon: const Icon(Icons.keyboard_arrow_down),
items: items.map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
dropDownIsSelected = true;
resetGame = false;
});
},
),
//get pets and show one of them randomly
const Padding(
padding: EdgeInsets.all(5.0),
child: Text(" ")),
(dropDownIsSelected == true)
? FutureBuilder<List<Pet>>(
future: API.get_pets(randomly_select_URL()),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (dropDownIsSelected == true) {
var number_of_parameters = snapshot.data!.length;
var random_pet = random.nextInt(number_of_parameters);
return Expanded(
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: number_of_parameters,
onPageChanged: (int index) {
setState(() {
dropdownvalue = null;
resetGame = true;
dropDownIsSelected = false;
});
},
itemBuilder: (context, index) {
print('***Item builder***');
Pet pet = snapshot.data![random_pet];
id = pet.id.toString();
name = pet.name.toString();
category = pet.category.toString();
status = pet.status.toString();
photoURL = pet.photoUrls.toString();
return Card(
child: Container(
decoration: (photoURL.length >= 50)
? BoxDecoration(
borderRadius:
BorderRadius.circular(15),
image: DecorationImage(
image: image(photoURL).image,
fit: BoxFit.fitWidth),
)
: BoxDecoration(
borderRadius:
BorderRadius.circular(15),
image: const DecorationImage(
image: NetworkImage(
"https://cdn-cziplee-estore.azureedge.net//cache/no_image_uploaded-253x190.png"),
fit: BoxFit.fitWidth),
),
child: Column(children: [
(id == null) ? Text("Null") : Text(id),
const Text(" "),
(name == null)
? Text("Null")
: Text(
name,
style: const TextStyle(
fontWeight: FontWeight.bold),
),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
(category == null)
? Text("Null")
: Text(category),
const Text(" | "),
(status.isEmpty)
? Text("Null")
: Text(
status,
style: TextStyle(
color: (status ==
'available')
? Colors.green
: (status ==
'pending')
? const Color
.fromARGB(
255,
255,
174,
0)
: Colors.red),
),
],
),
]),
),
);
},
),
);
} else if (dropDownIsSelected == false) {
return Card(
child: Column(children: const [
Text("Please Select Your Guess "),
Image(
image: NetworkImage(
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLq9in3yNssDoF-FEX9kySutJZc8I07zmYNyKFfFebFaIbw7rLM6avVWVFJoFb16c-aUk&usqp=CAU')),
]));
}
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const CircularProgressIndicator();
},
)
: (dropdownvalue.toString() == null ||
pet_category.toString() == null)
? Column(
children: [
Text("Your Guess: " dropdownvalue.toString()),
Text("Actual Pet: " pet_category.toString()),
(dropdownvalue == pet_category)
? const Text("You Win!")
: const Text(
"Maybe next time",
style: TextStyle(
fontSize: 17, color: Colors.red),
),
],
)
: const Text(
"Please select your guess",
style: TextStyle(fontSize: 17, color: Colors.indigo),
),
],
),
),
);
}
}
CodePudding user response:
The problem is that random_pet
is assigned once after the future completes. You should move the random_pet
variable assignment to the PageView.itemBuilder
so every time a new page is built a new random value is generated.
Here's the snippet:
...
itemBuilder: (context, index) {
print('***Item builder***');
final random_pet = random.nextInt(number_of_parameters);
Pet pet = snapshot.data![random_pet];
...
CodePudding user response:
Finally, I solved the problem by considering a condition to completely reset the game, It's kind of dirty coding but it may help.
import 'package:double_back_to_close/toast.dart';
import 'package:flutter/material.dart';
import 'webservice/API.dart';
import 'main.dart';
import 'dart:math';
import 'models/pet.dart';
import 'utils/utils.dart';
Random random = new Random();
class Guess_Game extends StatefulWidget {
const Guess_Game({Key? key}) : super(key: key);
@override
State<Guess_Game> createState() => _Guess_GameState();
}
class _Guess_GameState extends State<Guess_Game> {
String? dropdownvalue;
var items = ['Bunny', 'Fish', 'Hedgehog', 'Kitty', 'Puppy'];
var dropDownIsSelected = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.indigo,
title: const Text('Games'),
leading: GestureDetector(
child: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onTap: () {
// Navigator.pop(context);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const HomePage(),
),
(route) => false,
);
},
),
),
body: Center(
child: Column(
children: [
const Text("Guess Game",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Color.fromARGB(255, 40, 48, 95))),
const Padding(
padding: EdgeInsets.all(1.0),
child: Text("Guess which animal will we generate randomly"),
),
// Text("Your Guess: " dropdownvalue.toString()),
DropdownButton(
hint: const Text("My Guess"),
value: dropdownvalue,
icon: const Icon(Icons.keyboard_arrow_down),
items: items.map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
dropDownIsSelected = true;
});
},
),
//get pets and show one of them randomly
const Padding(
padding: EdgeInsets.all(1.0),
child: Text(" ")),
(dropDownIsSelected == true)
? FutureBuilder<List<Pet>>(
future: API.get_pets(randomly_select_URL()),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (dropDownIsSelected == true) {
var number_of_parameters = snapshot.data!.length;
var random_pet = random.nextInt(number_of_parameters);
return Expanded(
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: number_of_parameters,
onPageChanged: (int index) {
setState(() {
dropdownvalue = null;
dropDownIsSelected = false;
});
},
itemBuilder: (context, index) {
Pet pet = snapshot.data![random_pet];
var id = pet.id.toString();
var name = pet.name.toString();
var category = pet.category.toString();
var status = pet.status.toString();
var photoURL = pet.photoUrls.toString();
return Card(
child: Container(
decoration: (photoURL.length >= 50)
? BoxDecoration(
borderRadius:
BorderRadius.circular(15),
image: DecorationImage(
opacity: 0.6,
image: image(photoURL).image,
fit: BoxFit.scaleDown),
)
: BoxDecoration(
borderRadius:
BorderRadius.circular(15),
image: const DecorationImage(
opacity: 0.6,
image: NetworkImage(
"https://cdn-cziplee-estore.azureedge.net//cache/no_image_uploaded-253x190.png"),
fit: BoxFit.scaleDown),
),
child: Container(
padding: EdgeInsets.all(5),
child: Column(children: [
Text("Your Guess: "
dropdownvalue.toString()),
Text("Actual Pet: "
category.toString()),
(category == dropdownvalue)
? const Text("You Win!",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.green))
: const Text("Maybe Next Time :(",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red)),
const Text(' '),
(id == null)
? const Text("Null")
: Text(id),
(name == null)
? const Text("Null")
: Text(
name,
style: const TextStyle(
fontWeight:
FontWeight.bold),
),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
(category == null)
? const Text("Null")
: Text(category),
const Text(" | "),
(status.isEmpty)
? const Text("Null")
: Text(
status,
style: TextStyle(
color: (status ==
'available')
? Colors.green
: (status ==
'pending')
? const Color
.fromARGB(
255,
255,
174,
0)
: Colors.red),
),
],
),
]),
),
),
);
},
),
);
}
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const CircularProgressIndicator();
},
)
//check if category and dropdownvalue are equal or not
: const Text(
"Please select your guess",
style: TextStyle(fontSize: 17, color: Colors.indigo),
),
(dropDownIsSelected == true)
? ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.indigo,
),
child: const Text('Remove',
style: TextStyle(color: Colors.white)),
onPressed: () {
setState(() {
dropDownIsSelected = false;
dropdownvalue = null;
});
Toast.show("Play Again!", context);
})
: const Text(""),
],
),
),
);
}
}