NEW: MIH MineSweeper Package Pt 3

This commit is contained in:
2025-10-30 11:58:46 +02:00
parent 39a42048c2
commit d6f1629485
7 changed files with 293 additions and 151 deletions

View File

@@ -93,4 +93,31 @@ class MihColors {
return const Color(0xFF9857D4); return const Color(0xFF9857D4);
} }
} }
static Color getGoldColor(bool darkMode) {
if (darkMode == true) {
return const Color(0xFFD4AF37);
} else {
// Add a different shade of pink for light mode
return const Color(0xffFFD700);
}
}
static Color getSilverColor(bool darkMode) {
if (darkMode == true) {
return const Color(0xffC0C0C0);
} else {
// Add a different shade of pink for light mode
return const Color(0xFFA6A6A6);
}
}
static Color getBronze(bool darkMode) {
if (darkMode == true) {
return const Color(0xffB1560F);
} else {
// Add a different shade of pink for light mode
return const Color(0xFFCD7F32);
}
}
} }

View File

@@ -16,8 +16,26 @@ class BuildMinesweeperLeaderboardList extends StatefulWidget {
class _BuildMinesweeperLeaderboardListState class _BuildMinesweeperLeaderboardListState
extends State<BuildMinesweeperLeaderboardList> { extends State<BuildMinesweeperLeaderboardList> {
Color getMedalColor(int index) {
switch (index) {
case (0):
return MihColors.getGoldColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
case (1):
return MihColors.getSilverColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
case (2):
return MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
default:
return MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final double width = MediaQuery.sizeOf(context).width;
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>( return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider, builder: (BuildContext context, MzansiProfileProvider profileProvider,
MihMineSweeperProvider mineSweeperProvider, Widget? child) { MihMineSweeperProvider mineSweeperProvider, Widget? child) {
@@ -32,14 +50,15 @@ class _BuildMinesweeperLeaderboardListState
}, },
itemCount: mineSweeperProvider.leaderboard!.length, itemCount: mineSweeperProvider.leaderboard!.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return ListTile( return Padding(
leading: Row( padding: EdgeInsets.symmetric(horizontal: width / 20),
mainAxisSize: MainAxisSize.min, child: Row(
children: [ children: [
Text( Text(
"#${index + 1}", "#${index + 1}",
style: TextStyle( style: TextStyle(
fontSize: 25, fontSize: 25,
color: getMedalColor(index),
), ),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
@@ -49,36 +68,42 @@ class _BuildMinesweeperLeaderboardListState
mineSweeperProvider.leaderboardUserPictures.isNotEmpty mineSweeperProvider.leaderboardUserPictures.isNotEmpty
? mineSweeperProvider.leaderboardUserPictures[index] ? mineSweeperProvider.leaderboardUserPictures[index]
: null, : null,
width: 60, width: 80,
editable: false, editable: false,
fileNameController: null, fileNameController: null,
userSelectedfile: null, userSelectedfile: null,
frameColor: MihColors.getSecondaryColor( frameColor: getMedalColor(index),
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getPrimaryColor( backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"), MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: () {}, onChange: () {},
), ),
const SizedBox(width: 10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${mineSweeperProvider.leaderboard![index].username}${profileProvider.user!.username == mineSweeperProvider.leaderboard![index].username ? " (You)" : ""}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: getMedalColor(index),
),
),
Text(
"Score: ${mineSweeperProvider.leaderboard![index].game_score}\nTime: ${mineSweeperProvider.leaderboard![index].game_time}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 18,
// fontWeight: FontWeight.bold,
color: getMedalColor(index),
),
),
],
)
], ],
), ),
title: Text(
"${mineSweeperProvider.leaderboard![index].username}${profileProvider.user!.username == mineSweeperProvider.leaderboard![index].username ? " (You)" : ""}",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
"Score: ${mineSweeperProvider.leaderboard![index].game_score}\nTime: ${mineSweeperProvider.leaderboard![index].game_time}",
style: TextStyle(
fontSize: 18,
// fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
); );
}, },
); );

View File

@@ -15,8 +15,26 @@ class BuildMyScoreBoardList extends StatefulWidget {
class _BuildMinesweeperLeaderboardListState class _BuildMinesweeperLeaderboardListState
extends State<BuildMyScoreBoardList> { extends State<BuildMyScoreBoardList> {
Color getMedalColor(int index) {
switch (index) {
case (0):
return MihColors.getGoldColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
case (1):
return MihColors.getSilverColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
case (2):
return MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
default:
return MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final double width = MediaQuery.sizeOf(context).width;
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>( return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider, builder: (BuildContext context, MzansiProfileProvider profileProvider,
MihMineSweeperProvider mineSweeperProvider, Widget? child) { MihMineSweeperProvider mineSweeperProvider, Widget? child) {
@@ -31,36 +49,44 @@ class _BuildMinesweeperLeaderboardListState
}, },
itemCount: mineSweeperProvider.myScoreboard!.length, itemCount: mineSweeperProvider.myScoreboard!.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return ListTile( return Padding(
leading: Row( padding: EdgeInsets.symmetric(horizontal: width / 20),
mainAxisSize: MainAxisSize.min, child: Row(
children: [ children: [
Text( Text(
"#${index + 1}", "#${index + 1}",
style: TextStyle( style: TextStyle(
fontSize: 25, fontSize: 25,
color: getMedalColor(index),
), ),
), ),
const SizedBox(width: 10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Score: ${mineSweeperProvider.myScoreboard![index].game_score}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: getMedalColor(index),
),
),
Text(
"Time: ${mineSweeperProvider.myScoreboard![index].game_time}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 18,
// fontWeight: FontWeight.bold,
color: getMedalColor(index),
),
),
],
)
], ],
), ),
title: Text(
"Score: ${mineSweeperProvider.myScoreboard![index].game_score}",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
"Time: ${mineSweeperProvider.myScoreboard![index].game_time}",
style: TextStyle(
fontSize: 18,
// fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
); );
}, },
); );

View File

@@ -29,20 +29,16 @@ class _MihMineSweeperLeaderBoardState extends State<MihMineSweeperLeaderBoard> {
MihMineSweeperProvider mineSweeperProvider = MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>(); context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty; filterController.text = mineSweeperProvider.difficulty;
if (mineSweeperProvider.leaderboard == null || KenLogger.success("getting data");
mineSweeperProvider.leaderboard!.isEmpty) { await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider);
KenLogger.success("getting data"); List<ImageProvider<Object>?> userPictures = [];
await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider); String userPicUrl = "";
List<ImageProvider<Object>?> userPictures = []; for (final ranking in mineSweeperProvider.leaderboard!) {
String userPicUrl = ""; userPicUrl = await MihFileApi.getMinioFileUrl(ranking.proPicUrl, context);
for (final ranking in mineSweeperProvider.leaderboard!) { userPictures.add(NetworkImage(userPicUrl));
userPicUrl =
await MihFileApi.getMinioFileUrl(ranking.proPicUrl, context);
userPictures.add(NetworkImage(userPicUrl));
}
mineSweeperProvider.setLeaderboardUserPictures(
leaderboardUserPictures: userPictures);
} }
mineSweeperProvider.setLeaderboardUserPictures(
leaderboardUserPictures: userPictures);
} }
void refreshLeaderBoard( void refreshLeaderBoard(

View File

@@ -38,12 +38,12 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
Timer? _timer; Timer? _timer;
int _milliseconds = 0; int _milliseconds = 0;
bool _isRunning = false; bool _isRunning = false;
static const int millisecondsPerUpdate = 10; static const int millisecondsPerUpdate = 100;
double timeStringToTotalSeconds(String timeString) { double timeStringToTotalSeconds(String timeString) {
try { try {
List<String> parts = timeString.split(':'); List<String> parts = timeString.split(':');
if (parts.length < 4) { if (parts.length != 4) {
return 0.0; return 0.0;
} }
double hours = double.parse(parts[0]); double hours = double.parse(parts[0]);
@@ -51,7 +51,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
double seconds = double.parse(parts[2]); double seconds = double.parse(parts[2]);
double milliseconds = double.parse(parts[3]); double milliseconds = double.parse(parts[3]);
double totalSeconds = double totalSeconds =
(hours * 3600) + (minutes * 60) + seconds + (milliseconds / 1000); (hours * 3600) + (minutes * 60) + seconds + (milliseconds / 100);
return totalSeconds; return totalSeconds;
} catch (e) { } catch (e) {
print("Error parsing time string: $e"); print("Error parsing time string: $e");
@@ -113,7 +113,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
String _formatTime() { String _formatTime() {
Duration duration = Duration(milliseconds: _milliseconds); Duration duration = Duration(milliseconds: _milliseconds);
final int hours = duration.inHours.remainder(60); final int hours = duration.inHours;
final int minutes = duration.inMinutes.remainder(60); final int minutes = duration.inMinutes.remainder(60);
final int seconds = duration.inSeconds.remainder(60); final int seconds = duration.inSeconds.remainder(60);
final int centiseconds = (duration.inMilliseconds.remainder(1000)) ~/ 10; final int centiseconds = (duration.inMilliseconds.remainder(1000)) ~/ 10;
@@ -735,7 +735,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
children: [ children: [
SpeedDialChild( SpeedDialChild(
child: Icon( child: Icon(
Icons.add, Icons.rule_rounded,
color: MihColors.getPrimaryColor( color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"), "Dark"),

View File

@@ -18,9 +18,11 @@ class _MineSweeperQuickStartGuideState
return Text( return Text(
title, title,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: TextStyle(
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
), ),
); );
} }
@@ -28,9 +30,11 @@ class _MineSweeperQuickStartGuideState
Widget _buildSubSectionTitle(String title) { Widget _buildSubSectionTitle(String title) {
return Text( return Text(
title, title,
style: const TextStyle( style: TextStyle(
fontSize: 17, fontSize: 17,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
), ),
); );
} }
@@ -41,7 +45,8 @@ class _MineSweeperQuickStartGuideState
required Color color, required Color color,
}) { }) {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 4.0, bottom: 4.0), padding:
const EdgeInsets.only(left: 8.0, right: 8.0, top: 4.0, bottom: 4.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -58,7 +63,12 @@ class _MineSweeperQuickStartGuideState
padding: const EdgeInsets.only(left: 10.0), padding: const EdgeInsets.only(left: 10.0),
child: Text( child: Text(
'$point', '$point',
style: const TextStyle(fontSize: 16), style: TextStyle(
fontSize: 16,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
), ),
)) ))
.toList(), .toList(),
@@ -69,7 +79,7 @@ class _MineSweeperQuickStartGuideState
Widget _buildNumberClue(String clue, String explanation) { Widget _buildNumberClue(String clue, String explanation) {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0), padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 4.0),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
@@ -80,8 +90,8 @@ class _MineSweeperQuickStartGuideState
text: TextSpan( text: TextSpan(
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: MihColors.getYellowColor( color: MihColors.getOrangeColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark")), MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: 'If you see a $clue: ', text: 'If you see a $clue: ',
@@ -99,7 +109,7 @@ class _MineSweeperQuickStartGuideState
Widget _buildStrategyPoint(String title, String explanation, Widget _buildStrategyPoint(String title, String explanation,
{bool isAction = false}) { {bool isAction = false}) {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0), padding: const EdgeInsets.only(right: 8.0, left: 8.0, bottom: 4.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -107,7 +117,7 @@ class _MineSweeperQuickStartGuideState
text: TextSpan( text: TextSpan(
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: MihColors.getSecondaryColor( color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")), MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
@@ -141,7 +151,7 @@ class _MineSweeperQuickStartGuideState
Text('', Text('',
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
color: MihColors.getOrangeColor( color: MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"), MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
Expanded( Expanded(
@@ -149,7 +159,7 @@ class _MineSweeperQuickStartGuideState
text: TextSpan( text: TextSpan(
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: MihColors.getSecondaryColor( color: MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")), MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
@@ -194,83 +204,144 @@ class _MineSweeperQuickStartGuideState
'Minesweeper is a puzzle game where you use numbers to figure out where the hidden bombs (mines) are located.', 'Minesweeper is a puzzle game where you use numbers to figure out where the hidden bombs (mines) are located.',
style: TextStyle(fontSize: 16), style: TextStyle(fontSize: 16),
), ),
const Divider(height: 30), // const Divider(height: 30),
const SizedBox(height: 15),
// --- 1. Two Main Actions --- // --- 1. Two Main Actions ---
_buildSectionTitle('1. Two Main Actions (Your Controls)'), Container(
const SizedBox(height: 8), decoration: BoxDecoration(
_buildRulePoint( color: MihColors.getSecondaryColor(
title: 'Quick Tap (or Click): This is the Dig action.', MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
points: [ borderRadius: BorderRadius.circular(15),
'Goal: To uncover a square and see a number clue.', ),
'Risk: If you click a mine, the game ends!', child: Column(
], children: [
color: MihColors.getGreenColor( const SizedBox(height: 8),
MzansiInnovationHub.of(context)!.theme.mode != "Dark"), _buildSectionTitle('1. Two Main Actions (Your Controls)'),
const SizedBox(height: 8),
_buildRulePoint(
title: 'Quick Tap (or Click): This is the Dig action.',
points: [
'Goal: To uncover a square and see a number clue.',
'Risk: If you click a mine, the game ends!',
],
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
),
_buildRulePoint(
title:
'Tap and Hold (or Long Press): This is the Flag action (🚩).',
points: [
'Goal: To safely mark a square that you are **certain** is a mine.',
'Benefit: You cannot accidentally click a square that is flagged.',
],
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
),
const SizedBox(height: 4),
],
),
), ),
_buildRulePoint( const SizedBox(height: 15),
title:
'Tap and Hold (or Long Press): This is the Flag action (🚩).',
points: [
'Goal: To safely mark a square that you are **certain** is a mine.',
'Benefit: You cannot accidentally click a square that is flagged.',
],
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
),
const Divider(height: 30),
// --- 2. The Golden Rule: Reading the Numbers --- // --- 2. The Golden Rule: Reading the Numbers ---
_buildSectionTitle('2. The Golden Rule: Reading the Numbers'), Container(
const SizedBox(height: 8), decoration: BoxDecoration(
const Text( color: MihColors.getSecondaryColor(
'The number tells you exactly how many mines are touching that square (including sides and corners).', MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
style: TextStyle(fontSize: 18, fontStyle: FontStyle.italic), borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle('2. The Golden Rule: Reading the Numbers'),
const SizedBox(height: 8),
Text(
'The number tells you exactly how many mines are touching that square (including sides and corners).',
style: TextStyle(
fontSize: 18,
fontStyle: FontStyle.italic,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode !=
"Darl"),
),
),
const SizedBox(height: 8),
_buildNumberClue('Blank Space (a \'0\')',
'Zero (0) mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.'),
_buildNumberClue('\'1\'',
'Only **one** mine is touching this square. You must find and flag that single mine.'),
_buildNumberClue('\'3\'',
'Three mines are touching this square. You must find and flag all three.'),
const SizedBox(height: 4),
],
),
), ),
const SizedBox(height: 8), const SizedBox(height: 15),
_buildNumberClue('Blank Space (a \'0\')',
'Zero (0) mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.'),
_buildNumberClue('\'1\'',
'Only **one** mine is touching this square. You must find and flag that single mine.'),
_buildNumberClue('\'3\'',
'Three mines are touching this square. You must find and flag all three.'),
const Divider(height: 30),
// --- 3. The Winning Strategy --- // --- 3. The Winning Strategy ---
_buildSectionTitle('3. The Winning Strategy (The Deduction Loop)'), Container(
const SizedBox(height: 8), decoration: BoxDecoration(
const Text( color: MihColors.getSecondaryColor(
'The game is won by uncovering every single safe square and correctly flagging all the mines. Use this two-step loop to clear the board:', MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
style: TextStyle(fontSize: 18), borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle(
'3. The Winning Strategy (The Deduction Loop)'),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
'The game is won by uncovering every single safe square and correctly flagging all the mines. Use this two-step loop to clear the board:',
style: TextStyle(
fontSize: 18,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode !=
"Darl"),
),
),
),
const SizedBox(height: 8),
_buildSubSectionTitle('A. Find the Mines (Where to Flag 🚩)'),
_buildStrategyPoint(
'Look for a number that only has one choice for a mine.',
'Example: If a \'1\' is touching only one hidden square, that hidden square **must** be the mine.'),
_buildStrategyPoint('Action:',
'Tap and Hold to place a **Flag** on the square you are sure is a mine.',
isAction: true),
const SizedBox(height: 12),
_buildSubSectionTitle(
'B. Find the Safe Squares (Where to Dig)'),
_buildStrategyPoint(
'Look for a number that has been \'satisfied\' by your flags.',
'Example: You see a \'2\'. You have already placed two 🚩 flags touching it. The \'2\' is satisfied.'),
_buildStrategyPoint('Action:',
'Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They **must be safe** because the mine requirement has already been met.',
isAction: true),
],
),
), ),
const SizedBox(height: 8), const SizedBox(height: 15),
_buildSubSectionTitle('A. Find the Mines (Where to Flag 🚩)'),
_buildStrategyPoint(
'Look for a number that only has one choice for a mine.',
'Example: If a \'1\' is touching only one hidden square, that hidden square **must** be the mine.'),
_buildStrategyPoint('Action:',
'Tap and Hold to place a **Flag** on the square you are sure is a mine.',
isAction: true),
const SizedBox(height: 12),
_buildSubSectionTitle('B. Find the Safe Squares (Where to Dig)'),
_buildStrategyPoint(
'Look for a number that has been \'satisfied\' by your flags.',
'Example: You see a \'2\'. You have already placed two 🚩 flags touching it. The \'2\' is satisfied.'),
_buildStrategyPoint('Action:',
'Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They **must be safe** because the mine requirement has already been met.',
isAction: true),
const Divider(height: 30),
// --- Key Beginner Tip --- // --- Key Beginner Tip ---
_buildSectionTitle('✨ Key Beginner Tips'), Container(
_buildTipPoint('Start on the Edges and Corners:', decoration: BoxDecoration(
'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.'), color: MihColors.getSecondaryColor(
_buildTipPoint('Don\'t Guess:', MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
'If you are down to two squares and either one could be the mine, look somewhere else on the board for a guaranteed, safe move.'), borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle('✨ Key Beginner Tips'),
const SizedBox(height: 8),
_buildTipPoint('Start on the Edges and Corners:',
'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.'),
_buildTipPoint('Don\'t Guess:',
'If you are down to two squares and either one could be the mine, look somewhere else on the board for a guaranteed, safe move.'),
const SizedBox(height: 8),
],
),
),
], ],
), ),
), ),

View File

@@ -31,13 +31,10 @@ class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
MihMineSweeperProvider mineSweeperProvider = MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>(); context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty; filterController.text = mineSweeperProvider.difficulty;
if (mineSweeperProvider.myScoreboard == null || KenLogger.success("getting data");
mineSweeperProvider.myScoreboard!.isEmpty) { await MihMinesweeperServices()
KenLogger.success("getting data"); .getMyScoreboard(profileProvider, mineSweeperProvider);
await MihMinesweeperServices() KenLogger.success("${mineSweeperProvider.myScoreboard}");
.getMyScoreboard(profileProvider, mineSweeperProvider);
KenLogger.success("${mineSweeperProvider.myScoreboard}");
}
} }
void refreshLeaderBoard( void refreshLeaderBoard(