Skip to content
Snippets Groups Projects
Commit db163e64 authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Improve game architecture

parent 64bb7efd
No related branches found
No related tags found
1 merge request!19Resolve "Improve game architecture"
Pipeline #5668 passed
Showing
with 866 additions and 153 deletions
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6ade70" stroke="#000" stroke-width="2"/><g transform="translate(-3 -15)"><g transform="translate(-204 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-252 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-252 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 60)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 60)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 60)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-288 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-288 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-288 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-276 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-276 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-276 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="288" y="24" width="12" height="12" fill="#babdb6" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><rect x="48" y="48" width="12" height="12" fill="#fff" stroke="#000"/><rect x="48" y="60" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 -100.3 35.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/><g transform="translate(-240 12)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g></g></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6ade70" stroke="#000" stroke-width="2"/><g transform="matrix(.84066 0 0 .84066 -95.275 -4.4834)"><g transform="translate(-168 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-168 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-168 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><rect x="168" y="60" width="12" height="12" fill="#babdb6" stroke="#000"/><g transform="translate(-120 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g></g></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#be6ade" stroke="#000" stroke-width="2"/></svg>
import 'package:solitaire/utils/tools.dart';
class DefaultGameSettings {
// available game parameters codes
static const String parameterCodeLayout = 'layout';
static const List<String> availableParameters = [
parameterCodeLayout,
];
// layout: available values
static const String layoutValueFrench = 'french';
static const String layoutValueGerman = 'german';
static const String layoutValueEnglish = 'english';
static const String layoutValueDiamond = 'diamond';
static const List<String> allowedLayoutValues = [
layoutValueFrench,
layoutValueGerman,
layoutValueEnglish,
layoutValueDiamond,
];
// layout: default value
static const String defaultLayoutValue = layoutValueEnglish;
static List<String> getAvailableValues(String parameterCode) {
switch (parameterCode) {
case parameterCodeLayout:
return DefaultGameSettings.allowedLayoutValues;
}
printlog('Did not find any available value for game parameter "$parameterCode".');
return [];
}
}
import 'package:solitaire/utils/tools.dart';
class DefaultGlobalSettings {
// available global parameters codes
static const String parameterCodeSkin = 'skin';
static const List<String> availableParameters = [
parameterCodeSkin,
];
// skin: available values
static const String skinValueDefault = 'default';
static const List<String> allowedSkinValues = [
skinValueDefault,
];
// skin: default value
static const String defaultSkinValue = skinValueDefault;
static List<String> getAvailableValues(String parameterCode) {
switch (parameterCode) {
case parameterCodeSkin:
return DefaultGlobalSettings.allowedSkinValues;
}
printlog('Did not find any available value for global parameter "$parameterCode".');
return [];
}
}
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:unicons/unicons.dart'; import 'package:unicons/unicons.dart';
import 'package:solitaire/ui/screens/about_page.dart'; import 'package:solitaire/ui/screens/page_about.dart';
import 'package:solitaire/ui/screens/game_page.dart'; import 'package:solitaire/ui/screens/page_game.dart';
import 'package:solitaire/ui/screens/settings_page.dart'; import 'package:solitaire/ui/screens/page_settings.dart';
class MenuItem { class MenuItem {
final String code; final String code;
...@@ -19,35 +18,39 @@ class MenuItem { ...@@ -19,35 +18,39 @@ class MenuItem {
} }
class Menu { class Menu {
static List<MenuItem> items = [ static const indexGame = 0;
const MenuItem( static const menuItemGame = MenuItem(
code: 'bottom_nav_home', code: 'bottom_nav_game',
icon: Icon(UniconsLine.home), icon: Icon(UniconsLine.home),
page: GamePage(), page: PageGame(),
), );
const MenuItem(
static const indexSettings = 1;
static const menuItemSettings = MenuItem(
code: 'bottom_nav_settings', code: 'bottom_nav_settings',
icon: Icon(UniconsLine.setting), icon: Icon(UniconsLine.setting),
page: SettingsPage(), page: PageSettings(),
), );
const MenuItem(
static const indexAbout = 2;
static const menuItemAbout = MenuItem(
code: 'bottom_nav_about', code: 'bottom_nav_about',
icon: Icon(UniconsLine.info_circle), icon: Icon(UniconsLine.info_circle),
page: AboutPage(), page: PageAbout(),
), );
];
static Widget getPageWidget(int pageIndex) { static Map<int, MenuItem> items = {
return Menu.items.elementAt(pageIndex).page; indexGame: menuItemGame,
indexSettings: menuItemSettings,
indexAbout: menuItemAbout,
};
static bool isIndexAllowed(int pageIndex) {
return items.keys.contains(pageIndex);
} }
static List<BottomNavigationBarItem> getMenuItems() { static Widget getPageWidget(int pageIndex) {
return Menu.items return items[pageIndex]?.page ?? menuItemGame.page;
.map((MenuItem item) => BottomNavigationBarItem(
icon: item.icon,
label: tr(item.code),
))
.toList();
} }
static int itemsCount = Menu.items.length; static int itemsCount = Menu.items.length;
......
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:solitaire/models/cell_location.dart';
import 'package:solitaire/models/game.dart';
import 'package:solitaire/models/settings_game.dart';
import 'package:solitaire/models/settings_global.dart';
import 'package:solitaire/utils/tools.dart';
part 'game_state.dart';
class GameCubit extends HydratedCubit<GameState> {
GameCubit()
: super(GameState(
currentGame: Game.createNull(),
));
void updateState(Game game) {
emit(GameState(
currentGame: game,
));
}
void refresh() {
final Game game = Game(
gameSettings: state.currentGame.gameSettings,
globalSettings: state.currentGame.globalSettings,
board: state.currentGame.board,
isRunning: state.currentGame.isRunning,
isFinished: state.currentGame.isFinished,
movesCount: state.currentGame.movesCount,
remainingPegsCount: state.currentGame.remainingPegsCount,
allowedMovesCount: state.currentGame.allowedMovesCount,
);
// game.dump();
updateState(game);
}
void startNewGame({
required GameSettings gameSettings,
required GlobalSettings globalSettings,
}) {
Game newGame = Game.createNew(
gameSettings: gameSettings,
globalSettings: globalSettings,
);
newGame.dump();
updateState(newGame);
updateRemainingPegsCount(newGame.countRemainingPegs());
updateAllowedMovesCount(newGame.countAllowedMoves());
refresh();
}
void quitGame() {
state.currentGame.isRunning = false;
refresh();
}
void updatePegValue(CellLocation location, bool hasPeg) {
state.currentGame.board.cells[location.row][location.col].hasPeg = hasPeg;
refresh();
}
void incrementMovesCount() {
state.currentGame.movesCount++;
refresh();
}
void updateRemainingPegsCount(int count) {
state.currentGame.remainingPegsCount = count;
refresh();
}
void updateAllowedMovesCount(int count) {
state.currentGame.allowedMovesCount = count;
if (count == 0) {
state.currentGame.isFinished = true;
}
refresh();
}
void move({
required Game currentGame,
required List<int> source,
required List<int> target,
}) {
printlog('Move from $source to $target');
final int sourceCol = source[0];
final int sourceRow = source[1];
final int targetCol = target[0];
final int targetRow = target[1];
final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
updatePegValue(CellLocation.go(sourceRow, sourceCol), false);
updatePegValue(CellLocation.go(targetRow, targetCol), true);
updatePegValue(CellLocation.go(middleRow, middleCol), false);
incrementMovesCount();
updateRemainingPegsCount(currentGame.countRemainingPegs());
updateAllowedMovesCount(currentGame.countAllowedMoves());
}
@override
GameState? fromJson(Map<String, dynamic> json) {
Game currentGame = json['currentGame'] as Game;
return GameState(
currentGame: currentGame,
);
}
@override
Map<String, dynamic>? toJson(GameState state) {
return <String, dynamic>{
'currentGame': state.currentGame.toJson(),
};
}
}
part of 'game_cubit.dart';
@immutable
class GameState extends Equatable {
const GameState({
required this.currentGame,
});
final Game currentGame;
@override
List<dynamic> get props => <dynamic>[
currentGame,
];
Map<String, dynamic> get values => <String, dynamic>{
'currentGame': currentGame,
};
}
...@@ -2,26 +2,32 @@ import 'package:hydrated_bloc/hydrated_bloc.dart'; ...@@ -2,26 +2,32 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:solitaire/config/menu.dart'; import 'package:solitaire/config/menu.dart';
class BottomNavCubit extends HydratedCubit<int> { class NavCubit extends HydratedCubit<int> {
BottomNavCubit() : super(0); NavCubit() : super(0);
void updateIndex(int index) { void updateIndex(int index) {
if (isIndexAllowed(index)) { if (Menu.isIndexAllowed(index)) {
emit(index); emit(index);
} else { } else {
goToHomePage(); goToGamePage();
} }
} }
bool isIndexAllowed(int index) { void goToGamePage() {
return (index >= 0) && (index < Menu.itemsCount); emit(Menu.indexGame);
} }
void goToHomePage() => emit(0); void goToSettingsPage() {
emit(Menu.indexSettings);
}
void goToAboutPage() {
emit(Menu.indexAbout);
}
@override @override
int fromJson(Map<String, dynamic> json) { int fromJson(Map<String, dynamic> json) {
return 0; return Menu.indexGame;
} }
@override @override
......
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:solitaire/config/default_game_settings.dart';
import 'package:solitaire/models/settings_game.dart';
import 'package:solitaire/utils/tools.dart';
part 'settings_game_state.dart';
class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
void setValues({
String? layout,
}) {
emit(
GameSettingsState(
settings: GameSettings(
layout: layout ?? state.settings.layout,
),
),
);
}
String getParameterValue(String code) {
switch (code) {
case DefaultGameSettings.parameterCodeLayout:
return GameSettings.getLayoutValueFromUnsafe(state.settings.layout);
}
return '';
}
void setParameterValue(String code, String value) {
printlog('GameSettingsCubit.setParameterValue');
printlog('code: $code / value: $value');
String layout = code == DefaultGameSettings.parameterCodeLayout
? value
: getParameterValue(DefaultGameSettings.parameterCodeLayout);
setValues(
layout: layout,
);
}
@override
GameSettingsState? fromJson(Map<String, dynamic> json) {
String layout = json[DefaultGameSettings.parameterCodeLayout] as String;
return GameSettingsState(
settings: GameSettings(
layout: layout,
),
);
}
@override
Map<String, dynamic>? toJson(GameSettingsState state) {
return <String, dynamic>{
DefaultGameSettings.parameterCodeLayout: state.settings.layout,
};
}
}
part of 'settings_game_cubit.dart';
@immutable
class GameSettingsState extends Equatable {
const GameSettingsState({
required this.settings,
});
final GameSettings settings;
@override
List<dynamic> get props => <dynamic>[
settings,
];
Map<String, dynamic> get values => <String, dynamic>{
'settings': settings,
};
}
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:solitaire/config/default_global_settings.dart';
import 'package:solitaire/models/settings_global.dart';
part 'settings_global_state.dart';
class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> {
GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault()));
void setValues({
String? skin,
}) {
emit(
GlobalSettingsState(
settings: GlobalSettings(
skin: skin ?? state.settings.skin,
),
),
);
}
String getParameterValue(String code) {
switch (code) {
case DefaultGlobalSettings.parameterCodeSkin:
return GlobalSettings.getSkinValueFromUnsafe(state.settings.skin);
}
return '';
}
void setParameterValue(String code, String value) {
final String skin = (code == DefaultGlobalSettings.parameterCodeSkin)
? value
: getParameterValue(DefaultGlobalSettings.parameterCodeSkin);
setValues(
skin: skin,
);
}
@override
GlobalSettingsState? fromJson(Map<String, dynamic> json) {
final String skin = json[DefaultGlobalSettings.parameterCodeSkin] as String;
return GlobalSettingsState(
settings: GlobalSettings(
skin: skin,
),
);
}
@override
Map<String, dynamic>? toJson(GlobalSettingsState state) {
return <String, dynamic>{
DefaultGlobalSettings.parameterCodeSkin: state.settings.skin,
};
}
}
part of 'settings_global_cubit.dart';
@immutable
class GlobalSettingsState extends Equatable {
const GlobalSettingsState({
required this.settings,
});
final GlobalSettings settings;
@override
List<dynamic> get props => <dynamic>[
settings,
];
Map<String, dynamic> get values => <String, dynamic>{
'settings': settings,
};
}
class GameData {
static const Map<String, List<String>> templates = {
'french': [
' ooo ',
' ooooo ',
'ooo·ooo',
'ooooooo',
'ooooooo',
' ooooo ',
' ooo ',
],
'german': [
' ooo ',
' ooo ',
' ooo ',
'ooooooooo',
'oooo·oooo',
'ooooooooo',
' ooo ',
' ooo ',
' ooo ',
],
'english': [
' ooo ',
' ooo ',
'ooooooo',
'ooo·ooo',
'ooooooo',
' ooo ',
' ooo ',
],
'diamond': [
' o ',
' ooo ',
' ooooo ',
' ooooooo ',
'oooo·oooo',
' ooooooo ',
' ooooo ',
' ooo ',
' o ',
]
};
}
import 'package:flutter/material.dart';
import 'package:solitaire/provider/data.dart';
import 'package:solitaire/utils/game_utils.dart';
class Tile {
int currentRow;
int currentCol;
bool hasPeg;
Tile(
this.currentRow,
this.currentCol,
this.hasPeg,
);
Widget render(Data myProvider) {
List<Widget> stack = [
hole(myProvider),
];
if (hasPeg) {
stack.add(draggable(myProvider));
}
return Stack(
alignment: Alignment.center,
children: stack,
);
}
Widget hole(Data myProvider) {
String image = 'assets/skins/${myProvider.parameterSkin}_hole.png';
return DragTarget<List<int>>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Image(
image: AssetImage(image),
width: myProvider.tileSize,
height: myProvider.tileSize,
fit: BoxFit.fill,
);
},
onAcceptWithDetails: (DragTargetDetails<List<int>> source) {
List<int> target = [currentCol, currentRow];
// printlog('(drag) Pick from ' + source.toString() + ' and drop on ' + target.toString());
if (GameUtils.isMoveAllowed(myProvider, source.data, target)) {
GameUtils.move(myProvider, source.data, target);
}
},
);
}
Widget draggable(Data myProvider) {
return Draggable<List<int>>(
data: [currentCol, currentRow],
// Widget when draggable is being dragged
feedback: peg(myProvider),
// Widget to display on original place when being dragged
childWhenDragging: Container(),
// Widget when draggable is stationary
child: peg(myProvider),
);
}
Widget peg(Data myProvider) {
String image = 'assets/skins/${myProvider.parameterSkin}_peg.png';
return Image(
image: AssetImage(image),
width: myProvider.tileSize,
height: myProvider.tileSize,
fit: BoxFit.fill,
);
}
}
...@@ -6,17 +6,17 @@ import 'package:flutter_bloc/flutter_bloc.dart'; ...@@ -6,17 +6,17 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:overlay_support/overlay_support.dart';
import 'package:solitaire/config/theme.dart'; import 'package:solitaire/config/theme.dart';
import 'package:solitaire/cubit/bottom_nav_cubit.dart'; import 'package:solitaire/cubit/game_cubit.dart';
import 'package:solitaire/cubit/nav_cubit.dart';
import 'package:solitaire/cubit/settings_game_cubit.dart';
import 'package:solitaire/cubit/settings_global_cubit.dart';
import 'package:solitaire/cubit/theme_cubit.dart'; import 'package:solitaire/cubit/theme_cubit.dart';
import 'package:solitaire/provider/data.dart';
import 'package:solitaire/ui/skeleton.dart'; import 'package:solitaire/ui/skeleton.dart';
void main() async { void main() async {
/// Initialize packages // Initialize packages
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized(); await EasyLocalization.ensureInitialized();
final Directory tmpDir = await getTemporaryDirectory(); final Directory tmpDir = await getTemporaryDirectory();
...@@ -46,17 +46,15 @@ class MyApp extends StatelessWidget { ...@@ -46,17 +46,15 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()), BlocProvider<NavCubit>(create: (context) => NavCubit()),
BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()), BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
BlocProvider<GameCubit>(create: (context) => GameCubit()),
BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
], ],
child: BlocBuilder<ThemeCubit, ThemeModeState>( child: BlocBuilder<ThemeCubit, ThemeModeState>(
builder: (BuildContext context, ThemeModeState state) { builder: (BuildContext context, ThemeModeState state) {
return ChangeNotifierProvider( return MaterialApp(
create: (BuildContext context) => Data(),
child: Consumer<Data>(
builder: (context, data, child) {
return OverlaySupport(
child: MaterialApp(
title: 'Solitaire', title: 'Solitaire',
home: const SkeletonScreen(), home: const SkeletonScreen(),
...@@ -70,10 +68,6 @@ class MyApp extends StatelessWidget { ...@@ -70,10 +68,6 @@ class MyApp extends StatelessWidget {
supportedLocales: context.supportedLocales, supportedLocales: context.supportedLocales,
locale: context.locale, locale: context.locale,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
),
);
},
),
); );
}, },
), ),
......
import 'package:solitaire/entities/tile.dart'; import 'package:solitaire/data/game_data.dart';
import 'package:solitaire/provider/data.dart'; import 'package:solitaire/models/cell.dart';
import 'package:solitaire/utils/board_utils.dart'; import 'package:solitaire/models/cell_location.dart';
import 'package:solitaire/models/settings_game.dart';
import 'package:solitaire/utils/tools.dart'; import 'package:solitaire/utils/tools.dart';
class GameUtils { typedef BoardCells = List<List<Cell>>;
static Future<void> quitGame(Data myProvider) async {
myProvider.updateGameIsRunning(false); class Board {
} Board({
required this.cells,
});
BoardCells cells = const [];
static Future<void> quitAndDeleteCurrentGame(Data myProvider) async { factory Board.createEmpty() {
quitGame(myProvider); return Board(
myProvider.resetCurrentSavedState(); cells: [],
);
} }
static Future<void> startNewGame(Data myProvider) async { factory Board.createNew({
printlog('Starting game'); required GameSettings gameSettings,
}) {
final List<String>? template = GameData.templates[gameSettings.layout];
BoardUtils.createNewBoard(myProvider); final BoardCells grid = [];
myProvider.updateGameIsRunning(true); int row = 0;
} template?.forEach((String line) {
final List<Cell> gridLine = [];
int col = 0;
line.split("").forEach((String tileCode) {
gridLine.add(tileCode == ' '
? Cell.none
: Cell(
location: CellLocation.go(row, col),
hasHole: true,
hasPeg: (tileCode == 'o'),
));
col++;
});
row++;
grid.add(gridLine);
});
static void deleteSavedGame(Data myProvider) { return Board(
myProvider.resetCurrentSavedState(); cells: grid,
);
} }
static void resumeSavedGame(Data myProvider) { int get boardSize => cells.length;
Map<String, dynamic> savedState = myProvider.getCurrentSavedState();
if (savedState.isNotEmpty) {
try {
myProvider.setParameterValue('layout', savedState['layout']);
myProvider.setParameterValue('skin', savedState['skin']);
myProvider.updateMovesCount(int.parse(savedState['movesCount']));
myProvider.updateBoard(
BoardUtils.createBoardFromSavedState(myProvider, savedState['boardValues']));
myProvider.updateGameIsRunning(true); Cell get(CellLocation location) {
} catch (e) { if (location.row < cells.length) {
printlog('Failed to resume game. Will start new one instead.'); if (location.col < cells[location.row].length) {
myProvider.resetCurrentSavedState(); return cells[location.row][location.col];
myProvider.initParametersValues();
startNewGame(myProvider);
} }
} else {
myProvider.resetCurrentSavedState();
myProvider.initParametersValues();
startNewGame(myProvider);
} }
return Cell.none;
} }
static bool isMoveAllowed(Data myProvider, List<int> source, List<int> target) { void set(CellLocation location, Cell cell) {
cells[location.row][location.col] = cell;
}
bool isMoveAllowed({
required List<int> source,
required List<int> target,
}) {
// printlog('(test) Pick from ' + source.toString() + ' and drop on ' + target.toString()); // printlog('(test) Pick from ' + source.toString() + ' and drop on ' + target.toString());
final Board board = myProvider.board;
final int sourceCol = source[0]; final int sourceCol = source[0];
final int sourceRow = source[1]; final int sourceRow = source[1];
final int targetCol = target[0]; final int targetCol = target[0];
...@@ -59,28 +77,28 @@ class GameUtils { ...@@ -59,28 +77,28 @@ class GameUtils {
// ensure source and target are inside range // ensure source and target are inside range
if (sourceRow < 0 || if (sourceRow < 0 ||
sourceRow > (myProvider.boardSize - 1) || sourceRow > (boardSize - 1) ||
sourceCol < 0 || sourceCol < 0 ||
sourceCol > (myProvider.boardSize - 1)) { sourceCol > (boardSize - 1)) {
// printlog('move forbidden: source is out of board'); // printlog('move forbidden: source is out of board');
return false; return false;
} }
if (targetRow < 0 || if (targetRow < 0 ||
targetRow > (myProvider.boardSize - 1) || targetRow > (boardSize - 1) ||
targetCol < 0 || targetCol < 0 ||
targetCol > (myProvider.boardSize - 1)) { targetCol > (boardSize - 1)) {
// printlog('move forbidden: target is out of board'); // printlog('move forbidden: target is out of board');
return false; return false;
} }
// ensure source exists and has a peg // ensure source exists and has a peg
if (board[sourceRow][sourceCol] == null || board[sourceRow][sourceCol]?.hasPeg == false) { if (cells[sourceRow][sourceCol].hasPeg == false) {
// printlog('move forbidden: source peg does not exist'); // printlog('move forbidden: source peg does not exist');
return false; return false;
} }
// ensure target exists and is empty // ensure target exists and is empty
if (board[targetRow][targetCol] == null || board[targetRow][targetCol]?.hasPeg == true) { if (cells[targetRow][targetCol].hasPeg == true) {
// printlog('move forbidden: target does not exist or already with a peg'); // printlog('move forbidden: target does not exist or already with a peg');
return false; return false;
} }
...@@ -101,7 +119,7 @@ class GameUtils { ...@@ -101,7 +119,7 @@ class GameUtils {
// ensure middle tile exists and has a peg // ensure middle tile exists and has a peg
final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round(); final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round(); final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
if (board[middleRow][middleCol] == null || board[middleRow][middleCol]?.hasPeg == false) { if (cells[middleRow][middleCol].hasPeg == false) {
// printlog('move forbidden: tile between source and target does not contain a peg'); // printlog('move forbidden: tile between source and target does not contain a peg');
return false; return false;
} }
...@@ -110,71 +128,42 @@ class GameUtils { ...@@ -110,71 +128,42 @@ class GameUtils {
return true; return true;
} }
static void move(Data myProvider, List<int> source, List<int> target) { void printGrid() {
printlog('Move from $source to $target'); String textBoard = ' ';
final int sourceCol = source[0]; String textHole = '·';
final int sourceRow = source[1]; String textPeg = 'o';
final int targetCol = target[0];
final int targetRow = target[1];
final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
// remove peg from source
myProvider.updatePegValue(sourceRow, sourceCol, false);
// put peg in target
myProvider.updatePegValue(targetRow, targetCol, true);
// remove peg from middle tile
myProvider.updatePegValue(middleRow, middleCol, false);
// increment moves count
myProvider.incrementMovesCount();
// update remaining pegs count
myProvider.updateRemainingPegsCount(GameUtils.countRemainingPegs(myProvider));
// update allowed moves count
myProvider.updateAllowedMovesCount(GameUtils.countAllowedMoves(myProvider));
}
static List<Tile> listRemainingPegs(Data myProvider) {
List<Tile> pegs = [];
Board board = myProvider.board; printlog('');
for (int rowIndex = 0; rowIndex < board.length; rowIndex++) { printlog('-------');
for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) { for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
Tile? tile = board[rowIndex][colIndex]; String row = '';
if (tile != null && tile.hasPeg == true) { for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
pegs.add(tile); String textCell = textBoard;
} Cell tile = cells[rowIndex][colIndex];
textCell = tile.hasPeg ? textPeg : textHole;
row += textCell;
} }
printlog(row);
} }
printlog('-------');
return pegs; printlog('');
} }
static int countRemainingPegs(Data myProvider) { void dump() {
return GameUtils.listRemainingPegs(myProvider).length; printlog('');
printlog('$Board:');
printGrid();
printlog('');
} }
static int countAllowedMoves(Data myProvider) { @override
int allowedMovesCount = 0; String toString() {
List<Tile> pegs = GameUtils.listRemainingPegs(myProvider); return '$Board(${toJson()})';
for (Tile tile in pegs) {
final int row = tile.currentRow;
final int col = tile.currentCol;
final List<int> source = [col, row];
final List<List<int>> targets = [
[col - 2, row],
[col + 2, row],
[col, row - 2],
[col, row + 2],
];
for (List<int> target in targets) {
if (GameUtils.isMoveAllowed(myProvider, source, target)) {
allowedMovesCount++;
}
}
} }
return allowedMovesCount; Map<String, dynamic>? toJson() {
return <String, dynamic>{
'cells': cells,
};
} }
} }
import 'package:solitaire/models/cell_location.dart';
import 'package:solitaire/utils/tools.dart';
class Cell {
Cell({
required this.location,
required this.hasHole,
required this.hasPeg,
});
final CellLocation location;
bool hasHole;
bool hasPeg;
static Cell none = Cell(
location: CellLocation.go(0, 0),
hasHole: false,
hasPeg: false,
);
void dump() {
printlog('$Cell:');
printlog(' location: $location');
printlog(' hasHole: $hasHole');
printlog(' hasPeg: $hasPeg');
printlog('');
}
@override
String toString() {
return '$Cell(${toJson()})';
}
Map<String, dynamic>? toJson() {
return <String, dynamic>{
'location': location,
'hasHole': hasHole,
'hasPeg': hasPeg,
};
}
}
import 'package:solitaire/utils/tools.dart';
class CellLocation {
final int col;
final int row;
CellLocation({
required this.col,
required this.row,
});
factory CellLocation.go(int row, int col) {
return CellLocation(col: col, row: row);
}
void dump() {
printlog('$CellLocation:');
printlog(' col: $col');
printlog(' row: $row');
printlog('');
}
@override
String toString() {
return '$CellLocation(${toJson()})';
}
Map<String, dynamic>? toJson() {
return <String, dynamic>{
'col': col,
'row': row,
};
}
}
import 'package:solitaire/models/board.dart';
import 'package:solitaire/models/cell.dart';
import 'package:solitaire/models/settings_game.dart';
import 'package:solitaire/models/settings_global.dart';
import 'package:solitaire/utils/tools.dart';
class Game {
Game({
required this.gameSettings,
required this.globalSettings,
required this.board,
this.isRunning = false,
this.isFinished = false,
this.movesCount = 0,
this.remainingPegsCount = 0,
this.allowedMovesCount = 0,
});
final GameSettings gameSettings;
final GlobalSettings globalSettings;
bool isRunning = false;
bool isFinished = false;
Board board;
int movesCount = 0;
int remainingPegsCount = 0;
int allowedMovesCount = 0;
factory Game.createNull() {
return Game(
gameSettings: GameSettings.createDefault(),
globalSettings: GlobalSettings.createDefault(),
board: Board.createEmpty(),
);
}
factory Game.createNew({
GameSettings? gameSettings,
GlobalSettings? globalSettings,
}) {
GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
return Game(
gameSettings: newGameSettings,
globalSettings: newGlobalSettings,
board: Board.createNew(
gameSettings: newGameSettings,
),
isRunning: true,
);
}
int get boardSize => board.boardSize;
bool get gameWon => (isFinished && (remainingPegsCount == 1));
List<Cell> listRemainingPegs() {
final List<Cell> pegs = [];
final BoardCells cells = board.cells;
for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
Cell tile = cells[rowIndex][colIndex];
if (tile.hasPeg == true) {
pegs.add(tile);
}
}
}
return pegs;
}
int countRemainingPegs() {
return listRemainingPegs().length;
}
int countAllowedMoves() {
int allowedMovesCount = 0;
final List<Cell> pegs = listRemainingPegs();
for (Cell tile in pegs) {
final int row = tile.location.row;
final int col = tile.location.col;
final List<int> source = [col, row];
final List<List<int>> targets = [
[col - 2, row],
[col + 2, row],
[col, row - 2],
[col, row + 2],
];
for (List<int> target in targets) {
if (board.isMoveAllowed(
source: source,
target: target,
)) {
allowedMovesCount++;
}
}
}
return allowedMovesCount;
}
void dump() {
printlog('');
printlog('## Current game dump:');
printlog('');
gameSettings.dump();
globalSettings.dump();
printlog('');
printlog('');
printlog('$Game: ');
printlog(' isRunning: $isRunning');
printlog(' isFinished: $isFinished');
printlog(' movesCount: $movesCount');
printlog(' remainingPegsCount: $remainingPegsCount');
printlog(' allowedMovesCount: $allowedMovesCount');
printlog('');
board.dump();
printlog('');
}
@override
String toString() {
return '$Game(${toJson()})';
}
Map<String, dynamic>? toJson() {
return <String, dynamic>{
'gameSettings': gameSettings.toJson(),
'globalSettings': globalSettings.toJson(),
'board': board.toJson(),
'isRunning': isRunning,
'isFinished': isFinished,
'movesCount': movesCount,
'remainingPegsCount': remainingPegsCount,
'allowedMovesCount': allowedMovesCount,
};
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment