Flutter from Loadstate the number is being displayed but not updated in the cell

31 views Asked by At

So from the loadUserFillenumber using sharedpreference Im getting the userfilled number, and displaying in the sudoku table and cell, but its onlying displaying the userfillednumber from loadstate instead of updating, because of this my isGamewon isnt triggring. I tried but its not working is there any thing i need to modify so that when userfilledNumber from loadstate is updated in the cell instead of displaying,

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:iconsax/iconsax.dart';
import 'package:sudoku/Pages/navigation_bar.dart';
import 'package:sudoku/Screens/win_page.dart';
import 'package:sudoku/constants/usefull_tips_slideshow.dart';
import 'package:sudoku/services/game_state_manager.dart';
import 'package:sudoku/widgets/buttons/number_button.dart';
import 'package:sudoku/functions/sudoku_points.dart';
import 'package:sudoku/functions/sudoku_validator.dart';
import 'package:sudoku/functions/sudoku_functions.dart';
import 'package:sudoku/widgets/buttons/tool_button.dart';
import 'package:unicons/unicons.dart';

// ignore: must_be_immutable
class PausePlay extends StatefulWidget {
  PausePlay({required this.difficulty, super.key});
// ignore: prefer_typing_uninitialized_variables
  var difficulty;

  @override
  State<PausePlay> createState() => _PausePlayState();
}

class _PausePlayState extends State<PausePlay> {
  final SudokuPoints _pointsManager = SudokuPoints();
  List<List<int?>> _userFilledNumbers =
      List.generate(9, (_) => List<int?>.filled(9, null));

  late List<List<int?>> _sudokuGrid;
  late List<List<bool>> _userFilled;
  late List<List<List<int?>>> _userPencilMarks;
  late List<Map<String, dynamic>> _moveHistory;
  late List<int> _remainingNumbers;
  late Timer _timer;

  int? _selectedNumber;
  int? _selectedRow;
  int? _selectedCol;

  int _remainingHints = 0;
  int _mistakeCount = 0;
  int _secondsElapsed = 0;

  bool _isPencilActivated = false;
  bool _isPaused = false;

  bool _isGameWon() {
    return SudokuValidator(_sudokuGrid).isSudokuSolved();
  }

  @override
  void initState() {
    super.initState();
    _initializeState();
    _startTimer();
    _loadGameState();
    _loadTableState();
    _loadUserPencilMarks();
    _loadUserFilledNumbers();
  }

  Future<void> _loadTableState() async {
    try {
      List<List<int?>> loadedGrid = await GameStateManager.loadTableState();
      setState(() {
        _sudokuGrid = loadedGrid;
      });
    } catch (e) {
      debugPrint('Error loading Sudoku table state: $e');
    }
  }

  Future<void> _loadUserPencilMarks() async {
    try {
      List<List<List<int?>>> userPencilMarks =
          await GameStateManager.loadUserPencilMarks();
      setState(() {
        _userPencilMarks = userPencilMarks;
      });
    } catch (e) {
      debugPrint('Error loading user pencil marks: $e');
    }
  }

  Future<void> _loadGameState() async {
    try {
      Map<String, dynamic> gameState = await GameStateManager.loadGameState();
      setState(() {
        widget.difficulty = gameState['difficulty'] as String;
        _remainingHints = gameState['remainingHints'] as int;
        _mistakeCount = gameState['mistakeCount'] as int;
        _secondsElapsed = gameState['secondsElapsed'] as int;
      });
    } catch (e) {
      debugPrint('Error loading game state: $e');
    }
  }

  Future<void> _loadUserFilledNumbers() async {
    try {
      List<List<int?>> userFilledNumbers =
          await GameStateManager.loadUserFilledNumbers();
      setState(() {
        _userFilledNumbers = userFilledNumbers.cast<List<int?>>();
      });
    } catch (e) {
      debugPrint('Error loading user pencil marks: $e');
    }
  }

  void _handleGameWon() async {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return WinPage(
          totalTime: _formatTime(_secondsElapsed),
          difficultys: widget.difficulty,
          points: _pointsManager.points,
        );
      },
    );
  }

  void _initializeState() {
    _sudokuGrid = List.generate(9, (_) => List<int?>.filled(9, null));
    _userFilled = List.generate(9, (_) => List<bool>.filled(9, false));
    _userPencilMarks = List.generate(9, (_) => List.generate(9, (_) => []));
    _moveHistory = [];
    _remainingNumbers = List<int>.generate(9, (_) => 9);
  }

  void _togglePause() {
    setState(() {
      _isPaused = !_isPaused;
    });
  }

  @override
  void dispose() {
    super.dispose();
    _timer.cancel();
    GameStateManager.saveGameState(
      difficulty: widget.difficulty,
      remainingHints: _remainingHints,
      mistakeCount: _mistakeCount,
      secondsElapsed: _secondsElapsed,
    );
    GameStateManager.saveUserFilledNumbers(
        userFilledNumbers: _userFilledNumbers);

    GameStateManager.saveUserPencilMarks(userPencilMarks: _userPencilMarks);
  }

// Start the timer
  void _startTimer() {
    const oneSec = Duration(seconds: 1);
    _timer = Timer.periodic(oneSec, (Timer timer) {
      setState(() {
        if (!_isPaused) {
          _secondsElapsed++;
        }
      });
    });
  }

//time format
  String _formatTime(int seconds) {
    int minutes = seconds ~/ 60;
    int remainingSeconds = seconds % 60;
    String minutesStr = minutes < 10 ? '0$minutes' : '$minutes';
    String secondsStr =
        remainingSeconds < 10 ? '0$remainingSeconds' : '$remainingSeconds';
    return '$minutesStr:$secondsStr';
  }

//undo
  void _handleUndo() {
    if (_moveHistory.isNotEmpty) {
      setState(() {
        final lastMove = _moveHistory.removeLast();
        final row = lastMove['row'];
        final col = lastMove['col'];
        final prevValue = lastMove['prevValue'];

        _sudokuGrid[row][col] = prevValue;
        _userFilled[row][col] = prevValue == null ? false : true;

        _calculateRemainingNumbers();
      });
    }
  }

//eraser
  void _handleEraser() {
    SudokuFunctions.eraser(
        _sudokuGrid, _userFilled, _selectedRow, _selectedCol);
    setState(() {});
  }

//Pencil
  void handlePencil(int number) {
    if (_selectedRow != null && _selectedCol != null) {
      setState(() {
        if (_userPencilMarks[_selectedRow!][_selectedCol!].contains(number)) {
          _userPencilMarks[_selectedRow!][_selectedCol!].remove(number);
        } else {
          _userPencilMarks[_selectedRow!][_selectedCol!].add(number);
        }

        _selectedNumber = null;
      });
    }
  }

//hintt
  void _handleHint(BuildContext context) {
    if (_remainingHints > 0) {
      SudokuFunctions.hint(_sudokuGrid, _userFilled, context,
          (int row, int col, int number) {
        setState(() {
          _remainingHints--;
          _sudokuGrid[row][col] = number;
          _userFilled[row][col] = false;
        });
      });
    } else {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('No more hints available!'),
          duration: Duration(seconds: 1),
          backgroundColor: Colors.deepPurpleAccent,
        ),
      );
    }
  }

  void _calculateRemainingNumbers() {
    _remainingNumbers = List<int>.generate(9, (_) => 9);

    for (int row = 0; row < 9; row++) {
      for (int col = 0; col < 9; col++) {
        if (_sudokuGrid[row][col] != null) {
          _remainingNumbers[_sudokuGrid[row][col]! - 1]--;
        }
      }
    }
  }

  Widget _numTiles(BuildContext context, int index) {
    int row = index ~/ 9;
    int col = index % 9;
    int? value = _sudokuGrid[row][col];

    bool isSelected = _selectedRow != null &&
        _selectedCol != null &&
        (_selectedRow == row || _selectedCol == col);
    bool isInSelectedSubgrid = _selectedRow != null &&
        _selectedCol != null &&
        _isInSelectedSubgrid(row, col);
    bool isEditable = value == null || _userFilled[row][col];
    bool isWrongNumber = _userFilled[row][col] &&
        value != null &&
        !SudokuValidator(_sudokuGrid).isValidPlacement(row, col, value);

    bool hasUserPencilMarks = _userPencilMarks[row][col].isNotEmpty;

    Color? cellColor = isWrongNumber
        ? Colors.redAccent
        : isSelected || isInSelectedSubgrid
            ? Colors.deepPurple[100]
            : Colors.white;

    Color? textColor = isWrongNumber
        ? Colors.white
        : isSelected || isInSelectedSubgrid
            ? Colors.black
            : isEditable
                ? Colors.deepPurple[800]
                : Colors.black;

    if (_selectedRow == row && _selectedCol == col) {
      cellColor = Colors.deepPurpleAccent[100];
      textColor = Colors.white;
    }

    if (_selectedNumber != null && value == _selectedNumber) {
      cellColor = Colors.deepPurple[400];
      textColor = Colors.white;
    }

    if (!isEditable && hasUserPencilMarks) {
      _userPencilMarks[row][col] = [];
    }

    if (_userFilledNumbers[row][col] != null) {
      value = _userFilledNumbers[row][col];
      textColor = Colors.deepPurpleAccent; // Set value to user-filled number
    }

    return GestureDetector(
      onTap: isEditable
          ? () {
              setState(() {
                _selectedRow = row;
                _selectedCol = col;
                _selectedNumber = value;
              });
            }
          : null,
      child: Container(
        decoration: BoxDecoration(
          border: Border(
            top: BorderSide(
              color: Colors.deepPurple,
              width: _getBorderWidth(row, true),
            ),
            left: BorderSide(
              color: Colors.deepPurple,
              width: _getBorderWidth(col, false),
            ),
            right: col == 8
                ? const BorderSide(color: Colors.deepPurpleAccent, width: 1.0)
                : BorderSide.none,
            bottom: row == 8
                ? const BorderSide(color: Colors.deepPurpleAccent, width: 1.0)
                : BorderSide.none,
          ),
          color: cellColor,
        ),
        child: Stack(
          children: [
            Center(
              child: Text(
                '${value ?? ''}',
                style: TextStyle(
                  color: textColor,
                  fontFamily: 'PoppinsBold',
                  fontSize: 18.5,
                  fontWeight:
                      isWrongNumber ? FontWeight.bold : FontWeight.normal,
                ),
              ),
            ),
            if (isEditable && hasUserPencilMarks) _buildPencilMarks(row, col),
          ],
        ),
      ),
    );
  }

  Widget _buildPencilMarks(int row, int col) {
    bool isSelected = _selectedRow != null &&
        _selectedCol != null &&
        (_selectedRow == row || _selectedCol == col);
    return AspectRatio(
      aspectRatio: 1,
      child: Container(
        color: Colors.transparent,
        child: GridView.builder(
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
          ),
          itemBuilder: (context, index) {
            int number = index + 1;
            bool isUserPencil = _userPencilMarks[row][col].contains(number);
            return Center(
              child: Text(
                isUserPencil ? '$number' : '',
                style: TextStyle(
                  fontSize: 10,
                  color: isSelected ? Colors.white : Colors.deepPurpleAccent,
                  fontFamily: 'PoppinsBold',
                ),
              ),
            );
          },
          itemCount: 9,
          physics: const NeverScrollableScrollPhysics(),
        ),
      ),
    );
  }

  double _getBorderWidth(int position, bool isRow) {
    if ((position % 3 == 0 && position > 0)) {
      return 2.5;
    }
    return 1.0;
  }

  bool _isInSelectedSubgrid(int row, int col) {
    if (_selectedRow == null || _selectedCol == null) {
      return false;
    }

    int subgridStartRow = (_selectedRow! ~/ 3) * 3;
    int subgridStartCol = (_selectedCol! ~/ 3) * 3;

    return row >= subgridStartRow &&
        row < subgridStartRow + 3 &&
        col >= subgridStartCol &&
        col < subgridStartCol + 3;
  }

  void _updateCell(int number) async {
    if (_selectedRow != null && _selectedCol != null) {
      bool isValid = await SudokuValidator(_sudokuGrid)
          .validateCell(_selectedRow!, _selectedCol!, number);

      if (isValid) {
        _pointsManager.correctMove(); // Increment points for correct move
      } else {
        _pointsManager.wrongMove(); // Decrement points for wrong move
      }

      if (isValid) {
        _moveHistory.add({
          'row': _selectedRow!,
          'col': _selectedCol!,
          'prevValue': _sudokuGrid[_selectedRow!][_selectedCol!],
        });
      } else {
        _moveHistory.add({
          'row': _selectedRow!,
          'col': _selectedCol!,
          'prevValue': _sudokuGrid[_selectedRow!][_selectedCol!],
        });

        setState(() {
          _mistakeCount++;
        });
      }

      setState(() {
        if (isValid) {
          _sudokuGrid[_selectedRow!][_selectedCol!] = number;
          _userFilled[_selectedRow!][_selectedCol!] = false;
          _userFilledNumbers[_selectedRow!][_selectedCol!] = number;
        } else {
          _sudokuGrid[_selectedRow!][_selectedCol!] = number;
          _userFilled[_selectedRow!][_selectedCol!] = true;
          _userFilledNumbers[_selectedRow!][_selectedCol!];
        }

        _selectedRow = null;
        _selectedCol = null;
        _selectedNumber = null;
        _calculateRemainingNumbers();

        if (_isGameWon()) {
          _handleGameWon();
          _timer.cancel();
        }
      });

      if (!isValid) {
        // ignore: use_build_context_synchronously
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Wrong Sudoku move!'),
            duration: Duration(seconds: 1),
            backgroundColor: Colors.deepPurpleAccent,
          ),
        );
      }
    }
  }

  void _updateSelectedNumber(int number) {
    setState(() {
      _selectedNumber = _selectedNumber == number ? null : number;
    });
  }

  Widget _numberButton(int number) {
    return NumberButton(
      number: number,
      isPencilActivated: _isPencilActivated,
      selectedNumber: _selectedNumber,
      remainingNumbers: _remainingNumbers,
      handlePencil: handlePencil,
      updateSelectedNumber: _updateSelectedNumber,
      updateCell: _updateCell,
    );
  }

here is the code

I need to update the userfilled number from loadstate instead of displaying

0

There are 0 answers