Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • android/org.benoitharrault.sudoku
1 result
Show changes
Commits on Source (6)
Showing
with 462 additions and 165 deletions
image: ghcr.io/cirruslabs/flutter:latest
stages:
- update
- build-debug
- build-release
- release
- deploy
update:
stage: update
except:
- tags
script:
- flutter packages get
- flutter packages upgrade
interruptible: true
android:build-debug:
stage: build-debug
except:
- tags
- master
script:
# Flutter local configuration
- echo flutter.sdk=$FLUTTER_PATH > android/local.properties
......@@ -49,8 +40,6 @@ android:build-release:
- master
except:
- tags
dependencies:
- android:build-debug
script:
# Flutter local configuration
- echo flutter.sdk=$FLUTTER_PATH > android/local.properties
......@@ -121,4 +110,4 @@ android:deploy:
dependencies:
- application:release
script:
- curl "${REPOSITORY_UPDATE_WEBHOOK}?token=${REPOSITORY_TOKEN}"
- curl "${REPOSITORY_UPDATE_WEBHOOK}?token=${REPOSITORY_TOKEN}" --fail
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.1.15
app.versionCode=64
app.versionName=0.1.18
app.versionCode=67
Improve CI/CD, remove "update" step, disable "build-debug" in master branch.
Improve game architecture.
Add a timer after use of "help" button.
Amélioration de la CI/CD. Suppression de "update" et désactivation de "build-debug" sur master.
Amélioration de la conception du jeu.
Ajout d'une temporisation pour réactiver le bouton "aide" après usage.
......@@ -5,27 +5,30 @@ import 'package:sudoku/utils/board_animate.dart';
import 'package:sudoku/utils/board_utils.dart';
class Cell {
int value;
bool isFixed;
int conflictsCount = 0;
const Cell({
required this.row,
required this.col,
required this.value,
required this.isFixed,
});
bool isAnimated = false;
final int row;
final int col;
final int value;
final bool isFixed;
Cell(
this.value,
this.isFixed,
);
static const Cell none = Cell(row: 0, col: 0, value: 0, isFixed: true);
/*
* Build widget for board cell, with interactions
*/
Container widget(Data myProvider, int row, int col) {
Widget widget(Data myProvider) {
final String imageAsset = getImageAssetName(myProvider);
return Container(
decoration: BoxDecoration(
color: getBackgroundColor(myProvider),
border: getCellBorders(myProvider, row, col),
border: getCellBorders(myProvider),
),
child: GestureDetector(
child: AnimatedSwitcher(
......@@ -40,7 +43,7 @@ class Cell {
),
),
onTap: () {
if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) {
if (col != myProvider.selectedCellCol || row != myProvider.selectedCellRow) {
myProvider.selectCell(col, row);
} else {
myProvider.selectCell(null, null);
......@@ -62,14 +65,14 @@ class Cell {
Color backgroundColor = Colors.grey.shade200;
if (myProvider.showConflicts &&
myProvider.currentCellCol != null &&
myProvider.currentCellRow != null) {
final List<List<Cell>> cells = myProvider.cells;
myProvider.selectedCellCol != null &&
myProvider.selectedCellRow != null) {
final Board cells = myProvider.board;
final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
final int blockSizeVertical = myProvider.blockSizeVertical;
if (!BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical,
myProvider.currentCellCol, myProvider.currentCellRow, value)) {
myProvider.selectedCellCol, myProvider.selectedCellRow, value)) {
backgroundColor = Colors.pink.shade100;
}
}
......@@ -85,9 +88,9 @@ class Cell {
child: GestureDetector(
child: Image(image: AssetImage(imageAsset), fit: BoxFit.fill),
onTap: () {
if (myProvider.currentCellCol != null && myProvider.currentCellRow != null) {
if (myProvider.selectedCellCol != null && myProvider.selectedCellRow != null) {
myProvider.updateCellValue(
myProvider.currentCellCol, myProvider.currentCellRow, value);
myProvider.selectedCellCol, myProvider.selectedCellRow, value);
}
myProvider.selectCell(null, null);
if (BoardUtils.checkBoardIsSolved(myProvider)) {
......@@ -126,6 +129,8 @@ class Cell {
backgroundColor = fixedCellColor;
}
final int conflictsCount = myProvider.boardConflicts[row][col];
if (myProvider.showConflicts && (conflictsCount != 0)) {
if (isFixed) {
backgroundColor = fixedCellColorConflict;
......@@ -134,7 +139,7 @@ class Cell {
}
}
if (myProvider.showConflicts && (value == myProvider.currentCellValue)) {
if (myProvider.showConflicts && (value == myProvider.selectedCellValue)) {
if (isFixed) {
backgroundColor = fixedSelectedValueColor;
} else {
......@@ -142,6 +147,8 @@ class Cell {
}
}
final bool isAnimated = myProvider.boardAnimated[row][col];
if (isAnimated) {
if (isFixed) {
backgroundColor = fixedAnimated;
......@@ -154,7 +161,9 @@ class Cell {
}
// Compute cell borders, from board size and cell state
Border getCellBorders(Data myProvider, int row, int col) {
Border getCellBorders(Data myProvider) {
// final int row = , int col;
final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
final int blockSizeVertical = myProvider.blockSizeVertical;
......@@ -184,7 +193,7 @@ class Cell {
);
// Update cell borders if not currently selected cell
if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) {
if (col != myProvider.selectedCellCol || row != myProvider.selectedCellRow) {
borders = Border(
top: BorderSide(
width: cellBorderWidth,
......
......@@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
import 'package:overlay_support/overlay_support.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/screens/home.dart';
import 'package:sudoku/ui/screens/home.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
......@@ -27,9 +27,6 @@ class MyApp extends StatelessWidget {
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const Home(),
routes: {
Home.id: (context) => const Home(),
},
),
);
}),
......
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
......@@ -6,6 +7,11 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:sudoku/entities/cell.dart';
import 'package:sudoku/utils/tools.dart';
typedef Board = List<List<Cell>>;
typedef ConflictsCount = List<List<int>>;
typedef AnimatedBoard = List<List<bool>>;
typedef AnimatedBoardSequence = List<AnimatedBoard>;
class Data extends ChangeNotifier {
// Configuration available values
final List<String> _availableParameters = ['level', 'size', 'skin'];
......@@ -39,15 +45,18 @@ class Data extends ChangeNotifier {
bool _animationInProgress = false;
int _blockSizeVertical = 0;
int _blockSizeHorizontal = 0;
List<List<Cell>> _cells = [];
List<List<Cell>> _cellsSolved = [];
Board _board = [];
Board _boardSolved = [];
ConflictsCount _boardConflicts = [];
AnimatedBoard _boardAnimated = [];
List<int> _shuffledCellValues = [];
int? _currentCellCol;
int? _currentCellRow;
int? _currentCellValue;
int? _selectedCellCol;
int? _selectedCellRow;
int? _selectedCellValue;
bool _showConflicts = false;
int _givenTipsCount = 0;
String _currentState = '';
int _givenTipsCountEnableCountdown = 0;
String _currentSavedState = '';
void updateParameterLevel(String parameterLevel) {
_parameterLevel = parameterLevel;
......@@ -115,15 +124,15 @@ class Data extends ChangeNotifier {
setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault);
}
String get currentState => _currentState;
String get currentSavedState => _currentSavedState;
String computeCurrentGameState() {
String cellsValues = '';
const String stringValues = '0123456789ABCDEFG';
for (int rowIndex = 0; rowIndex < _cells.length; rowIndex++) {
for (int colIndex = 0; colIndex < _cells[rowIndex].length; colIndex++) {
cellsValues += stringValues[_cells[rowIndex][colIndex].value];
cellsValues += _cells[rowIndex][colIndex].isFixed ? 'x' : ' ';
for (int rowIndex = 0; rowIndex < _board.length; rowIndex++) {
for (int colIndex = 0; colIndex < _board[rowIndex].length; colIndex++) {
cellsValues += stringValues[_board[rowIndex][colIndex].value];
cellsValues += _board[rowIndex][colIndex].isFixed ? 'x' : ' ';
}
}
......@@ -140,35 +149,35 @@ class Data extends ChangeNotifier {
void saveCurrentGameState() async {
if (_gameIsRunning) {
_currentState = computeCurrentGameState();
_currentSavedState = computeCurrentGameState();
final prefs = await SharedPreferences.getInstance();
prefs.setString('savedState', _currentState);
prefs.setString('savedState', _currentSavedState);
} else {
resetCurrentSavedState();
}
}
void resetCurrentSavedState() async {
_currentState = '';
_currentSavedState = '';
final prefs = await SharedPreferences.getInstance();
prefs.setString('savedState', _currentState);
prefs.setString('savedState', _currentSavedState);
notifyListeners();
}
void loadCurrentSavedState() async {
final prefs = await SharedPreferences.getInstance();
_currentState = prefs.getString('savedState') ?? '';
_currentSavedState = prefs.getString('savedState') ?? '';
}
bool hasCurrentSavedState() {
return (_currentState != '');
return (_currentSavedState != '');
}
Map<String, dynamic> getCurrentSavedState() {
if (_currentState != '') {
Map<String, dynamic> savedState = json.decode(_currentState);
if (_currentSavedState != '') {
Map<String, dynamic> savedState = json.decode(_currentSavedState);
if (savedState.isNotEmpty) {
return savedState;
}
......@@ -187,17 +196,20 @@ class Data extends ChangeNotifier {
_assetsPreloaded = assetsPreloaded;
}
List<List<Cell>> get cells => _cells;
void updateCells(List<List<Cell>> cells) {
_cells = cells;
Board get board => _board;
void updateCells(Board board) {
_board = board;
notifyListeners();
}
List<List<Cell>> get cellsSolved => _cellsSolved;
void updateCellsSolved(List<List<Cell>> cells) {
_cellsSolved = cells;
Board get boardSolved => _boardSolved;
void updateCellsSolved(Board boardSolved) {
_boardSolved = boardSolved;
}
AnimatedBoard get boardAnimated => _boardAnimated;
ConflictsCount get boardConflicts => _boardConflicts;
void shuffleCellValues() {
const int maxCellValue = 16;
final List<int> values = List<int>.generate(maxCellValue, (i) => i + 1);
......@@ -218,56 +230,100 @@ class Data extends ChangeNotifier {
return _shuffledCellValues[originalValue - 1];
}
int? get currentCellCol => _currentCellCol;
set updateCurrentCellCol(int? currentCellCol) {
_currentCellCol = currentCellCol;
int? get selectedCellCol => _selectedCellCol;
set updateCelectedCellCol(int? selectedCellCol) {
_selectedCellCol = selectedCellCol;
notifyListeners();
}
int? get currentCellRow => _currentCellRow;
set updateCurrentCellRow(int? currentCellRow) {
_currentCellRow = currentCellRow;
int? get selectedCellRow => _selectedCellRow;
set updateSelectedCellRow(int? selectedCellRow) {
_selectedCellRow = selectedCellRow;
notifyListeners();
}
int? get currentCellValue => _currentCellValue;
set updateCurrentCellValue(int? currentCellValue) {
_currentCellValue = currentCellValue;
int? get selectedCellValue => _selectedCellValue;
set updateSelectedCellValue(int? selectedCellValue) {
_selectedCellValue = selectedCellValue;
notifyListeners();
}
int get givenTipsCountEnableCountdown => _givenTipsCountEnableCountdown;
int get givenTipsCount => _givenTipsCount;
increaseGivenTipsCount() {
void increaseGivenTipsCount() {
_givenTipsCount = _givenTipsCount + 1;
_givenTipsCountEnableCountdown = 60;
const Duration interval = Duration(milliseconds: 500);
Timer.periodic(
interval,
(Timer timer) {
if (_givenTipsCountEnableCountdown == 0) {
timer.cancel();
notifyListeners();
} else {
_givenTipsCountEnableCountdown--;
notifyListeners();
}
},
);
saveCurrentGameState();
notifyListeners();
}
setGivenTipsCount(int value) {
void setGivenTipsCount(int value) {
_givenTipsCount = value;
_givenTipsCountEnableCountdown = 0;
notifyListeners();
}
resetGivenTipsCount() {
bool canGiveTip() {
return (_givenTipsCountEnableCountdown == 0);
}
void resetGivenTipsCount() {
setGivenTipsCount(0);
}
selectCell(int? col, int? row) {
_currentCellCol = col;
_currentCellRow = row;
_currentCellValue = null;
void selectCell(int? col, int? row) {
_selectedCellCol = col;
_selectedCellRow = row;
_selectedCellValue = null;
if (row != null && col != null) {
if (_cells[row][col].value != 0) {
_currentCellValue = _cells[row][col].value;
if (_board[row][col].value != 0) {
_selectedCellValue = _board[row][col].value;
}
}
notifyListeners();
}
updateCellValue(int? col, int? row, int value) {
void initConflictsBoard() {
ConflictsCount nonConflictedBoard = [];
final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
for (int row = 0; row < boardSideLength; row++) {
List<int> line = [];
for (int col = 0; col < boardSideLength; col++) {
line.add(0);
}
nonConflictedBoard.add(line);
}
_boardConflicts = nonConflictedBoard;
}
void updateConflicts(ConflictsCount conflictsCount) {
_boardConflicts = conflictsCount;
}
void updateCellValue(int? col, int? row, int value) {
if ((col != null) && (row != null)) {
if (!_cells[row][col].isFixed) {
_cells[row][col].value = value;
if (!_board[row][col].isFixed) {
_board[row][col] = Cell(
row: row,
col: col,
value: value,
isFixed: false,
);
saveCurrentGameState();
notifyListeners();
......@@ -292,11 +348,24 @@ class Data extends ChangeNotifier {
notifyListeners();
}
void initAnimatedBackground() {
AnimatedBoard staticBoard = [];
final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
for (int row = 0; row < boardSideLength; row++) {
List<bool> line = [];
for (int col = 0; col < boardSideLength; col++) {
line.add(false);
}
staticBoard.add(line);
}
_boardAnimated = staticBoard;
}
void setAnimatedBackground(List animatedCellsPattern) {
final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
for (int row = 0; row < boardSideLength; row++) {
for (int col = 0; col < boardSideLength; col++) {
_cells[row][col].isAnimated = animatedCellsPattern[row][col];
_boardAnimated[row][col] = animatedCellsPattern[row][col];
}
}
notifyListeners();
......@@ -306,7 +375,7 @@ class Data extends ChangeNotifier {
final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
for (int row = 0; row < boardSideLength; row++) {
for (int col = 0; col < boardSideLength; col++) {
_cells[row][col].isAnimated = false;
_boardAnimated[row][col] = false;
}
}
}
......
import 'package:flutter/material.dart';
import 'package:sudoku/entities/cell.dart';
import 'package:sudoku/provider/data.dart';
class Board {
static Container buildGameBoard(Data myProvider) {
class BoardLayout extends StatelessWidget {
const BoardLayout({super.key, required this.myProvider});
final Data myProvider;
@override
Container build(BuildContext context) {
const Color borderColor = Colors.black;
final int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
final Widget gameTileset = Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
for (int row = 0; row < boardSize; row++)
TableRow(
children: [
for (int col = 0; col < boardSize; col++)
Column(
children: [myProvider.board[row][col].widget(myProvider)],
),
],
),
],
);
return Container(
margin: const EdgeInsets.all(2),
......@@ -20,22 +40,9 @@ class Board {
),
child: Column(
children: [
buildGameTileset(myProvider),
gameTileset,
],
),
);
}
static Widget buildGameTileset(Data myProvider) {
final int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
final List<List<Cell>> cells = myProvider.cells;
return Table(defaultColumnWidth: const IntrinsicColumnWidth(), children: [
for (int row = 0; row < boardSize; row++)
TableRow(children: [
for (int col = 0; col < boardSize; col++)
Column(children: [cells[row][col].widget(myProvider, row, col)]),
]),
]);
}
}
import 'package:flutter/material.dart';
import 'package:sudoku/ui/layout/board.dart';
import 'package:sudoku/ui/widgets/message_game_end.dart';
import 'package:sudoku/ui/widgets/bar_select_cell_value.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/utils/board_utils.dart';
class Game extends StatelessWidget {
const Game({super.key, required this.myProvider});
final Data myProvider;
@override
Widget build(BuildContext context) {
final bool gameIsFinished = BoardUtils.checkBoardIsSolved(myProvider);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BoardLayout(myProvider: myProvider),
const SizedBox(height: 2),
gameIsFinished
? EndGameMessage(myProvider: myProvider)
: SelectCellValueBar(myProvider: myProvider),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/utils/game_utils.dart';
import 'package:sudoku/ui/widgets/button_game_resume.dart';
import 'package:sudoku/ui/widgets/button_game_start_new.dart';
class Parameters extends StatelessWidget {
const Parameters({super.key, required this.myProvider});
final Data myProvider;
class Parameters {
static const double separatorHeight = 2.0;
static const double blockMargin = 3.0;
static const double blockPadding = 2.0;
......@@ -15,7 +20,8 @@ class Parameters {
static const double buttonPadding = 0.0;
static const double buttonMargin = 0.0;
static Widget buildParametersSelector(Data myProvider) {
@override
Widget build(BuildContext context) {
List<Widget> lines = [];
List<String> parameters = myProvider.availableParameters;
......@@ -26,8 +32,8 @@ class Parameters {
myProvider.loadCurrentSavedState();
Widget buttonsBlock = myProvider.hasCurrentSavedState()
? buildResumeGameButton(myProvider)
: buildStartNewGameButton(myProvider);
? ResumeGameButton(myProvider: myProvider)
: StartNewGameButton(myProvider: myProvider);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
......@@ -73,66 +79,7 @@ class Parameters {
);
}
static Container buildStartNewGameButton(Data myProvider) {
return Container(
margin: const EdgeInsets.all(blockMargin),
padding: const EdgeInsets.all(blockPadding),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
buildDecorationImageWidget(),
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_start'),
onPressed: () => GameUtils.startNewGame(myProvider),
),
],
),
buildDecorationImageWidget(),
],
),
],
),
);
}
static Container buildResumeGameButton(Data myProvider) {
return Container(
margin: const EdgeInsets.all(blockMargin),
padding: const EdgeInsets.all(blockPadding),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_delete_saved_game'),
onPressed: () => GameUtils.deleteSavedGame(myProvider),
),
],
),
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_resume_game'),
onPressed: () => GameUtils.resumeSavedGame(myProvider),
),
],
),
buildDecorationImageWidget(),
],
),
],
),
);
}
static Widget buildParameterSelector(Data myProvider, String parameterCode) {
Widget buildParameterSelector(Data myProvider, String parameterCode) {
List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode);
if (availableValues.length == 1) {
......@@ -156,8 +103,7 @@ class Parameters {
);
}
static Widget _buildParameterButton(
Data myProvider, String parameterCode, String parameterValue) {
Widget _buildParameterButton(Data myProvider, String parameterCode, String parameterValue) {
String currentValue = myProvider.getParameterValue(parameterCode).toString();
bool isActive = (parameterValue == currentValue);
......
......@@ -3,14 +3,12 @@ import 'package:provider/provider.dart';
import 'package:badges/badges.dart' as badges;
import 'package:overlay_support/overlay_support.dart';
import 'package:sudoku/layout/game.dart';
import 'package:sudoku/layout/parameters.dart';
import 'package:sudoku/ui/layout/game.dart';
import 'package:sudoku/ui/layout/parameters.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/utils/game_utils.dart';
class Home extends StatefulWidget {
static const String id = 'home';
const Home({super.key});
@override
......@@ -69,7 +67,7 @@ class HomeState extends State<Home> {
final Data myProvider = Provider.of<Data>(context);
if (!myProvider.assetsPreloaded) {
List<String> assets = getImagesAssets(myProvider);
final List<String> assets = getImagesAssets(myProvider);
for (String asset in assets) {
precacheImage(AssetImage(asset), context);
}
......@@ -119,13 +117,16 @@ class HomeState extends State<Home> {
myProvider.givenTipsCount == 0 ? '' : myProvider.givenTipsCount.toString(),
style: const TextStyle(color: Colors.white),
),
child: const Image(
image: AssetImage('assets/icons/button_help.png'),
fit: BoxFit.fill,
child: Container(
padding: EdgeInsets.all(myProvider.givenTipsCountEnableCountdown / 4),
child: const Image(
image: AssetImage('assets/icons/button_help.png'),
fit: BoxFit.fill,
),
),
),
),
onPressed: () => GameUtils.showTip(myProvider),
onPressed: () => myProvider.canGiveTip() ? GameUtils.showTip(myProvider) : null,
));
menuActions.add(const Spacer());
menuActions.add(TextButton(
......@@ -155,8 +156,8 @@ class HomeState extends State<Home> {
body: SafeArea(
child: Center(
child: myProvider.gameIsRunning
? Game.buildGameWidget(myProvider)
: Parameters.buildParametersSelector(myProvider),
? Game(myProvider: myProvider)
: Parameters(myProvider: myProvider),
),
),
);
......
......@@ -3,35 +3,21 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:sudoku/entities/cell.dart';
import 'package:sudoku/layout/board.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/utils/board_utils.dart';
import 'package:sudoku/utils/game_utils.dart';
class Game {
static Widget buildGameWidget(Data myProvider) {
final bool gameIsFinished = BoardUtils.checkBoardIsSolved(myProvider);
class SelectCellValueBar extends StatelessWidget {
const SelectCellValueBar({super.key, required this.myProvider});
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Board.buildGameBoard(myProvider),
const SizedBox(height: 2),
gameIsFinished
? Game.buildEndGameMessage(myProvider)
: Game.buildSelectCellValueBar(myProvider),
],
);
}
final Data myProvider;
static Container buildSelectCellValueBar(Data myProvider) {
final List<List<Cell>> cells = myProvider.cells;
@override
Widget build(BuildContext context) {
final Board cells = myProvider.board;
final bool isCellSelected =
(myProvider.currentCellCol != null && myProvider.currentCellRow != null);
(myProvider.selectedCellCol != null && myProvider.selectedCellRow != null);
final bool isUpdatableCellSelected = isCellSelected
? !cells[myProvider.currentCellRow ?? 0][myProvider.currentCellCol ?? 0].isFixed
? !cells[myProvider.selectedCellRow ?? 0][myProvider.selectedCellCol ?? 0].isFixed
: false;
final int maxValue = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
......@@ -53,9 +39,12 @@ class Game {
value++)
Column(
children: [
Cell(isUpdatableCellSelected ? (value <= maxValue ? value : -1) : -1,
false)
.widgetUpdateValue(myProvider)
Cell(
row: 1,
col: value,
value: isUpdatableCellSelected ? (value <= maxValue ? value : -1) : -1,
isFixed: false,
).widgetUpdateValue(myProvider)
],
),
],
......@@ -64,48 +53,4 @@ class Game {
),
);
}
static Widget buildRestartGameButton(Data myProvider) {
return TextButton(
child: const Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill,
),
onPressed: () => GameUtils.quitGame(myProvider),
);
}
static Container buildEndGameMessage(Data myProvider) {
const Image decorationImage = Image(
image: AssetImage('assets/icons/game_win.png'),
fit: BoxFit.fill,
);
return Container(
margin: const EdgeInsets.all(2),
padding: const EdgeInsets.all(2),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
const Column(
children: [decorationImage],
),
Column(
children: [
myProvider.animationInProgress
? decorationImage
: buildRestartGameButton(myProvider)
],
),
const Column(
children: [decorationImage],
),
],
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/utils/game_utils.dart';
class RestartGameButton extends StatelessWidget {
const RestartGameButton({super.key, required this.myProvider});
final Data myProvider;
@override
Widget build(BuildContext context) {
return TextButton(
child: const Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill,
),
onPressed: () => GameUtils.quitGame(myProvider),
);
}
}
import 'package:flutter/material.dart';
import 'package:sudoku/ui/layout/parameters.dart';
import 'package:sudoku/utils/game_utils.dart';
class ResumeGameButton extends Parameters {
const ResumeGameButton({super.key, required super.myProvider});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(Parameters.blockMargin),
padding: const EdgeInsets.all(Parameters.blockPadding),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Column(
children: [
TextButton(
child: Parameters.buildImageContainerWidget('button_delete_saved_game'),
onPressed: () => GameUtils.deleteSavedGame(myProvider),
),
],
),
Column(
children: [
TextButton(
child: Parameters.buildImageContainerWidget('button_resume_game'),
onPressed: () => GameUtils.resumeSavedGame(myProvider),
),
],
),
Parameters.buildDecorationImageWidget(),
],
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:sudoku/provider/data.dart';
import 'package:sudoku/ui/layout/parameters.dart';
import 'package:sudoku/utils/game_utils.dart';
class StartNewGameButton extends StatelessWidget {
const StartNewGameButton({super.key, required this.myProvider});
final Data myProvider;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(Parameters.blockMargin),
padding: const EdgeInsets.all(Parameters.blockPadding),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Parameters.buildDecorationImageWidget(),
Column(
children: [
TextButton(
child: Parameters.buildImageContainerWidget('button_start'),
onPressed: () => GameUtils.startNewGame(myProvider),
),
],
),
Parameters.buildDecorationImageWidget(),
],
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:sudoku/ui/widgets/button_game_restart.dart';
import 'package:sudoku/provider/data.dart';
class EndGameMessage extends StatelessWidget {
const EndGameMessage({super.key, required this.myProvider});
final Data myProvider;
@override
Widget build(BuildContext context) {
const Image decorationImage = Image(
image: AssetImage('assets/icons/game_win.png'),
fit: BoxFit.fill,
);
return Container(
margin: const EdgeInsets.all(2),
padding: const EdgeInsets.all(2),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
const Column(
children: [decorationImage],
),
Column(
children: [
myProvider.animationInProgress
? decorationImage
: RestartGameButton(myProvider: myProvider)
],
),
const Column(
children: [decorationImage],
),
],
),
],
),
);
}
}