app/src/main/java/de/tobiasbielefeld/solitaire/helper/Sounds.java
public class Sounds {

    public enum names {CARD_RETURN, CARD_SET, HINT, DEAL_CARDS, SHOW_AUTOCOMPLETE}

    private SoundPool sp;// = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
    private int[] soundList = new int[9];

    public Sounds(Context context) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            createNewSoundPool();
        } else {
            createOldSoundPool();
        }

        loadSounds(context);
    }

    public void playSound(names name) {

        if (prefs.getSavedSoundEnabled() && !SharedData.stopUiUpdates) {
            switch (name) {
                case CARD_RETURN:
                    sp.play(soundList[0], 1, 1, 0, 0, 1);
                    break;
                case CARD_SET:
                    sp.play(soundList[1], 1, 1, 0, 0, 1);
                    break;
                case HINT:
                    sp.play(soundList[2], 1, 1, 0, 0, 1);
                    break;
                case DEAL_CARDS:
                    sp.play(soundList[3], 1, 1, 0, 0, 1);
                    break;
                case SHOW_AUTOCOMPLETE:
                    sp.play(soundList[4], 1, 1, 0, 0, 1);
                    break;
            }
        }
    }

    public void playWinSound() {
        if (prefs.getSavedSoundEnabled()) {
            switch (prefs.getSavedWinSound()) {
                case "0":
                    sp.play(soundList[5], 1, 1, 0, 0, 1);
                    break;
                case "1":
                    sp.play(soundList[6], 1, 1, 0, 0, 1);
                    break;
                case "2":
                    sp.play(soundList[7], 1, 1, 0, 0, 1);
                    break;
                case "3":
                    sp.play(soundList[8], 1, 1, 0, 0, 1);
                    break;
            }
        }
    }

    private void loadSounds(Context context) {
        soundList[0] = sp.load(context, R.raw.card_return, 1);
        soundList[1] = sp.load(context, R.raw.card_set, 1);
        soundList[2] = sp.load(context, R.raw.hint, 1);
        soundList[3] = sp.load(context, R.raw.deal_cards, 1);
        soundList[4] = sp.load(context, R.raw.show_autocomplete, 1);

        soundList[5] = sp.load(context, R.raw.win_1, 1);
        soundList[6] = sp.load(context, R.raw.win_2, 1);
        soundList[7] = sp.load(context, R.raw.win_3, 1);
        soundList[8] = sp.load(context, R.raw.win_4, 1);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    protected void createNewSoundPool() {
        AudioAttributes attributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_GAME)
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .build();
        sp = new SoundPool.Builder()
                .setAudioAttributes(attributes)
                .build();
    }

    @SuppressWarnings("deprecation")
    protected void createOldSoundPool() {
        sp = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
    }

}
app/src/main/java/de/tobiasbielefeld/solitaire/classes/Card.java
public class Card {

    public enum movements {INSTANT, NONE, DEFAULT}

    public static int width, height;                      //width and height calculated in relation of the screen dimensions in Main activity
    public static Bitmap background;
    private static Bitmap[] drawables = new Bitmap[52];
    public CustomImageView view;                          //the image view of the card, for easier code not private
    private int color;                                    //1=clubs 2=hearts 3=Spades 4=diamonds
    private int value;                                    //1=ace 2,3,4,5,6,7,8,9,10, 11=joker 12=queen 13=king
    private Stack stack;                                  //saves the stack where the card is placed
    private int id;                                       //internal id
    private boolean isUp;                                 //indicates if the card is placed upwards or backwards
    private boolean isInvisible;
    private PointF oldLocation = new PointF();            //old location so cards can be moved back if they can't placed on a new stack

    public static int ACE = 1;
    public static int JOKER = 11;
    public static int QUEEN = 12;
    public static int KING = 13;

    //no enum, I want to explicitly set the values, because they are saved in the sharedPref and
    private static final int STATE_FACED_DOWN = 0;
    public static final int STATE_FACED_UP = 1;
    public static final int STATE_INVISIBLE = 2;

    /**
     * Sets id, color and value. The cards are initialized at game start with a for loop.
     * <p>
     * The color range is 1 to 4 and depends on the cardDrawableOrder, which is set to
     * 1 for the first 13 cards, 2 for the following 13 cards and so on.
     * After 52 cards (= one deck) it repeats. The value range is from 1 to 13 (= Ace to King).
     *
     * @param id The position in the cards array
     */
    public Card(int id) {
        this.id = id;
        color = currentGame.cardDrawablesOrder[(id % 52) / 13];
        value = (id % 13) + 1;
    }

    public void setImageBitmap(Bitmap bitmap) {
        if (!stopUiUpdates) {
            view.setImageBitmap(bitmap);
        }
    }

    /**
     * Sets the card drawables according to set preferences. Each card theme has one drawable file
     * with 52 cards in it. These will be loaded in bitmaps and applied to the cards. The bitmap array
     * has the same order like the cards array. If the fourColor theme is enabled, Clubs and Diamonds
     * use another row in the bitmap file.
     */
    public static void updateCardDrawableChoice() {
        boolean fourColors = prefs.getSavedFourColorMode();

        for (int i = 0; i < 13; i++) {
            drawables[i] = bitmaps.getCardFront(i, fourColors ? 1 : 0);
            drawables[13 + i] = bitmaps.getCardFront(i, 2);
            drawables[26 + i] = bitmaps.getCardFront(i, 3);
            drawables[39 + i] = bitmaps.getCardFront(i, fourColors ? 5 : 4);
        }

        if (cards == null) {
            return;
        }

        for (Card card : cards) {
            if (card.isUp()) {
                card.setCardFront();
            }
        }
    }

    /**
     * Loads the card backgrounds for the bitmap file and applies them.
     */
    public static void updateCardBackgroundChoice() {
        int positionX = prefs.getSavedCardBackground();
        int positionY = prefs.getSavedCardBackgroundColor();
        background = bitmaps.getCardBack(positionX, positionY);

        if (cards == null) {
            return;
        }

        for (Card card : cards) {
            if (!card.isUp()) {
                card.setCardBack();
            }
        }
    }

    /**
     * Save the card direction (up/down) as a string list.
     */
    public static void save() {
        List<Integer> list = new ArrayList<>(cards.length);

        for (Card card : cards) {
            int state = card.isUp ? STATE_FACED_UP : STATE_FACED_DOWN;

            if (card.isInvisible) {
                state = STATE_INVISIBLE;
            }

            list.add(state);
        }

        prefs.saveCards(list);
    }

    /**
     * Load the card direction (up/down) from a string list and applies the data.
     */
    public static void load() {
        List<Integer> list = prefs.getSavedCards();

        for (int i = 0; i < cards.length; i++) {
            switch (list.get(i)) {
                case STATE_FACED_UP:
                    cards[i].flipUp();
                    break;
                case STATE_FACED_DOWN:
                    cards[i].flipDown();
                    break;
                case STATE_INVISIBLE:
                    cards[i].view.setVisibility(View.GONE);
                    cards[i].isInvisible = true;
                    //cards[i].removeFromGame();
                    break;
            }
        }
    }

    /**
     * Sets the card front side from the bitmap array. The position is calculated with the card
     * color and value.
     */
    public void setCardFront() {
        setImageBitmap(drawables[(color - 1) * 13 + value - 1]);
    }

    /**
     * Sets the card background, there is only one background for all cards.
     */
    public void setCardBack() {
        setImageBitmap(background);
    }

    /**
     * Updates the color of the card. It is only used when a custom color order is set up
     * (like in Spider for different difficulties).
     */
    public void setColor() {
        color = currentGame.cardDrawablesOrder[(id % 52) / 13];
    }

    /**
     * Moves a card to the given coordinates (if not already there). This will use a translate
     * Animation and no interaction with cards/buttons is possible during the movement.
     *
     * @param pX The x-coordinate of the destination
     * @param pY The y-coordinate of the destination
     */
    public void setLocation(float pX, float pY) {

        if (isInvisible) {
            setLocationWithoutMovement(pX, pY);
        }

        if (!stopUiUpdates) {
            if (view.getX() != pX || view.getY() != pY) {
                animate.moveCard(this, pX, pY);
            }
        }
    }

    /**
     * Sets the location instantly WITHOUT a movement.
     *
     * @param pX The x-coordinate of the destination
     * @param pY The y-coordinate of the destination
     */
    public void setLocationWithoutMovement(float pX, float pY) {
        if (!stopUiUpdates) {
            view.bringToFront();
            view.setX(pX);
            view.setY(pY);
        }
    }

    /**
     * Saves the current location of the card as the old location, so it can be reverted if
     * necessary.
     */
    public void saveOldLocation() {
        oldLocation.x = view.getX();
        oldLocation.y = view.getY();
    }

    /**
     * reverts the current location to the saved one.
     */
    public void returnToOldLocation() {
        view.setX(oldLocation.x);
        view.setY(oldLocation.y);
    }

    /**
     * Sets the direction to up and updates the drawable.
     */
    public void flipUp() {
        isUp = true;

        if (!stopUiUpdates) {
            setCardFront();
        }
    }

    /**
     * Sets the direction to down and updates the drawable.
     */
    public void flipDown() {
        isUp = false;

        if (!stopUiUpdates) {
            setCardBack();
        }
    }

    /**
     * Sets the direction to the opposite of the current direction.
     */
    public void flip() {
        if (isUp())
            flipDown();
        else
            flipUp();
    }

    /**
     * Sets the direction to the opposite of the current direction, but with an animation.
     * This also updates the score (movement from the current stack to the same stack is counted
     * as a flip) and sets a new record in the record list.
     */
    public void flipWithAnim() {
        if (isUp()) {
            isUp = false;
            //sounds.playSound(Sounds.names.CARD_FLIP_BACK);
            scores.undo(this, getStack());

            if (!stopUiUpdates) {
                animate.flipCard(this, false);
            }
        } else {
            isUp = true;
            //sounds.playSound(Sounds.names.CARD_FLIP);
            scores.move(this, getStack());
            recordList.addFlip(this);

            if (!stopUiUpdates) {
                animate.flipCard(this, true);
            }
        }
    }

    /**
     * Tests if this card can be placed on a stack:
     * Only possible if: the cardTest returns true, the card and the top card on the destination are
     * up, and no auto complete is running.
     *
     * @param destination The destination stack to test the card on
     * @return True if movement is possible, false otherwise
     */
    public boolean test(Stack destination) {
        if (prefs.isDeveloperOptionMoveCardsEverywhereEnabled()) {
            return true;
        }

        return !((!isUp() || (destination.getSize() != 0 && !destination.getTopCard().isUp())) && !autoComplete.isRunning()) && currentGame.cardTest(destination, this);
    }

    public int getColor() {
        return color;
    }

    public boolean isTopCard() {
        return getStack().getTopCard() == this;
    }

    public boolean isFirstCard() {
        return getStack().getCard(0) == this;
    }

    public int getIndexOnStack() {
        return getStack().getIndexOfCard(this);
    }

    public boolean isUp() {                                                                         //returns if the card is up
        return isUp;
    }

    public int getId() {
        return id;
    }

    public int getValue() {
        return value;
    }

    public Stack getStack() {
        return stack;
    }

    public void setStack(Stack stack) {
        this.stack = stack;
    }

    public float getX() {
        return view.getX();
    }

    public void setX(float X) {
        view.setX(X);
    }

    public float getY() {
        return view.getY();
    }

    public void setY(float Y) {
        view.setY(Y);
    }

    public int getStackId() {
        return stack.getId();
    }

    public boolean isInvisible() {
        return isInvisible;
    }

    public void removeFromCurrentStack() {
        if (stack != null) {
            stack.removeCard(this);
            stack = null;
        }
    }

    public Card getCardOnTop() {
        if (getIndexOnStack() < stack.getSize() - 1) {
            return stack.getCard(getIndexOnStack() + 1);
        } else {
            return this;
        }
    }

    public Card getCardBelow() {
        return getIndexOnStack() == 0 ? this : stack.getCard(getIndexOnStack() - 1);
    }

    public void bringToFront() {
        if (!stopUiUpdates) {
            view.bringToFront();
        }
    }

    public void removeFromGame() {
        view.setVisibility(View.GONE);
        isInvisible = true;
        moveToStack(this, currentGame.offScreenStack, OPTION_NO_RECORD);
    }

    public void addBackToGame(Stack moveTo) {
        isInvisible = false;
        flipUp();
        view.setVisibility(View.VISIBLE);
        moveToStack(this, moveTo);
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/dialogs/DialogPreferenceCards.java
public class DialogPreferenceCards extends CustomDialogPreference implements View.OnClickListener {

    private static int NUMBER_OF_CARD_THEMES = 10;

    private LinearLayout[] linearLayouts = new LinearLayout[NUMBER_OF_CARD_THEMES];
    private Context context;
    private ImageView image;

    public DialogPreferenceCards(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.dialog_settings_cards);
        setDialogIcon(null);
        this.context = context;
    }

    @Override
    protected void onBindDialogView(View view) {
        int row = prefs.getSavedFourColorMode() ? 1 : 0;

        linearLayouts[0] = view.findViewById(R.id.settingsLinearLayoutCardsBasic);
        linearLayouts[1] = view.findViewById(R.id.settingsLinearLayoutCardsClassic);
        linearLayouts[2] = view.findViewById(R.id.settingsLinearLayoutCardsAbstract);
        linearLayouts[3] = view.findViewById(R.id.settingsLinearLayoutCardsSimple);
        linearLayouts[4] = view.findViewById(R.id.settingsLinearLayoutCardsModern);
        linearLayouts[5] = view.findViewById(R.id.settingsLinearLayoutCardsOxygenDark);
        linearLayouts[6] = view.findViewById(R.id.settingsLinearLayoutCardsOxygenLight);
        linearLayouts[7] = view.findViewById(R.id.settingsLinearLayoutCardsPoker);
        linearLayouts[8] = view.findViewById(R.id.settingsLinearLayoutCardsParis);
        linearLayouts[9] = view.findViewById(R.id.settingsLinearLayoutCardsDondorf);

        for (int i = 0; i < NUMBER_OF_CARD_THEMES; i++) {
            linearLayouts[i].setOnClickListener(this);
            ImageView imageView = (ImageView) linearLayouts[i].getChildAt(0);
            imageView.setImageBitmap(bitmaps.getCardPreview(i, row));
        }

        super.onBindDialogView(view);
    }

    public void onClick(View v) {
        int choice;

        switch (v.getId()) {
            case R.id.settingsLinearLayoutCardsBasic:
            default:
                choice = 1;
                break;
            case R.id.settingsLinearLayoutCardsClassic:
                choice = 2;
                break;
            case R.id.settingsLinearLayoutCardsAbstract:
                choice = 3;
                break;
            case R.id.settingsLinearLayoutCardsSimple:
                choice = 4;
                break;
            case R.id.settingsLinearLayoutCardsModern:
                choice = 5;
                break;
            case R.id.settingsLinearLayoutCardsOxygenDark:
                choice = 6;
                break;
            case R.id.settingsLinearLayoutCardsOxygenLight:
                choice = 7;
                break;
            case R.id.settingsLinearLayoutCardsPoker:
                choice = 8;
                break;
            case R.id.settingsLinearLayoutCardsParis:
                choice = 9;
                break;
            case R.id.settingsLinearLayoutCardsDondorf:
                choice = 10;
                break;
        }

        prefs.saveCardTheme(choice);
        updateSummary();
        getDialog().dismiss();
    }

    /*
     * Get the layout from the preference, so I can get the imageView from the widgetLayout
     */
    @Override
    protected View onCreateView(ViewGroup parent) {
        View view = super.onCreateView(parent);

        image = view.findViewById(R.id.preference_cards_imageView);
        updateSummary();

        return view;
    }

    /**
     * Gets the bitmap for the card theme preference icon and also set its summary
     */
    public void updateSummary() {
        String text;
        Bitmap cardPreview;
        int row = prefs.getSavedFourColorMode() ? 1 : 0;
        int selectedTheme = prefs.getSavedCardTheme();

        switch (selectedTheme) {
            case 1:
            default:
                text = context.getString(R.string.settings_basic);
                break;
            case 2:
                text = context.getString(R.string.settings_classic);
                break;
            case 3:
                text = context.getString(R.string.settings_abstract);
                break;
            case 4:
                text = context.getString(R.string.settings_simple);
                break;
            case 5:
                text = context.getString(R.string.settings_modern);
                break;
            case 6:
                text = context.getString(R.string.settings_oxygen_dark);
                break;
            case 7:
                text = context.getString(R.string.settings_oxygen_light);
                break;
            case 8:
                text = context.getString(R.string.settings_poker);
                break;
            case 9:
                text = context.getString(R.string.settings_cards_paris);
                break;
            case 10:
                text = context.getString(R.string.settings_cards_dondorf);
                break;
        }

        cardPreview = bitmaps.getCardPreview2(selectedTheme - 1, row);

        if (image != null) {
            image.setImageBitmap(cardPreview);
        }

        setSummary(text);
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/helper/Preferences.java
public class Preferences {

    private SharedPreferences savedSharedData;
    private SharedPreferences savedGameData;

    //Strings
    public static String PREF_KEY_NEXT_CARD_VALUES;
    public static String PREF_KEY_HIDE_STATUS_BAR;
    public static String PREF_KEY_LONGEST_RUN;
    public static String PREF_KEY_RUN_COUNTER;
    public static String PREF_KEY_ORDER;
    public static String PREF_KEY_SCORE;
    public static String PREF_KEY_SAVED_SCORES;

    public static String PREF_KEY_SAVED_RECENT_SCORES;
    public static String PREF_KEY_TOTAL_NUMBER_UNDOS;
    public static String PREF_KEY_TOTAL_HINTS_SHOWN;
    public static String PREF_KEY_TOTAL_POINTS_EARNED;
    public static String PREF_KEY_TOTAL_TIME_PLAYED;
    public static String PREF_KEY_DEALING_CARDS;
    public static String PREF_KEY_HIDE_MENU_BUTTON;
    public static String PREF_KEY_STATISTICS_HIDE_WIN_PERCENTAGE;
    public static String OLD;

    public static String PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT;
    public static String PREF_KEY_ENSURE_MOVABILITY;
    public static String PREF_KEY_ENSURE_MOVABILITY_MIN_MOVES;
    public static String PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME;
    public static String PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE;
    public static String PREF_KEY_DISABLE_UNDO_COSTS;
    public static String PREF_KEY_DISABLE_HINT_COSTS;
    public static String PREF_KEY_VEGAS_OLD_SCORE;
    public static String PREF_KEY_VEGAS_TIME;
    public static String PREF_KEY_GAME_REDEAL_COUNT;
    public static String PREF_KEY_GAME_WON;
    public static String PREF_KEY_GAME_WON_AND_RELOADED;
    public static String PREF_KEY_GAME_NUMBER_OF_WON_GAMES;
    public static String PREF_KEY_GAME_NUMBER_OF_PLAYED_GAMES;
    public static String PREF_KEY_GAME_RANDOM_CARDS;
    public static String PREF_KEY_GAME_FIRST_RUN;
    public static String PREF_KEY_GAME_MOVED_FIRST_CARD;
    public static String PREF_KEY_RECORD_LIST_ENTRY;
    public static String PREF_KEY_RECORD_LIST_ENTRIES_SIZE;
    public static String PREF_KEY_FLIP_CARD;
    public static String PREF_KEY_ORIGIN;
    public static String PREF_KEY_IMMERSIVE_MODE;
    public static String PREF_KEY_CARD;
    public static String PREF_KEY_CARDS;
    public static String PREF_KEY_STACK;
    public static String PREF_KEY_TIMER_END_TIME;
    public static String PREF_KEY_TIMER_START_TIME;
    public static String PREF_KEY_TIMER_WINNING_TIME;
    public static String PREF_KEY_CARD_DRAWABLES;
    public static String PREF_KEY_CARD_BACKGROUND;
    public static String PREF_KEY_CARD_BACKGROUND_COLOR;
    public static String PREF_KEY_MENU_COLUMNS_PORTRAIT;
    public static String PREF_KEY_MENU_COLUMNS_LANDSCAPE;
    public static String PREF_KEY_CANFIELD_START_CARD_VALUE;
    public static String PREF_KEY_START_WITH_MENU;
    public static String PREF_KEY_YUKON_RULES;
    public static String PREF_KEY_YUKON_RULES_OLD;
    public static String PREF_KEY_KLONDIKE_DRAW;
    public static String PREF_KEY_KLONDIKE_DRAW_OLD;
    public static String PREF_KEY_VEGAS_DRAW;
    public static String PREF_KEY_VEGAS_DRAW_OLD;
    public static String PREF_KEY_GOLF_CYCLIC;
    public static String PREF_KEY_CANFIELD_DRAW;
    public static String PREF_KEY_CANFIELD_DRAW_OLD;
    public static String PREF_KEY_PYRAMID_DIFFICULTY;
    public static String PREF_KEY_SPIDER_DIFFICULTY;
    public static String PREF_KEY_SPIDER_DIFFICULTY_OLD;
    public static String PREF_KEY_SPIDERETTE_DIFFICULTY;
    public static String PREF_KEY_SPIDERETTE_DIFFICULTY_OLD;
    public static String PREF_KEY_LANGUAGE;
    public static String PREF_KEY_CURRENT_GAME;
    public static String PREF_KEY_ORIENTATION;
    public static String PREF_KEY_MENU_GAMES;
    public static String PREF_KEY_4_COLOR_MODE;
    public static String PREF_KEY_LEFT_HANDED_MODE;
    public static String PREF_KEY_MENU_BAR_POS_PORTRAIT;
    public static String PREF_KEY_MENU_BAR_POS_LANDSCAPE;
    public static String PREF_KEY_DOUBLE_TAP_ENABLED;
    public static String PREF_KEY_DOUBLE_TAP_ALL_CARDS;
    public static String PREF_KEY_DOUBLE_TAP_FOUNDATION_FIRST;
    public static String PREF_KEY_TAP_TO_SELECT_ENABLED;
    public static String PREF_KEY_SINGLE_TAP_SPECIAL_GAMES;
    public static String PREF_KEY_BACKGROUND_COLOR_TYPE;
    public static String PREF_KEY_BACKGROUND_COLOR;
    public static String PREF_KEY_BACKGROUND_COLOR_CUSTOM;
    public static String PREF_KEY_MOVEMENT_SPEED;
    public static String PREF_KEY_TEXT_COLOR;
    public static String PREF_KEY_SOUND_ENABLED;
    public static String PREF_KEY_WIN_SOUND;
    public static String PREF_KEY_BACKGROUND_MUSIC;
    public static String PREF_KEY_BACKGROUND_VOLUME;
    public static String PREF_KEY_PYRAMID_LIMITED_RECYCLES;
    public static String PREF_KEY_FORTYEIGHT_LIMITED_RECYCLES;
    public static String PREF_KEY_PYRAMID_NUMBER_OF_RECYCLES;
    public static String PREF_KEY_NAPOLEONSTOMB_NUMBER_OF_RECYCLES;
    public static String PREF_KEY_FORTYEIGHT_NUMBER_OF_RECYCLES;
    public static String PREF_KEY_KLONDIKE_LIMITED_RECYCLES;
    public static String PREF_KEY_KLONDIKE_NUMBER_OF_RECYCLES;
    public static String PREF_KEY_VEGAS_NUMBER_OF_RECYCLES;
    public static String PREF_KEY_VEGAS_BET_AMOUNT;
    public static String PREF_KEY_VEGAS_BET_AMOUNT_OLD;
    public static String PREF_KEY_VEGAS_WIN_AMOUNT;
    public static String PREF_KEY_VEGAS_WIN_AMOUNT_OLD;
    public static String PREF_KEY_MENU_ORDER;
    public static String PREF_KEY_AUTO_START_NEW_GAME;
    public static String PREF_KEY_FORCE_TABLET_LAYOUT;
    public static String PREF_KEY_CALCULATION_ALTERNATIVE;
    public static String PREF_KEY_CALCULATION_ALTERNATIVE_OLD;
    public static String PREF_KEY_SHOW_ADVANCED_SETTINGS;
    public static String PREF_KEY_HIDE_TIME;
    public static String PREF_KEY_HIDE_SCORE;
    public static String PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON;
    public static String PREF_KEY_VEGAS_MONEY;
    public static String PREF_KEY_VEGAS_MONEY_ENABLED;
    public static String PREF_KEY_VEGAS_RESET_MONEY;
    public static String PREF_KEY_MOD3_AUTO_MOVE;
    public static String PREF_KEY_PYRAMID_AUTO_MOVE;
    public static String PREF_KEY_SINGLE_TAP_ALL_GAMES;
    public static String PREF_KEY_CANFIELD_SIZE_OF_RESERVE;
    public static String PREF_KEY_DEVELOPER_OPTION_MOVE_CARDS_EVERYWHERE;
    public static String PREF_KEY_DEVELOPER_OPTION_PLAY_EVERY_CARD;
    public static String PREF_KEY_DEVELOPER_OPTION_INSTANT_WIN;
    public static String PREF_KEY_USE_TRUE_RANDOMISATION;
    public static String PREF_KEY_DEVELOPER_OPTION_NO_SAVING;
    public static String PREF_KEY_DEVELOPER_OPTION_DEAL_CORRECT_SEQUENCES;
    public static String PREF_KEY_MAX_NUMBER_UNDOS;
    public static String PREF_KEY_SHOW_DIALOG_NEW_GAME;
    public static String PREF_KEY_SHOW_DIALOG_REDEAL;
    public static String PREF_KEY_SHOW_DIALOG_MIX_CARDS;
    public static String PREF_KEY_HIDE_MENU_BAR;
    public static String PREF_KEY_IMPROVE_AUTO_MOVE;
    public static String DEFAULT_CANFIELD_DRAW;
    public static String DEFAULT_KLONDIKE_DRAW;
    public static String DEFAULT_VEGAS_DRAW;
    public static String DEFAULT_YUKON_RULES;
    public static String DEFAULT_MENU_BAR_POSITION_LANDSCAPE;
    public static String DEFAULT_MENU_BAR_POSITION_PORTRAIT;
    public static String DEFAULT_PYRAMID_DIFFICULTY;
    public static String DEFAULT_SPIDER_DIFFICULTY;
    public static String DEFAULT_SPIDERETTE_DIFFICULTY;
    public static String DEFAULT_LANGUAGE;
    public static String DEFAULT_MENU_COLUMNS_LANDSCAPE;
    public static String DEFAULT_MENU_COLUMNS_PORTRAIT;
    public static String DEFAULT_ORIENTATION;
    public static String DEFAULT_BACKGROUND_COLOR;
    public static String DEFAULT_BACKGROUND_MUSIC;
    public static String DEFAULT_PYRAMID_NUMBER_OF_RECYCLES;
    public static String DEFAULT_FORTYEIGHT_NUMBER_OF_RECYCLES;
    public static String DEFAULT_VEGAS_NUMBER_OF_RECYCLES;
    public static String DEFAULT_KLONDIKE_NUMBER_OF_RECYCLES;
    public static String DEFAULT_WIN_SOUND;
    public static String DEFAULT_MOVEMENT_SPEED;
    public static String DEFAULT_CANFIELD_SIZE_OF_RESERVE;
    public static String DEFAULT_DEVELOPER_OPTION_DEAL_CORRECT_SEQUENCES;
    public static String DEFAULT_NAPOLEONSTOMB_NUMBER_OF_RECYCLES;
    public static int DEFAULT_CURRENT_GAME;
    public static int DEFAULT_GAME_LAYOUT_MARGINS_PORTRAIT;
    public static int DEFAULT_GAME_LAYOUT_MARGINS_LANDSCAPE;
    public static int DEFAULT_CARD_BACKGROUND;
    public static int DEFAULT_CARD_BACKGROUND_COLOR;
    public static int DEFAULT_WINNING_TIME;
    public static int DEFAULT_BACKGROUND_COLOR_TYPE;
    public static int DEFAULT_BACKGROUND_VOLUME;
    public static int DEFAULT_BACKGROUND_COLOR_CUSTOM;
    public static int DEFAULT_VEGAS_BET_AMOUNT;
    public static int DEFAULT_VEGAS_WIN_AMOUNT;
    public static int DEFAULT_VEGAS_MONEY;
    public static int DEFAULT_MAX_NUMBER_UNDOS;
    public static int DEFAULT_ENSURE_MOVABILITY_MIN_MOVES;
    public static int DEFAULT_TEXT_COLOR;
    public static boolean DEFAULT_STATISTICS_HIDE_WIN_PERCENTAGE;
    public static boolean DEFAULT_ENSURE_MOVABILITY;
    public static boolean DEFAULT_HIDE_AUTOCOMPLETE_BUTTON;
    public static boolean DEFAULT_SETTINGS_ONLY_FOR_THIS_GAME;
    public static boolean DEFAULT_HIDE_MENU_BUTTON;
    public static boolean DEFAULT_IMMERSIVE_MODE;
    public static boolean DEFAULT_DISABLE_UNDO_COSTS;
    public static boolean DEFAULT_DISABLE_HINT_COSTS;
    public static boolean DEFAULT_SHOW_DIALOG_NEW_GAME;
    public static boolean DEFAULT_SHOW_DIALOG_REDEAL;
    public static boolean DEFAULT_SHOW_DIALOG_MIX_CARDS;
    public static boolean DEFAULT_SHOW_ADVANCED_SETTINGS;
    public static boolean DEFAULT_GOLF_CYCLIC;
    public static boolean DEFAULT_LEFT_HANDED_MODE;
    public static boolean DEFAULT_DOUBLE_TAP_ENABLE;
    public static boolean DEFAULT_DOUBLE_TAP_ALL_CARDS;
    public static boolean DEFAULT_DOUBLE_TAP_FOUNDATION_FIRST;
    public static boolean DEFAULT_WON;
    public static boolean DEFAULT_HIDE_MENU_BAR;
    public static boolean DEFAULT_IMPROVE_AUTO_MOVE;
    public static boolean DEFAULT_WON_AND_RELOADED;
    public static boolean DEFAULT_FIRST_RUN;
    public static boolean DEFAULT_MOVED_FIRST_CARD;
    public static boolean DEFAULT_4_COLOR_MODE;
    public static boolean DEFAULT_TAP_TO_SELECT_ENABLED;
    public static boolean DEFAULT_SINGLE_TAP_SPECIAL_GAMES_ENABLED;
    public static boolean DEFAULT_SOUND_ENABLED;
    public static boolean DEFAULT_AUTO_START_NEW_GAME;
    public static boolean DEFAULT_FORCE_TABLET_LAYOUT;
    public static boolean DEFAULT_HIDE_TIME;
    public static boolean DEFAULT_HIDE_SCORE;
    public static boolean DEFAULT_VEGAS_MONEY_ENABLED;
    public static boolean DEFAULT_VEGAS_RESET_MONEY;
    public static boolean DEFAULT_SINGLE_TAP_ALL_GAMES;
    public static boolean DEFAULT_PYRAMID_LIMITED_RECYCLES;
    public static boolean DEFAULT_FORTYEIGHT_LIMITED_RECYCLES;
    public static boolean DEFAULT_KLONDIKE_LIMITED_RECYCLES;
    public static boolean DEFAULT_CALCULATION_ALTERNATIVE;
    public static boolean DEFAULT_MOD3_AUTO_MOVE;
    public static boolean DEFAULT_PYRAMID_AUTO_MOVE;
    public static boolean DEFAULT_DEVELOPER_OPTION_MOVE_CARDS_EVERYWHERE;
    public static boolean DEFAULT_DEVELOPER_OPTION_PLAY_EVERY_CARD;
    public static boolean DEFAULT_DEVELOPER_OPTION_INSTANT_WIN;
    public static boolean DEFAULT_DEVELOPER_OPTION_NO_SAVING;
    public static boolean DEFAULT_USE_TRUE_RANDOMISATION;

    public Preferences(Context context) {
        loadStrings(context.getResources());

        savedSharedData = PreferenceManager.getDefaultSharedPreferences(context);
        setGamePreferences(context);
    }

    public void setGamePreferences(Context context) {
        savedGameData = context.getSharedPreferences(lg.getSharedPrefName(), MODE_PRIVATE);

    }

    public void registerListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
        savedSharedData.registerOnSharedPreferenceChangeListener(listener);

        if (savedGameData != null) {
            savedGameData.registerOnSharedPreferenceChangeListener(listener);
        }
    }

    public void unregisterListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
        savedSharedData.unregisterOnSharedPreferenceChangeListener(listener);

        if (savedGameData != null) {
            savedGameData.unregisterOnSharedPreferenceChangeListener(listener);
        }
    }

    /**
     * Load the static strings, so i can use them in every file instead of writing the string itself,
     * which would be susceptible for errors. TODO manage this in a better way.
     *
     * @param res Used to load the strings
     */
    private void loadStrings(Resources res) {

        OLD = "_old";

        PREF_KEY_STATISTICS_HIDE_WIN_PERCENTAGE = res.getString(R.string.pref_key_statistics_hide_win_percentage);
        PREF_KEY_ENSURE_MOVABILITY = res.getString(R.string.pref_key_ensure_movability);
        PREF_KEY_ENSURE_MOVABILITY_MIN_MOVES = res.getString(R.string.pref_key_ensure_movability_min_moves);
        PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME = res.getString(R.string.pref_key_settings_only_for_this_game);
        PREF_KEY_DEALING_CARDS = "pref_key_dealing_cards";
        PREF_KEY_VEGAS_TIME = "pref_key_vegas_time";
        PREF_KEY_VEGAS_OLD_SCORE = "pref_key_vegas_old_score";
        PREF_KEY_ORDER = "order";
        PREF_KEY_LONGEST_RUN = "longest_run";
        PREF_KEY_RUN_COUNTER = "run_counter";
        PREF_KEY_NEXT_CARD_VALUES = "pref_key_next_card_values";
        PREF_KEY_START_WITH_MENU = res.getString(R.string.pref_key_start_menu);
        PREF_KEY_HIDE_STATUS_BAR = res.getString(R.string.pref_key_hide_status_bar);
        PREF_KEY_YUKON_RULES = res.getString(R.string.pref_key_yukon_rules);
        PREF_KEY_KLONDIKE_DRAW = res.getString(R.string.pref_key_klondike_draw);
        PREF_KEY_VEGAS_DRAW = res.getString(R.string.pref_key_vegas_draw);
        PREF_KEY_CANFIELD_DRAW = res.getString(R.string.pref_key_canfield_draw);
        PREF_KEY_YUKON_RULES_OLD = PREF_KEY_YUKON_RULES + OLD;
        PREF_KEY_KLONDIKE_DRAW_OLD = PREF_KEY_KLONDIKE_DRAW + OLD;
        PREF_KEY_VEGAS_DRAW_OLD = PREF_KEY_VEGAS_DRAW + OLD;
        PREF_KEY_CANFIELD_DRAW_OLD = PREF_KEY_CANFIELD_DRAW + OLD;
        PREF_KEY_GOLF_CYCLIC = res.getString(R.string.pref_key_golf_cyclic);
        PREF_KEY_PYRAMID_DIFFICULTY = res.getString(R.string.pref_key_pyramid_difficulty);
        PREF_KEY_SPIDER_DIFFICULTY = res.getString(R.string.pref_key_spider_difficulty);
        PREF_KEY_SPIDER_DIFFICULTY_OLD = PREF_KEY_SPIDER_DIFFICULTY + OLD;
        PREF_KEY_SPIDERETTE_DIFFICULTY = res.getString(R.string.pref_key_spiderette_difficulty);
        PREF_KEY_SPIDERETTE_DIFFICULTY_OLD = PREF_KEY_SPIDERETTE_DIFFICULTY + OLD;
        PREF_KEY_SHOW_ADVANCED_SETTINGS = res.getString(R.string.pref_key_show_advanced_settings);
        PREF_KEY_LANGUAGE = res.getString(R.string.pref_key_language);
        PREF_KEY_CURRENT_GAME = res.getString(R.string.pref_key_current_game);
        PREF_KEY_MENU_GAMES = res.getString(R.string.pref_key_menu_games);
        PREF_KEY_HIDE_MENU_BUTTON = res.getString(R.string.pref_key_hide_menu_button);
        PREF_KEY_ORIENTATION = res.getString(R.string.pref_key_orientation);
        PREF_KEY_IMPROVE_AUTO_MOVE = res.getString(R.string.pref_key_improve_auto_move);
        PREF_KEY_4_COLOR_MODE = res.getString(R.string.pref_key_4_color_mode);
        PREF_KEY_LEFT_HANDED_MODE = res.getString(R.string.pref_key_left_handed_mode);
        PREF_KEY_MENU_BAR_POS_PORTRAIT = res.getString(R.string.pref_key_menu_bar_position_portrait);
        PREF_KEY_MENU_BAR_POS_LANDSCAPE = res.getString(R.string.pref_key_menu_bar_position_landscape);
        PREF_KEY_DOUBLE_TAP_ENABLED = res.getString(R.string.pref_key_double_tap_enable);
        PREF_KEY_DOUBLE_TAP_ALL_CARDS = res.getString(R.string.pref_key_double_tap_all_cards);
        PREF_KEY_DOUBLE_TAP_FOUNDATION_FIRST = res.getString(R.string.pref_key_double_tap_foundation_first);
        PREF_KEY_TAP_TO_SELECT_ENABLED = res.getString(R.string.pref_key_tap_to_select_enable);
        PREF_KEY_SINGLE_TAP_SPECIAL_GAMES = res.getString(R.string.pref_key_single_tap_special_games);
        PREF_KEY_BACKGROUND_COLOR_TYPE = res.getString(R.string.pref_key_background_color_type);
        PREF_KEY_BACKGROUND_COLOR = res.getString(R.string.pref_key_background_color);
        PREF_KEY_BACKGROUND_COLOR_CUSTOM = res.getString(R.string.pref_key_background_color_custom);
        PREF_KEY_MOVEMENT_SPEED = res.getString(R.string.pref_key_movement_speed);
        PREF_KEY_SOUND_ENABLED = res.getString(R.string.pref_key_sound_enabled);
        PREF_KEY_WIN_SOUND = res.getString(R.string.pref_key_win_sound);
        PREF_KEY_BACKGROUND_MUSIC = res.getString(R.string.pref_key_background_music);
        PREF_KEY_BACKGROUND_VOLUME = res.getString(R.string.pref_key_background_volume);
        PREF_KEY_PYRAMID_LIMITED_RECYCLES = res.getString(R.string.pref_key_pyramid_limit_recycles);
        PREF_KEY_FORTYEIGHT_LIMITED_RECYCLES = res.getString(R.string.pref_key_fortyeight_limit_recycles);
        PREF_KEY_PYRAMID_NUMBER_OF_RECYCLES = res.getString(R.string.pref_key_pyramid_number_of_recycles);
        PREF_KEY_FORTYEIGHT_NUMBER_OF_RECYCLES = res.getString(R.string.pref_key_fortyeight_number_of_recycles);
        PREF_KEY_VEGAS_NUMBER_OF_RECYCLES = res.getString(R.string.pref_key_vegas_number_of_recycles);
        PREF_KEY_VEGAS_BET_AMOUNT = res.getString(R.string.pref_key_vegas_bet_amount);
        PREF_KEY_VEGAS_WIN_AMOUNT = res.getString(R.string.pref_key_vegas_win_amount);
        PREF_KEY_MENU_ORDER = res.getString(R.string.pref_key_menu_order);
        PREF_KEY_VEGAS_BET_AMOUNT_OLD = PREF_KEY_VEGAS_BET_AMOUNT + OLD;
        PREF_KEY_VEGAS_WIN_AMOUNT_OLD = PREF_KEY_VEGAS_WIN_AMOUNT + OLD;
        PREF_KEY_AUTO_START_NEW_GAME = res.getString(R.string.pref_key_auto_start_new_game);
        PREF_KEY_FORCE_TABLET_LAYOUT = res.getString(R.string.pref_key_force_tablet_layout);
        PREF_KEY_KLONDIKE_LIMITED_RECYCLES = res.getString(R.string.pref_key_klondike_limit_recycles);
        PREF_KEY_KLONDIKE_NUMBER_OF_RECYCLES = res.getString(R.string.pref_key_klondike_number_of_recycles);
        PREF_KEY_NAPOLEONSTOMB_NUMBER_OF_RECYCLES = res.getString(R.string.pref_key_napoleons_tomb_number_of_recycles);
        PREF_KEY_CALCULATION_ALTERNATIVE = res.getString(R.string.pref_key_calculation_alternative);
        PREF_KEY_HIDE_MENU_BAR = res.getString(R.string.pref_key_hide_menu_bar);
        PREF_KEY_IMMERSIVE_MODE = res.getString(R.string.pref_key_immersive_mode);
        PREF_KEY_CALCULATION_ALTERNATIVE_OLD = PREF_KEY_CALCULATION_ALTERNATIVE + OLD;
        PREF_KEY_HIDE_TIME = res.getString(R.string.pref_key_hide_time);
        PREF_KEY_HIDE_SCORE = res.getString(R.string.pref_key_hide_score);
        PREF_KEY_VEGAS_MONEY = res.getString(R.string.pref_key_vegas_money);
        PREF_KEY_VEGAS_MONEY_ENABLED = res.getString(R.string.pref_key_vegas_money_enabled);
        PREF_KEY_VEGAS_RESET_MONEY = res.getString(R.string.pref_key_vegas_reset_money);
        PREF_KEY_MOD3_AUTO_MOVE = res.getString(R.string.pref_key_mod3_auto_move);
        PREF_KEY_PYRAMID_AUTO_MOVE = res.getString(R.string.pref_key_pyramid_auto_move);
        PREF_KEY_SINGLE_TAP_ALL_GAMES = res.getString(R.string.pref_key_single_tap_all_games);
        PREF_KEY_CANFIELD_SIZE_OF_RESERVE = res.getString(R.string.pref_key_canfield_size_of_reserve);
        PREF_KEY_USE_TRUE_RANDOMISATION = res.getString(R.string.pref_key_use_true_randomisation);
        PREF_KEY_MAX_NUMBER_UNDOS = res.getString(R.string.pref_key_max_number_undos);
        PREF_KEY_TOTAL_TIME_PLAYED = res.getString(R.string.pref_key_total_time_played);
        PREF_KEY_TOTAL_NUMBER_UNDOS = res.getString(R.string.pref_key_total_number_undos);
        PREF_KEY_TOTAL_HINTS_SHOWN = res.getString(R.string.pref_key_total_hints_shown);
        PREF_KEY_TOTAL_POINTS_EARNED = res.getString(R.string.pref_key_total_points_earned);
        PREF_KEY_SHOW_DIALOG_NEW_GAME = res.getString(R.string.pref_key_show_dialog_new_game);
        PREF_KEY_SHOW_DIALOG_REDEAL = res.getString(R.string.pref_key_show_dialog_redeal);
        PREF_KEY_SHOW_DIALOG_MIX_CARDS = res.getString(R.string.pref_key_show_dialog_mix_cards);
        PREF_KEY_DISABLE_UNDO_COSTS = res.getString(R.string.pref_key_disable_undo_costs);
        PREF_KEY_DISABLE_HINT_COSTS = res.getString(R.string.pref_key_disable_hint_costs);
        PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON = res.getString(R.string.pref_key_hide_auto_complete_button);
        PREF_KEY_GAME_REDEAL_COUNT = res.getString(R.string.game_recycle_count);
        PREF_KEY_GAME_WON = res.getString(R.string.game_won);
        PREF_KEY_GAME_WON_AND_RELOADED = res.getString(R.string.game_won_and_reloaded);
        PREF_KEY_GAME_NUMBER_OF_WON_GAMES = res.getString(R.string.game_number_of_won_games);
        PREF_KEY_GAME_NUMBER_OF_PLAYED_GAMES = res.getString(R.string.game_number_of_played_games);
        PREF_KEY_GAME_RANDOM_CARDS = res.getString(R.string.game_random_cards);
        PREF_KEY_GAME_FIRST_RUN = res.getString(R.string.game_first_run);
        PREF_KEY_GAME_MOVED_FIRST_CARD = res.getString(R.string.game_moved_first_card);
        PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT = res.getString(R.string.pref_key_game_layout_margins_portrait);
        PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE = res.getString(R.string.pref_key_game_layout_margins_landscape);
        PREF_KEY_TEXT_COLOR = res.getString(R.string.pref_key_text_color);

        PREF_KEY_CANFIELD_START_CARD_VALUE = res.getString(R.string.canfield_start_value);
        PREF_KEY_SCORE = res.getString(R.string.score);
        PREF_KEY_SAVED_SCORES = res.getString(R.string.saved_scores);
        PREF_KEY_SAVED_RECENT_SCORES = res.getString(R.string.saved_recent_scores);

        PREF_KEY_RECORD_LIST_ENTRY = res.getString(R.string.record_list_entry);
        PREF_KEY_RECORD_LIST_ENTRIES_SIZE = res.getString(R.string.record_list_entries_size);
        PREF_KEY_FLIP_CARD = res.getString(R.string.flip_card);
        PREF_KEY_ORIGIN = res.getString(R.string.origin);
        PREF_KEY_CARD = res.getString(R.string.card);
        PREF_KEY_CARDS = res.getString(R.string.cards);
        PREF_KEY_STACK = res.getString(R.string.stack);

        PREF_KEY_TIMER_END_TIME = res.getString(R.string.saved_current_time);
        PREF_KEY_TIMER_START_TIME = res.getString(R.string.saved_start_time);
        PREF_KEY_TIMER_WINNING_TIME = res.getString(R.string.saved_shown_time);

        PREF_KEY_CARD_DRAWABLES = res.getString(R.string.pref_key_card_drawables);
        PREF_KEY_CARD_BACKGROUND = res.getString(R.string.pref_key_cards_background);
        PREF_KEY_CARD_BACKGROUND_COLOR = res.getString(R.string.pref_key_cards_background_color);
        PREF_KEY_MENU_COLUMNS_PORTRAIT = res.getString(R.string.pref_key_menu_columns_portrait);
        PREF_KEY_MENU_COLUMNS_LANDSCAPE = res.getString(R.string.pref_key_menu_columns_landscape);

        PREF_KEY_DEVELOPER_OPTION_MOVE_CARDS_EVERYWHERE = res.getString(R.string.pref_key_developer_option_move_cards_everywhere);
        PREF_KEY_DEVELOPER_OPTION_PLAY_EVERY_CARD = res.getString(R.string.pref_key_developer_option_play_every_card);
        PREF_KEY_DEVELOPER_OPTION_INSTANT_WIN = res.getString(R.string.pref_key_developer_option_instant_win);
        PREF_KEY_DEVELOPER_OPTION_NO_SAVING = res.getString(R.string.pref_key_developer_option_no_saving);
        PREF_KEY_DEVELOPER_OPTION_DEAL_CORRECT_SEQUENCES = res.getString(R.string.pref_key_developer_option_deal_correct_sequences);

        DEFAULT_PYRAMID_DIFFICULTY = res.getStringArray(R.array.pref_pyramid_difficulty_values)[0];
        DEFAULT_LANGUAGE = res.getStringArray(R.array.pref_language_values)[0];
        DEFAULT_SPIDER_DIFFICULTY = res.getStringArray(R.array.pref_spider_difficulty_values)[0];
        DEFAULT_SPIDERETTE_DIFFICULTY = res.getStringArray(R.array.pref_spider_difficulty_values)[0];   //same as in Spider
        DEFAULT_ORIENTATION = res.getStringArray(R.array.pref_orientation_values)[0];
        DEFAULT_DOUBLE_TAP_ALL_CARDS = res.getBoolean(R.bool.default_double_tap_all_cards);
        DEFAULT_DOUBLE_TAP_ENABLE = res.getBoolean(R.bool.default_double_tap_enable);
        DEFAULT_DOUBLE_TAP_FOUNDATION_FIRST = res.getBoolean(R.bool.default_double_tap_foundation_first);
        DEFAULT_LEFT_HANDED_MODE = res.getBoolean(R.bool.default_left_handed_mode);
        DEFAULT_GOLF_CYCLIC = res.getBoolean(R.bool.default_golf_cyclic);
        DEFAULT_TAP_TO_SELECT_ENABLED = res.getBoolean(R.bool.default_tap_to_select_enable);
        DEFAULT_SINGLE_TAP_SPECIAL_GAMES_ENABLED = res.getBoolean(R.bool.default_single_tap_enable);
        DEFAULT_AUTO_START_NEW_GAME = res.getBoolean(R.bool.default_auto_start_new_game);
        DEFAULT_KLONDIKE_LIMITED_RECYCLES = res.getBoolean(R.bool.default_klondike_limited_recycles);
        DEFAULT_STATISTICS_HIDE_WIN_PERCENTAGE = res.getBoolean(R.bool.default_statistics_hide_win_percentage);
        DEFAULT_CALCULATION_ALTERNATIVE = res.getBoolean(R.bool.default_calculation_alternative);
        DEFAULT_HIDE_TIME = res.getBoolean(R.bool.default_hide_time);
        DEFAULT_HIDE_SCORE = res.getBoolean(R.bool.default_hide_score);
        DEFAULT_VEGAS_MONEY_ENABLED = res.getBoolean(R.bool.default_vegas_money_enabled);
        DEFAULT_VEGAS_RESET_MONEY = res.getBoolean(R.bool.default_vegas_reset_money);
        DEFAULT_MOD3_AUTO_MOVE = res.getBoolean(R.bool.default_mod3_auto_move);
        DEFAULT_PYRAMID_AUTO_MOVE = res.getBoolean(R.bool.default_pyramid_auto_move);
        DEFAULT_SINGLE_TAP_ALL_GAMES = res.getBoolean(R.bool.default_single_tap_all_games);
        DEFAULT_DEVELOPER_OPTION_NO_SAVING = res.getBoolean(R.bool.default_developer_option_no_saving);
        DEFAULT_SHOW_ADVANCED_SETTINGS = res.getBoolean(R.bool.default_show_advaced_settings);
        DEFAULT_SHOW_DIALOG_NEW_GAME = res.getBoolean(R.bool.default_show_dialog_new_game);
        DEFAULT_SHOW_DIALOG_REDEAL = res.getBoolean(R.bool.default_show_dialog_redeal);
        DEFAULT_SHOW_DIALOG_MIX_CARDS = res.getBoolean(R.bool.default_show_dialog_mix_cards);
        DEFAULT_HIDE_MENU_BAR = res.getBoolean(R.bool.default_hide_menu_bar);
        DEFAULT_IMMERSIVE_MODE = res.getBoolean(R.bool.default_immersive_mode);
        DEFAULT_HIDE_MENU_BUTTON = res.getBoolean(R.bool.default_hide_menu_button);
        DEFAULT_ENSURE_MOVABILITY = res.getBoolean(R.bool.default_ensure_movability);
        DEFAULT_IMPROVE_AUTO_MOVE = res.getBoolean(R.bool.default_improve_auto_move);
        DEFAULT_SETTINGS_ONLY_FOR_THIS_GAME = false;
        DEFAULT_CURRENT_GAME = res.getInteger(R.integer.default_current_game);
        DEFAULT_TEXT_COLOR = res.getInteger(R.integer.default_text_color);
        DEFAULT_MENU_COLUMNS_LANDSCAPE = res.getString(R.string.default_menu_columns_landscape);
        DEFAULT_MENU_COLUMNS_PORTRAIT = res.getString(R.string.default_menu_columns_portrait);
        DEFAULT_MENU_BAR_POSITION_LANDSCAPE = res.getString(R.string.default_menu_bar_position_landscape);
        DEFAULT_MENU_BAR_POSITION_PORTRAIT = res.getString(R.string.default_menu_bar_position_portrait);
        DEFAULT_FIRST_RUN = res.getBoolean(R.bool.default_first_run);
        DEFAULT_WON = res.getBoolean(R.bool.default_won);
        DEFAULT_HIDE_AUTOCOMPLETE_BUTTON = res.getBoolean(R.bool.default_hide_auto_complete_button);
        DEFAULT_WON_AND_RELOADED = res.getBoolean(R.bool.default_won_and_reloaded);
        DEFAULT_MOVED_FIRST_CARD = res.getBoolean(R.bool.default_moved_first_card);
        DEFAULT_4_COLOR_MODE = res.getBoolean(R.bool.default_4_color_mode);
        DEFAULT_DEVELOPER_OPTION_MOVE_CARDS_EVERYWHERE = res.getBoolean(R.bool.default_developer_option_move_cards_everywhere);
        DEFAULT_DEVELOPER_OPTION_PLAY_EVERY_CARD = res.getBoolean(R.bool.default_developer_option_play_every_card);
        DEFAULT_DEVELOPER_OPTION_INSTANT_WIN = res.getBoolean(R.bool.default_developer_option_instant_win);
        DEFAULT_DEVELOPER_OPTION_DEAL_CORRECT_SEQUENCES = res.getString(R.string.default_developer_option_deal_correct_sequences);
        DEFAULT_USE_TRUE_RANDOMISATION = res.getBoolean(R.bool.default_use_true_randomisation);
        DEFAULT_CARD_BACKGROUND = res.getInteger(R.integer.default_card_background);
        DEFAULT_GAME_LAYOUT_MARGINS_PORTRAIT = res.getInteger(R.integer.default_game_layout_margins_portrait);
        DEFAULT_GAME_LAYOUT_MARGINS_LANDSCAPE = res.getInteger(R.integer.default_game_layout_margins_landscape);
        DEFAULT_CARD_BACKGROUND_COLOR = res.getInteger(R.integer.default_card_background_color);
        DEFAULT_WINNING_TIME = res.getInteger(R.integer.default_winning_time);
        DEFAULT_BACKGROUND_COLOR_TYPE = res.getInteger(R.integer.default_background_color_type);
        DEFAULT_CANFIELD_SIZE_OF_RESERVE = res.getString(R.string.default_canfield_size_of_reserve);
        DEFAULT_BACKGROUND_COLOR = res.getString(R.string.default_background_color);
        DEFAULT_BACKGROUND_COLOR_CUSTOM = res.getInteger(R.integer.default_background_color_custom);
        DEFAULT_MOVEMENT_SPEED = res.getString(R.string.default_movement_speed);
        DEFAULT_SOUND_ENABLED = res.getBoolean(R.bool.default_sound_enabled);
        DEFAULT_FORCE_TABLET_LAYOUT = res.getBoolean(R.bool.default_force_tablet_layout);
        DEFAULT_WIN_SOUND = res.getString(R.string.default_win_sound);
        DEFAULT_BACKGROUND_MUSIC = res.getString(R.string.default_background_music);
        DEFAULT_BACKGROUND_VOLUME = res.getInteger(R.integer.default_background_volume);
        DEFAULT_VEGAS_BET_AMOUNT = res.getInteger(R.integer.default_vegas_bet_amount);
        DEFAULT_VEGAS_WIN_AMOUNT = res.getInteger(R.integer.default_vegas_win_amount);
        DEFAULT_VEGAS_MONEY = res.getInteger(R.integer.default_vegas_money);
        DEFAULT_ENSURE_MOVABILITY_MIN_MOVES = res.getInteger(R.integer.default_ensure_movability_min_moves);
        DEFAULT_MAX_NUMBER_UNDOS = res.getInteger(R.integer.default_max_number_undos);
        DEFAULT_PYRAMID_NUMBER_OF_RECYCLES = res.getString(R.string.default_pyramid_number_of_recycles);
        DEFAULT_FORTYEIGHT_NUMBER_OF_RECYCLES = res.getString(R.string.default_fortyeight_number_of_recycles);
        DEFAULT_VEGAS_NUMBER_OF_RECYCLES = res.getString(R.string.default_vegas_number_of_recycles);
        DEFAULT_KLONDIKE_NUMBER_OF_RECYCLES = res.getString(R.string.default_klondike_number_of_recycles);
        DEFAULT_PYRAMID_LIMITED_RECYCLES = res.getBoolean(R.bool.default_pyramid_limited_recycles);
        DEFAULT_FORTYEIGHT_LIMITED_RECYCLES = res.getBoolean(R.bool.default_fortyeight_limited_recycles);
        DEFAULT_DISABLE_UNDO_COSTS = res.getBoolean(R.bool.default_disable_undo_costs);
        DEFAULT_DISABLE_HINT_COSTS = res.getBoolean(R.bool.default_disable_hint_costs);
        DEFAULT_YUKON_RULES = res.getStringArray(R.array.pref_yukon_rules_values)[0];
        DEFAULT_KLONDIKE_DRAW = res.getStringArray(R.array.pref_draw_values)[0];
        DEFAULT_VEGAS_DRAW = res.getStringArray(R.array.pref_draw_values)[1];
        DEFAULT_CANFIELD_DRAW = res.getStringArray(R.array.pref_draw_values)[1];
        DEFAULT_NAPOLEONSTOMB_NUMBER_OF_RECYCLES = res.getString(R.string.default_napoleons_tomb_number_of_recycles);
    }

    private void putIntList(String name, List<Integer> list) {
        //Thanks to this answer for this idea http://stackoverflow.com/a/11201225/7016229

        StringBuilder s = new StringBuilder();
        for (int i : list) {
            s.append(i).append(",");
        }

        savedGameData.edit().putString(name, s.toString()).apply();
    }

    private void putLongList(String name, List<Long> list) {
        //Thanks to this answer for this idea http://stackoverflow.com/a/11201225/7016229

        StringBuilder s = new StringBuilder();
        for (long i : list) {
            s.append(i).append(",");
        }
        savedGameData.edit().putString(name, s.toString()).apply();
    }

    private void putSharedIntList(String name, List<Integer> list) {
        //
        StringBuilder s = new StringBuilder();
        for (int i : list) {
            s.append(i).append(",");
        }
        savedSharedData.edit().putString(name, s.toString()).apply();
    }

    private void putSharedStringList(String name, List<String> list) {
        //
        StringBuilder s = new StringBuilder();
        for (String i : list) {
            s.append(i).append(",");
        }
        savedSharedData.edit().putString(name, s.toString()).apply();
    }

    private ArrayList<Integer> getIntList(String name) {
        //Thanks to this answer for this idea http://stackoverflow.com/a/11201225/7016229

        String s = savedGameData.getString(name, "");
        StringTokenizer st = new StringTokenizer(s, ",");
        ArrayList<Integer> result = new ArrayList<>();

        while (st.hasMoreTokens()) {
            result.add(Integer.parseInt(st.nextToken()));
        }

        return result;
    }

    private ArrayList<Long> getLongList(String name) {
        //Thanks to this answer for this idea http://stackoverflow.com/a/11201225/7016229

        String s = savedGameData.getString(name, "");
        StringTokenizer st = new StringTokenizer(s, ",");
        ArrayList<Long> result = new ArrayList<>();

        while (st.hasMoreTokens()) {
            result.add(Long.parseLong(st.nextToken()));
        }

        return result;
    }

    private ArrayList<String> getStringList(String name) {
        String s = savedGameData.getString(name, "");
        StringTokenizer st = new StringTokenizer(s, ",");
        ArrayList<String> result = new ArrayList<>();

        while (st.hasMoreTokens()) {
            result.add(st.nextToken());
        }

        return result;
    }

    private ArrayList<Integer> getSharedIntList(String name) {
        String s = savedSharedData.getString(name, "");
        StringTokenizer st = new StringTokenizer(s, ",");
        ArrayList<Integer> result = new ArrayList<>();

        while (st.hasMoreTokens()) {
            result.add(Integer.parseInt(st.nextToken()));
        }

        return result;
    }

    private ArrayList<String> getSharedStringList(String name) {
        String s = savedSharedData.getString(name, "");
        StringTokenizer st = new StringTokenizer(s, ",");
        ArrayList<String> result = new ArrayList<>();

        while (st.hasMoreTokens()) {
            result.add(st.nextToken());
        }

        return result;
    }

    /**
     * need to ensure these settings already exist in the shared pref, or otherwise they getHighScore created
     * by the settings headers and the settings activity would do stuff, because it thinks the user changed
     * the values
     */
    public void setCriticalSettings() {
        saveLocale(getSavedLocale());
        saveForcedTabletLayout(getSavedForcedTabletLayout());
        saveShowExpertSettings(getShowAdvancedSettings());
        saveSingleTapAllGames(getSingleTapAllGames());
        saveTapToSelectEnabled(getSavedTapToSelectEnabled());
        saveLeftHandedMode(getSavedLeftHandedMode());
    }

    /**
     * see description of setCriticalSettings(). Without setting these before loading the settings-activity,
     * the activity would show toasts to start a new game. (Because the preferences getHighScore created and trigger
     * the toast notification)
     */
    public void setCriticalGameSettings() {
        saveCanfieldDrawMode(getSavedCanfieldDrawMode());
        saveKlondikeDrawMode(getSavedKlondikeDrawMode());
        saveVegasDrawMode(getSavedVegasDrawMode());
        saveSpiderDifficulty(getSavedSpiderDifficulty());
        saveSpideretteDifficulty(getSavedSpideretteDifficulty());
        saveYukonRules(getSavedYukonRules());
    }

    /* getters for individual game data */

    public long getSavedTotalTimePlayed() {
        return savedGameData.getLong(PREF_KEY_TOTAL_TIME_PLAYED, 0);
    }

    public long getSavedTotalPointsEarned() {
        return savedGameData.getLong(PREF_KEY_TOTAL_POINTS_EARNED, 0);
    }

    public long getSavedEndTime() {
        return savedGameData.getLong(PREF_KEY_TIMER_END_TIME, System.currentTimeMillis());
    }

    public long getSavedScore() {
        return savedGameData.getLong(PREF_KEY_SCORE, 0);
    }

    public long getSavedStartTime() {
        return savedGameData.getLong(PREF_KEY_TIMER_START_TIME, System.currentTimeMillis());
    }

    public long getSavedWinningTime() {
        return savedGameData.getLong(PREF_KEY_TIMER_WINNING_TIME, DEFAULT_WINNING_TIME);
    }

    public long getSavedVegasMoney() {
        return savedGameData.getLong(PREF_KEY_VEGAS_MONEY, DEFAULT_VEGAS_MONEY);
    }

    public long getSavedVegasOldScore() {
        return savedGameData.getLong(PREF_KEY_VEGAS_OLD_SCORE, 0);
    }

    public long getSavedVegasTime() {
        return savedGameData.getLong(PREF_KEY_VEGAS_TIME, 0);
    }

    public long[][] getSavedHighScores() {
        long savedScores[][] = new long[MAX_SAVED_SCORES][3];

        ArrayList<Long> listScores = getLongList(PREF_KEY_SAVED_SCORES + 0);
        ArrayList<Long> listTimes = getLongList(PREF_KEY_SAVED_SCORES + 1);
        ArrayList<Long> listDates = getLongList(PREF_KEY_SAVED_SCORES + 2);

        //for compatibility for older app versions, check the size of the saved data
        for (int i = 0; i < MAX_SAVED_SCORES; i++) {
            savedScores[i][0] = listScores.size() > i ? listScores.get(i) : 0;
            savedScores[i][1] = listTimes.size() > i ? listTimes.get(i) : 0;
            savedScores[i][2] = listDates.size() > i ? listDates.get(i) : 0;
        }

        return savedScores;
    }

    public long[][] getSavedRecentScores() {
        long savedScores[][] = new long[MAX_SAVED_SCORES][3];

        ArrayList<Long> listScores = getLongList(PREF_KEY_SAVED_RECENT_SCORES + 0);
        ArrayList<Long> listTimes = getLongList(PREF_KEY_SAVED_RECENT_SCORES + 1);
        ArrayList<Long> listDates = getLongList(PREF_KEY_SAVED_RECENT_SCORES + 2);

        //for compatibility for older app versions, check the size of the saved data
        for (int i = 0; i < MAX_SAVED_SCORES; i++) {
            savedScores[i][0] = listScores.size() > i ? listScores.get(i) : 0;
            savedScores[i][1] = listTimes.size() > i ? listTimes.get(i) : 0;
            savedScores[i][2] = listDates.size() > i ? listDates.get(i) : 0;
        }

        return savedScores;
    }

    public int getSavedTotalNumberUndos() {
        return savedGameData.getInt(PREF_KEY_TOTAL_NUMBER_UNDOS, 0);
    }

    public int getSavedTotalHintsShown() {
        return savedGameData.getInt(PREF_KEY_TOTAL_HINTS_SHOWN, 0);
    }

    public int getSavedRecycleCounter(int total) {
        return savedGameData.getInt(PREF_KEY_GAME_REDEAL_COUNT, total);
    }

    public int getSavedLongestRun() {
        return savedGameData.getInt(PREF_KEY_LONGEST_RUN, 0);
    }

    public int getSavedRunCounter() {
        return savedGameData.getInt(PREF_KEY_RUN_COUNTER, 0);
    }

    public int getSavedNumberOfPlayedGames() {
        return savedGameData.getInt(PREF_KEY_GAME_NUMBER_OF_PLAYED_GAMES, getSavedNumberOfWonGames());
    }

    public int getSavedNumberOfWonGames() {
        return savedGameData.getInt(PREF_KEY_GAME_NUMBER_OF_WON_GAMES, 0);
    }

    public int getSavedEnsureMovabilityMinMoves() {
        return savedGameData.getInt(PREF_KEY_ENSURE_MOVABILITY_MIN_MOVES, DEFAULT_ENSURE_MOVABILITY_MIN_MOVES);
    }

    public int getSavedRecordListEntriesSize() {
        return savedGameData.getInt(PREF_KEY_RECORD_LIST_ENTRIES_SIZE, -1);
    }

    public int getSavedFlipCardId(String pos) {
        return savedGameData.getInt(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_FLIP_CARD, -1);
    }

    public boolean isFirstRun() {
        return savedGameData.getBoolean(PREF_KEY_GAME_FIRST_RUN, DEFAULT_FIRST_RUN);
    }

    public boolean hasSettingsOnlyForThisGame() {
        return (prefs.getSavedCurrentGame() != DEFAULT_CURRENT_GAME)
                && savedGameData.getBoolean(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME, DEFAULT_SETTINGS_ONLY_FOR_THIS_GAME);
    }

    public boolean isDealingCards() {
        return savedGameData.getBoolean(PREF_KEY_DEALING_CARDS, false);
    }

    public boolean isWon() {
        return savedGameData.getBoolean(PREF_KEY_GAME_WON, DEFAULT_WON);
    }

    public boolean isWonAndReloaded() {
        return savedGameData.getBoolean(PREF_KEY_GAME_WON_AND_RELOADED, DEFAULT_WON_AND_RELOADED);
    }

    public boolean hasMovedFirstCard() {
        return savedGameData.getBoolean(PREF_KEY_GAME_MOVED_FIRST_CARD, DEFAULT_MOVED_FIRST_CARD);
    }

    public boolean isDeveloperOptionMoveCardsEverywhereEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_DEVELOPER_OPTION_MOVE_CARDS_EVERYWHERE, DEFAULT_DEVELOPER_OPTION_MOVE_CARDS_EVERYWHERE);
    }

    public boolean isDeveloperOptionPlayEveryCardEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_DEVELOPER_OPTION_PLAY_EVERY_CARD, DEFAULT_DEVELOPER_OPTION_PLAY_EVERY_CARD);
    }

    public boolean isDeveloperOptionInstantWinEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_DEVELOPER_OPTION_INSTANT_WIN, DEFAULT_DEVELOPER_OPTION_INSTANT_WIN);
    }

    public boolean isDeveloperOptionSavingDisabled() {
        return savedSharedData.getBoolean(PREF_KEY_DEVELOPER_OPTION_NO_SAVING, DEFAULT_DEVELOPER_OPTION_NO_SAVING);
    }

    public int getDeveloperOptionDealCorrectSequences() {
        String value = savedSharedData.getString(PREF_KEY_DEVELOPER_OPTION_DEAL_CORRECT_SEQUENCES, DEFAULT_DEVELOPER_OPTION_DEAL_CORRECT_SEQUENCES);
        return Integer.parseInt(value);
    }

    public ArrayList<Integer> getSavedCards() {
        return getIntList(PREF_KEY_CARDS);
    }

    public ArrayList<Integer> getSavedStacks(int id) {
        return getIntList(PREF_KEY_STACK + id);
    }

    public ArrayList<Integer> getSavedRandomCards() {
        return getIntList(PREF_KEY_GAME_RANDOM_CARDS);
    }

    public ArrayList<Integer> getSavedRecordListCards(String pos) {
        return getIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_CARD);
    }

    public ArrayList<Integer> getSavedRecordListOrigins(String pos) {
        return getIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_ORIGIN);
    }

    public ArrayList<Integer> getSavedRecordListOrders(String pos) {
        return getIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_ORDER);
    }

    public ArrayList<Integer> getSavedRecordListFlipCards(String pos) {
        return getIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_FLIP_CARD);
    }

    /* setters for individual game data */

    public void saveTotalPointsEarned(long value) {
        savedGameData.edit().putLong(PREF_KEY_TOTAL_POINTS_EARNED, value).apply();
    }

    public void saveTotalTimePlayed(long value) {
        savedGameData.edit().putLong(PREF_KEY_TOTAL_TIME_PLAYED, value).apply();
    }

    public void saveScore(long value) {
        savedGameData.edit().putLong(PREF_KEY_SCORE, value).apply();
    }

    public void saveStartTime(long value) {
        savedGameData.edit().putLong(PREF_KEY_TIMER_START_TIME, value).apply();
    }

    public void saveEndTime(long value) {
        savedGameData.edit().putLong(PREF_KEY_TIMER_END_TIME, value).apply();
    }

    public void saveWinningTime(long value) {
        savedGameData.edit().putLong(PREF_KEY_TIMER_WINNING_TIME, value).apply();
    }

    public void saveVegasMoney(long value) {
        savedGameData.edit().putLong(PREF_KEY_VEGAS_MONEY, value).apply();
    }

    public void saveVegasOldScore(long value) {
        savedGameData.edit().putLong(PREF_KEY_VEGAS_OLD_SCORE, value).apply();
    }

    public void saveVegasTime(long value) {
        savedGameData.edit().putLong(PREF_KEY_VEGAS_TIME, value).apply();
    }

    public void saveHighScores(long savedScores[][]) {
        ArrayList<Long> listScores = new ArrayList<>();
        ArrayList<Long> listTimes = new ArrayList<>();
        ArrayList<Long> listDates = new ArrayList<>();

        for (int i = 0; i < MAX_SAVED_SCORES; i++) {
            listScores.add(savedScores[i][0]);
            listTimes.add(savedScores[i][1]);
            listDates.add(savedScores[i][2]);
        }

        putLongList(PREF_KEY_SAVED_SCORES + 0, listScores);
        putLongList(PREF_KEY_SAVED_SCORES + 1, listTimes);
        putLongList(PREF_KEY_SAVED_SCORES + 2, listDates);
    }

    public void saveRecentScores(long savedScores[][]) {
        ArrayList<Long> listScores = new ArrayList<>();
        ArrayList<Long> listTimes = new ArrayList<>();
        ArrayList<Long> listDates = new ArrayList<>();

        for (int i = 0; i < MAX_SAVED_SCORES; i++) {
            listScores.add(savedScores[i][0]);
            listTimes.add(savedScores[i][1]);
            listDates.add(savedScores[i][2]);
        }

        putLongList(PREF_KEY_SAVED_RECENT_SCORES + 0, listScores);
        putLongList(PREF_KEY_SAVED_RECENT_SCORES + 1, listTimes);
        putLongList(PREF_KEY_SAVED_RECENT_SCORES + 2, listDates);
    }

    public void saveTotalNumberUndos(int value) {
        savedGameData.edit().putInt(PREF_KEY_TOTAL_NUMBER_UNDOS, value).apply();
    }

    public void saveTotalHintsShown(int value) {
        savedGameData.edit().putInt(PREF_KEY_TOTAL_HINTS_SHOWN, value).apply();
    }

    public void saveRedealCount(int value) {
        savedGameData.edit().putInt(PREF_KEY_GAME_REDEAL_COUNT, value).apply();
    }

    public void saveEnsureMovabilityMinMoves(int value) {
        savedGameData.edit().putInt(PREF_KEY_ENSURE_MOVABILITY_MIN_MOVES, value).apply();
    }

    public void saveLongestRun(int value) {
        savedGameData.edit().putInt(PREF_KEY_LONGEST_RUN, value).apply();
    }

    public void saveRunCounter(int value) {
        savedGameData.edit().putInt(PREF_KEY_RUN_COUNTER, value).apply();
    }

    public void saveNumberOfWonGames(int value) {
        savedGameData.edit().putInt(PREF_KEY_GAME_NUMBER_OF_WON_GAMES, value).apply();
    }

    public void saveNumberOfPlayedGames(int value) {
        savedGameData.edit().putInt(PREF_KEY_GAME_NUMBER_OF_PLAYED_GAMES, value).apply();
    }

    public void saveRecordListEntriesSize(int value) {
        savedGameData.edit().putInt(PREF_KEY_RECORD_LIST_ENTRIES_SIZE, value).apply();
    }

    public void setSettingsOnlyForThisGame(boolean value) {
        savedGameData.edit().putBoolean(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME, value).apply();
    }

    public void saveFirstRun(boolean value) {
        savedGameData.edit().putBoolean(PREF_KEY_GAME_FIRST_RUN, value).apply();
    }

    public void setDealingCards(boolean value) {
        savedGameData.edit().putBoolean(PREF_KEY_DEALING_CARDS, value).apply();
    }

    public void saveWon(boolean value) {
        savedGameData.edit().putBoolean(PREF_KEY_GAME_WON, value).apply();
    }

    public void saveWonAndReloaded(boolean value) {
        savedGameData.edit().putBoolean(PREF_KEY_GAME_WON_AND_RELOADED, value).apply();
    }

    public void saveMovedFirstCard(boolean value) {
        savedGameData.edit().putBoolean(PREF_KEY_GAME_MOVED_FIRST_CARD, value).apply();
    }

    public void saveCards(List<Integer> list) {
        putIntList(PREF_KEY_CARDS, list);
    }

    public void saveStacks(ArrayList<Integer> list, int id) {
        putIntList(PREF_KEY_STACK + id, list);
    }

    public void saveRandomCards(ArrayList<Integer> list) {
        putIntList(PREF_KEY_GAME_RANDOM_CARDS, list);
    }

    public void saveRecordListCards(ArrayList<Integer> list, String pos) {
        putIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_CARD, list);
    }

    public void saveRecordListOrigins(ArrayList<Integer> list, String pos) {
        putIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_ORIGIN, list);
    }

    public void saveRecordListOrders(ArrayList<Integer> list, String pos) {
        putIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_ORDER, list);
    }

    public void saveRecordListFlipCards(ArrayList<Integer> list, String pos) {
        putIntList(PREF_KEY_RECORD_LIST_ENTRY + pos + PREF_KEY_FLIP_CARD, list);
    }

    /* getters for shared data */

    public int getSavedGameLayoutMarginsPortrait() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT, DEFAULT_GAME_LAYOUT_MARGINS_PORTRAIT);
        } else {
            return savedSharedData.getInt(PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT, DEFAULT_GAME_LAYOUT_MARGINS_PORTRAIT);
        }
    }

    public int getSavedGameLayoutMarginsLandscape() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE, DEFAULT_GAME_LAYOUT_MARGINS_LANDSCAPE);
        } else {
            return savedSharedData.getInt(PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE, DEFAULT_GAME_LAYOUT_MARGINS_LANDSCAPE);
        }
    }

    public int getSavedCardBackground() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_CARD_BACKGROUND, DEFAULT_CARD_BACKGROUND);
        } else {
            return savedSharedData.getInt(PREF_KEY_CARD_BACKGROUND, DEFAULT_CARD_BACKGROUND);
        }
    }

    public int getSavedCardBackgroundColor() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_CARD_BACKGROUND_COLOR, DEFAULT_CARD_BACKGROUND_COLOR);
        } else {
            return savedSharedData.getInt(PREF_KEY_CARD_BACKGROUND_COLOR, DEFAULT_CARD_BACKGROUND_COLOR);
        }
    }

    public int getSavedBackgroundColorType() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_BACKGROUND_COLOR_TYPE, DEFAULT_BACKGROUND_COLOR_TYPE);
        } else {
            return savedSharedData.getInt(PREF_KEY_BACKGROUND_COLOR_TYPE, DEFAULT_BACKGROUND_COLOR_TYPE);
        }
    }

    public int getSavedBackgroundCustomColor() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_BACKGROUND_COLOR_CUSTOM, DEFAULT_BACKGROUND_COLOR_CUSTOM);
        } else {
            return savedSharedData.getInt(PREF_KEY_BACKGROUND_COLOR_CUSTOM, DEFAULT_BACKGROUND_COLOR_CUSTOM);
        }
    }

    public int getSavedCardTheme() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_CARD_DRAWABLES, 1);
        } else {
            return savedSharedData.getInt(PREF_KEY_CARD_DRAWABLES, 1);
        }
    }

    public int getSavedBackgroundVolume() {
        return savedSharedData.getInt(PREF_KEY_BACKGROUND_VOLUME, DEFAULT_BACKGROUND_VOLUME);
    }

    public int getSavedVegasBetAmount() {
        return savedSharedData.getInt(PREF_KEY_VEGAS_BET_AMOUNT, DEFAULT_VEGAS_BET_AMOUNT);
    }

    public int getSavedVegasWinAmount() {
        return savedSharedData.getInt(PREF_KEY_VEGAS_WIN_AMOUNT, DEFAULT_VEGAS_WIN_AMOUNT);
    }

    public int getSavedVegasBetAmountOld() {
        return savedSharedData.getInt(PREF_KEY_VEGAS_BET_AMOUNT_OLD, DEFAULT_VEGAS_BET_AMOUNT);
    }

    public int getSavedVegasWinAmountOld() {
        return savedSharedData.getInt(PREF_KEY_VEGAS_WIN_AMOUNT_OLD, DEFAULT_VEGAS_WIN_AMOUNT);
    }

    public int getSavedCurrentGame() {
        return savedSharedData.getInt(PREF_KEY_CURRENT_GAME, DEFAULT_CURRENT_GAME);
    }

    public int getSavedOrientation() {
        return Integer.parseInt(savedSharedData.getString(PREF_KEY_ORIENTATION, DEFAULT_ORIENTATION));
    }

    public int getSavedBackgroundColor() {
        if (hasSettingsOnlyForThisGame()) {
            return Integer.parseInt(savedGameData.getString(PREF_KEY_BACKGROUND_COLOR, DEFAULT_BACKGROUND_COLOR));
        } else {
            return Integer.parseInt(savedSharedData.getString(PREF_KEY_BACKGROUND_COLOR, DEFAULT_BACKGROUND_COLOR));
        }
    }

    public int getSavedTextColor() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getInt(PREF_KEY_TEXT_COLOR, DEFAULT_TEXT_COLOR);
        } else {
            return savedSharedData.getInt(PREF_KEY_TEXT_COLOR, DEFAULT_TEXT_COLOR);
        }
    }

    public int getSavedMenuColumnsPortrait() {
        return Integer.parseInt(savedSharedData.getString(PREF_KEY_MENU_COLUMNS_PORTRAIT, DEFAULT_MENU_COLUMNS_PORTRAIT));
    }

    public int getSavedMenuColumnsLandscape() {
        return Integer.parseInt(savedSharedData.getString(PREF_KEY_MENU_COLUMNS_LANDSCAPE, DEFAULT_MENU_COLUMNS_LANDSCAPE));
    }

    public int getSavedNumberOfRecycles(String Key, String defaulValue) {
        return Integer.parseInt(savedSharedData.getString(Key, defaulValue));
    }

    public int getSavedCanfieldSizeOfReserve() {
        return Integer.parseInt(savedSharedData.getString(PREF_KEY_CANFIELD_SIZE_OF_RESERVE, DEFAULT_CANFIELD_SIZE_OF_RESERVE));
    }

    public float getSavedMovementSpeed() {
        return Float.parseFloat(savedSharedData.getString(PREF_KEY_MOVEMENT_SPEED, DEFAULT_MOVEMENT_SPEED));
    }

    public int getSavedMaxNumberUndos() {
        return savedSharedData.getInt(PREF_KEY_MAX_NUMBER_UNDOS, DEFAULT_MAX_NUMBER_UNDOS);
    }

    public String getSavedBackgroundMusic() {
        return savedSharedData.getString(PREF_KEY_BACKGROUND_MUSIC, DEFAULT_BACKGROUND_MUSIC);
    }

    public String getSavedLocale() {
        return savedSharedData.getString(PREF_KEY_LANGUAGE, DEFAULT_LANGUAGE);
    }

    public String getSavedCanfieldDrawMode() {
        return savedSharedData.getString(PREF_KEY_CANFIELD_DRAW, DEFAULT_CANFIELD_DRAW);
    }

    public String getSavedCanfieldDrawModeOld() {
        return savedSharedData.getString(PREF_KEY_CANFIELD_DRAW_OLD, DEFAULT_CANFIELD_DRAW);
    }

    public String getSavedKlondikeDrawMode() {
        return savedSharedData.getString(PREF_KEY_KLONDIKE_DRAW, DEFAULT_KLONDIKE_DRAW);
    }

    public String getSavedVegasDrawMode() {
        return savedSharedData.getString(PREF_KEY_VEGAS_DRAW, DEFAULT_VEGAS_DRAW);
    }

    public String getSavedKlondikeVegasDrawModeOld(int which) {
        if (which == 1) {
            return savedSharedData.getString(PREF_KEY_KLONDIKE_DRAW_OLD, DEFAULT_KLONDIKE_DRAW);
        } else {
            return savedSharedData.getString(PREF_KEY_VEGAS_DRAW_OLD, DEFAULT_VEGAS_DRAW);
        }
    }

    public String getSavedSpiderDifficulty() {
        return savedSharedData.getString(PREF_KEY_SPIDER_DIFFICULTY, DEFAULT_SPIDER_DIFFICULTY);
    }

    public String getSavedSpiderDifficultyOld() {
        return savedSharedData.getString(PREF_KEY_SPIDER_DIFFICULTY_OLD, DEFAULT_SPIDER_DIFFICULTY);
    }

    public String getSavedSpideretteDifficulty() {
        return savedSharedData.getString(PREF_KEY_SPIDERETTE_DIFFICULTY, DEFAULT_SPIDERETTE_DIFFICULTY);
    }

    public String getSavedSpideretteDifficultyOld() {
        return savedSharedData.getString(PREF_KEY_SPIDERETTE_DIFFICULTY_OLD, DEFAULT_SPIDERETTE_DIFFICULTY);
    }

    public String getSavedYukonRules() {
        return savedSharedData.getString(PREF_KEY_YUKON_RULES, DEFAULT_YUKON_RULES);
    }

    public String getSavedYukonRulesOld() {
        return savedSharedData.getString(PREF_KEY_YUKON_RULES_OLD, DEFAULT_YUKON_RULES);
    }

    public String getSavedMenuBarPosPortrait() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getString(PREF_KEY_MENU_BAR_POS_PORTRAIT, DEFAULT_MENU_BAR_POSITION_PORTRAIT);
        } else {
            return savedSharedData.getString(PREF_KEY_MENU_BAR_POS_PORTRAIT, DEFAULT_MENU_BAR_POSITION_PORTRAIT);
        }
    }

    public String getSavedMenuBarPosLandscape() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getString(PREF_KEY_MENU_BAR_POS_LANDSCAPE, DEFAULT_MENU_BAR_POSITION_LANDSCAPE);
        } else {
            return savedSharedData.getString(PREF_KEY_MENU_BAR_POS_LANDSCAPE, DEFAULT_MENU_BAR_POSITION_LANDSCAPE);
        }

    }

    public String getSavedPyramidDifficulty() {
        return savedSharedData.getString(PREF_KEY_PYRAMID_DIFFICULTY, DEFAULT_PYRAMID_DIFFICULTY);
    }

    public String getSavedWinSound() {
        return savedSharedData.getString(PREF_KEY_WIN_SOUND, DEFAULT_WIN_SOUND);
    }

    public boolean getSavedForcedTabletLayout() {
        return savedSharedData.getBoolean(PREF_KEY_FORCE_TABLET_LAYOUT, DEFAULT_FORCE_TABLET_LAYOUT);
    }

    public boolean getSavedLeftHandedMode() {
        return savedSharedData.getBoolean(PREF_KEY_LEFT_HANDED_MODE, DEFAULT_LEFT_HANDED_MODE);
    }

    public boolean getSavedFourColorMode() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getBoolean(PREF_KEY_4_COLOR_MODE, DEFAULT_4_COLOR_MODE);
        } else {
            return savedSharedData.getBoolean(PREF_KEY_4_COLOR_MODE, DEFAULT_4_COLOR_MODE);
        }
    }

    public boolean getSavedHideStatusBar() {
        return savedSharedData.getBoolean(PREF_KEY_HIDE_STATUS_BAR, false);
    }

    public boolean getSavedStatisticsHideWinPercentage() {
        return savedSharedData.getBoolean(PREF_KEY_STATISTICS_HIDE_WIN_PERCENTAGE, DEFAULT_STATISTICS_HIDE_WIN_PERCENTAGE);
    }

    public boolean getHideMenuButton() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getBoolean(PREF_KEY_HIDE_MENU_BUTTON, DEFAULT_HIDE_MENU_BUTTON);
        } else {
            return savedSharedData.getBoolean(PREF_KEY_HIDE_MENU_BUTTON, DEFAULT_HIDE_MENU_BUTTON);
        }
    }

    public boolean getHideAutoCompleteButton() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getBoolean(PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON, DEFAULT_HIDE_AUTOCOMPLETE_BUTTON);
        } else {
            return savedSharedData.getBoolean(PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON, DEFAULT_HIDE_AUTOCOMPLETE_BUTTON);
        }
    }

    public boolean getSavedCalculationAlternativeMode() {
        return savedSharedData.getBoolean(PREF_KEY_CALCULATION_ALTERNATIVE, DEFAULT_CALCULATION_ALTERNATIVE);
    }

    public boolean getSavedCalculationAlternativeModeOld() {
        return savedSharedData.getBoolean(PREF_KEY_CALCULATION_ALTERNATIVE_OLD, DEFAULT_CALCULATION_ALTERNATIVE);
    }

    public boolean getSavedFortyEightLimitedRecycles() {
        return savedSharedData.getBoolean(PREF_KEY_FORTYEIGHT_LIMITED_RECYCLES, DEFAULT_FORTYEIGHT_LIMITED_RECYCLES);
    }

    public boolean getSavedGoldCyclic() {
        return savedSharedData.getBoolean(PREF_KEY_GOLF_CYCLIC, DEFAULT_GOLF_CYCLIC);
    }

    public boolean getSavedImmersiveMode() {
        return savedSharedData.getBoolean(PREF_KEY_IMMERSIVE_MODE, DEFAULT_IMMERSIVE_MODE);
    }

    public boolean getSavedKlondikeLimitedRecycles() {
        return savedSharedData.getBoolean(PREF_KEY_KLONDIKE_LIMITED_RECYCLES, DEFAULT_KLONDIKE_LIMITED_RECYCLES);
    }

    public boolean getSavedMod3AutoMove() {
        return savedSharedData.getBoolean(PREF_KEY_MOD3_AUTO_MOVE, DEFAULT_MOD3_AUTO_MOVE);
    }

    public boolean getSavedPyramidLimitedRecycles() {
        return savedSharedData.getBoolean(PREF_KEY_PYRAMID_LIMITED_RECYCLES, DEFAULT_PYRAMID_LIMITED_RECYCLES);
    }

    public boolean getSavedPyramidAutoMove() {
        return savedSharedData.getBoolean(PREF_KEY_PYRAMID_AUTO_MOVE, DEFAULT_PYRAMID_AUTO_MOVE);
    }

    public boolean getSavedVegasSaveMoneyEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_VEGAS_MONEY_ENABLED, DEFAULT_VEGAS_MONEY_ENABLED);
    }

    public boolean getSavedVegasResetMoney() {
        return savedSharedData.getBoolean(PREF_KEY_VEGAS_RESET_MONEY, DEFAULT_VEGAS_RESET_MONEY);
    }

    public boolean getSavedHideTime() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getBoolean(PREF_KEY_HIDE_TIME, DEFAULT_HIDE_TIME);
        } else {
            return savedSharedData.getBoolean(PREF_KEY_HIDE_TIME, DEFAULT_HIDE_TIME);
        }
    }

    public boolean getSavedHideScore() {
        if (hasSettingsOnlyForThisGame()) {
            return savedGameData.getBoolean(PREF_KEY_HIDE_SCORE, DEFAULT_HIDE_SCORE);
        } else {
            return savedSharedData.getBoolean(PREF_KEY_HIDE_SCORE, DEFAULT_HIDE_SCORE);
        }
    }

    public boolean getSavedAutoStartNewGame() {
        return savedSharedData.getBoolean(PREF_KEY_AUTO_START_NEW_GAME, DEFAULT_AUTO_START_NEW_GAME);
    }

    public boolean getSavedTapToSelectEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_TAP_TO_SELECT_ENABLED, DEFAULT_TAP_TO_SELECT_ENABLED);
    }

    public boolean getSavedDoubleTapEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_DOUBLE_TAP_ENABLED, DEFAULT_DOUBLE_TAP_ENABLE);
    }

    public boolean getSavedDoubleTapAllCards() {
        return savedSharedData.getBoolean(PREF_KEY_DOUBLE_TAP_ALL_CARDS, DEFAULT_DOUBLE_TAP_ALL_CARDS);
    }

    public boolean getShowAdvancedSettings() {
        return savedSharedData.getBoolean(PREF_KEY_SHOW_ADVANCED_SETTINGS, DEFAULT_SHOW_ADVANCED_SETTINGS);
    }

    public boolean getSavedDoubleTapFoundationFirst() {
        return savedSharedData.getBoolean(PREF_KEY_DOUBLE_TAP_FOUNDATION_FIRST, DEFAULT_DOUBLE_TAP_FOUNDATION_FIRST);
    }

    public boolean getSavedEnsureMovability() {
        return savedSharedData.getBoolean(PREF_KEY_ENSURE_MOVABILITY, DEFAULT_ENSURE_MOVABILITY);
    }

    public boolean getSavedSingleTapSpecialGames() {
        return savedSharedData.getBoolean(PREF_KEY_SINGLE_TAP_SPECIAL_GAMES, DEFAULT_SINGLE_TAP_SPECIAL_GAMES_ENABLED);
    }

    public boolean getSavedStartWithMenu() {
        return savedSharedData.getBoolean(PREF_KEY_START_WITH_MENU, false);
    }

    public boolean getSavedSoundEnabled() {
        return savedSharedData.getBoolean(PREF_KEY_SOUND_ENABLED, DEFAULT_SOUND_ENABLED);
    }

    public boolean getSingleTapAllGames() {
        return savedSharedData.getBoolean(PREF_KEY_SINGLE_TAP_ALL_GAMES, DEFAULT_SINGLE_TAP_ALL_GAMES);
    }

    public boolean getSavedUseTrueRandomisation() {
        return savedSharedData.getBoolean(PREF_KEY_USE_TRUE_RANDOMISATION, DEFAULT_USE_TRUE_RANDOMISATION);
    }

    public boolean getShowDialogNewGame() {
        return savedSharedData.getBoolean(PREF_KEY_SHOW_DIALOG_NEW_GAME, DEFAULT_SHOW_DIALOG_NEW_GAME);
    }

    public boolean getShowDialogRedeal() {
        return savedSharedData.getBoolean(PREF_KEY_SHOW_DIALOG_REDEAL, DEFAULT_SHOW_DIALOG_REDEAL);
    }

    public boolean getShowDialogMixCards() {
        return savedSharedData.getBoolean(PREF_KEY_SHOW_DIALOG_MIX_CARDS, DEFAULT_SHOW_DIALOG_MIX_CARDS);
    }

    public boolean getDisableUndoCosts() {
        return savedSharedData.getBoolean(PREF_KEY_DISABLE_UNDO_COSTS, DEFAULT_DISABLE_UNDO_COSTS);
    }

    public boolean getDisableHintCosts() {
        return savedSharedData.getBoolean(PREF_KEY_DISABLE_HINT_COSTS, DEFAULT_DISABLE_HINT_COSTS);
    }

    public boolean getHideMenuBar() {
        return savedSharedData.getBoolean(PREF_KEY_HIDE_MENU_BAR, DEFAULT_HIDE_MENU_BAR);
    }

    public boolean getImproveAutoMove() {
        return savedSharedData.getBoolean(PREF_KEY_IMPROVE_AUTO_MOVE, DEFAULT_IMPROVE_AUTO_MOVE);
    }

    public ArrayList<Integer> getSavedMenuGamesList() {
        return getSharedIntList(PREF_KEY_MENU_GAMES);
    }

    public ArrayList<Integer> getSavedMenuOrderList() {
        return getSharedIntList(PREF_KEY_MENU_ORDER);
    }

    /* setters for shared data */

    public void saveYukonRulesOld() {
        savedSharedData.edit().putString(PREF_KEY_YUKON_RULES_OLD, getSavedYukonRules()).apply();
    }

    public void saveBackgroundColorType(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_BACKGROUND_COLOR_TYPE, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_BACKGROUND_COLOR_TYPE, value).apply();
        }
    }

    public void saveBackgroundCustomColor(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_BACKGROUND_COLOR_CUSTOM, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_BACKGROUND_COLOR_CUSTOM, value).apply();
        }
    }

    public void saveCardBackground(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_CARD_BACKGROUND, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_CARD_BACKGROUND, value).apply();
        }
    }

    public void saveCardBackgroundColor(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_CARD_BACKGROUND_COLOR, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_CARD_BACKGROUND_COLOR, value).apply();
        }
    }

    public void saveCardTheme(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_CARD_DRAWABLES, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_CARD_DRAWABLES, value).apply();
        }
    }

    public void saveBackgroundVolume(int value) {
        savedSharedData.edit().putInt(PREF_KEY_BACKGROUND_VOLUME, value).apply();
    }

    public void saveVegasBetAmount(int value) {
        savedSharedData.edit().putInt(PREF_KEY_VEGAS_BET_AMOUNT, value).apply();
    }

    public void saveVegasWinAmount(int value) {
        savedSharedData.edit().putInt(PREF_KEY_VEGAS_WIN_AMOUNT, value).apply();
    }

    public void saveGameLayoutMarginsPortrait(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT, value).apply();
        }
    }

    public void saveGameLayoutMarginsLandscape(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE, value).apply();
        }
    }

    public void saveVegasBetAmountOld() {
        savedSharedData.edit().putInt(PREF_KEY_VEGAS_BET_AMOUNT_OLD, getSavedVegasBetAmount()).apply();
    }

    public void saveVegasWinAmountOld() {
        savedSharedData.edit().putInt(PREF_KEY_VEGAS_WIN_AMOUNT_OLD, getSavedVegasWinAmount()).apply();
    }

    public void saveCurrentGame(int value) {
        savedSharedData.edit().putInt(PREF_KEY_CURRENT_GAME, value).apply();
    }

    public void saveLocale(String locale) {
        savedSharedData.edit().putString(PREF_KEY_LANGUAGE, locale).apply();
    }

    public void saveCanfieldDrawMode(String value) {
        savedSharedData.edit().putString(PREF_KEY_CANFIELD_DRAW, value).apply();
    }

    public void saveCanfieldDrawModeOld() {
        savedSharedData.edit().putString(PREF_KEY_CANFIELD_DRAW_OLD, getSavedCanfieldDrawMode()).apply();
    }

    public void saveKlondikeDrawMode(String value) {
        savedSharedData.edit().putString(PREF_KEY_KLONDIKE_DRAW, value).apply();
    }

    public void saveKlondikeVegasDrawModeOld(int which) {
        if (which == 1) {
            savedSharedData.edit().putString(PREF_KEY_KLONDIKE_DRAW_OLD, getSavedKlondikeDrawMode()).apply();
        } else {
            savedSharedData.edit().putString(PREF_KEY_VEGAS_DRAW_OLD, getSavedVegasDrawMode()).apply();
        }
    }

    public void saveVegasDrawMode(String value) {
        savedSharedData.edit().putString(PREF_KEY_VEGAS_DRAW, value).apply();
    }

    public void saveSpiderDifficulty(String value) {
        savedSharedData.edit().putString(PREF_KEY_SPIDER_DIFFICULTY, value).apply();
    }

    public void saveSpiderDifficultyOld() {
        savedSharedData.edit().putString(PREF_KEY_SPIDER_DIFFICULTY_OLD, getSavedSpiderDifficulty()).apply();
    }

    public void saveSpideretteDifficulty(String value) {
        savedSharedData.edit().putString(PREF_KEY_SPIDERETTE_DIFFICULTY, value).apply();
    }

    public void saveSpideretteDifficultyOld() {
        savedSharedData.edit().putString(PREF_KEY_SPIDERETTE_DIFFICULTY_OLD, getSavedSpideretteDifficulty()).apply();
    }

    public void saveYukonRules(String value) {
        savedSharedData.edit().putString(PREF_KEY_YUKON_RULES, value).apply();
    }

    public void saveCalculationAlternativeModeOld() {
        savedSharedData.edit().putBoolean(PREF_KEY_CALCULATION_ALTERNATIVE_OLD, getSavedCalculationAlternativeMode()).apply();
    }

    public void saveForcedTabletLayout(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_FORCE_TABLET_LAYOUT, value).apply();
    }

    public void saveShowExpertSettings(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_SHOW_ADVANCED_SETTINGS, value).apply();
    }

    public void saveHideMenuBar(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_HIDE_MENU_BAR, value).apply();
    }

    public void saveStatisticsHideWinPercentage(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_STATISTICS_HIDE_WIN_PERCENTAGE, value).apply();
    }

    public void saveBackgroundColor(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putString(PREF_KEY_BACKGROUND_COLOR, Integer.toString(value)).apply();
        } else {
            savedSharedData.edit().putString(PREF_KEY_BACKGROUND_COLOR, Integer.toString(value)).apply();
        }
    }

    public void saveMaxNumberUndos(int value) {
        savedSharedData.edit().putInt(PREF_KEY_MAX_NUMBER_UNDOS, value).apply();
    }

    public void saveTextColor(int value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putInt(PREF_KEY_TEXT_COLOR, value).apply();
        } else {
            savedSharedData.edit().putInt(PREF_KEY_TEXT_COLOR, value).apply();
        }
    }

    public void saveMenuBarPosPortrait(String value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putString(PREF_KEY_MENU_BAR_POS_PORTRAIT, value).apply();
        } else {
            savedSharedData.edit().putString(PREF_KEY_MENU_BAR_POS_PORTRAIT, value).apply();
        }
    }

    public void saveMenuBarPosLandscape(String value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putString(PREF_KEY_MENU_BAR_POS_LANDSCAPE, value).apply();
        } else {
            savedSharedData.edit().putString(PREF_KEY_MENU_BAR_POS_LANDSCAPE, value).apply();
        }
    }

    public void saveMenuColumnsPortrait(String value) {
        savedSharedData.edit().putString(PREF_KEY_MENU_COLUMNS_PORTRAIT, value).apply();
    }

    public void saveMenuColumnsLandscape(String value) {
        savedSharedData.edit().putString(PREF_KEY_MENU_COLUMNS_LANDSCAPE, value).apply();
    }

    public void saveVegasResetMoney(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_VEGAS_RESET_MONEY, value).apply();
    }

    public void saveSingleTapAllGames(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_SINGLE_TAP_ALL_GAMES, value).apply();
    }

    public void saveTapToSelectEnabled(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_TAP_TO_SELECT_ENABLED, value).apply();
    }

    public void saveLeftHandedMode(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_LEFT_HANDED_MODE, value).apply();
    }

    public void putShowDialogNewGame(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_SHOW_DIALOG_NEW_GAME, value).apply();
    }

    public void putShowDialogRedeal(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_SHOW_DIALOG_REDEAL, value).apply();
    }

    public void putShowDialogMixCards(boolean value) {
        savedSharedData.edit().putBoolean(PREF_KEY_SHOW_DIALOG_MIX_CARDS, value).apply();
    }

    public void putFourColorMode(boolean value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putBoolean(PREF_KEY_4_COLOR_MODE, value).apply();
        } else {
            savedSharedData.edit().putBoolean(PREF_KEY_4_COLOR_MODE, value).apply();
        }
    }

    public void putHideTime(boolean value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putBoolean(PREF_KEY_HIDE_TIME, value).apply();
        } else {
            savedSharedData.edit().putBoolean(PREF_KEY_HIDE_TIME, value).apply();
        }
    }

    public void putHideScore(boolean value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putBoolean(PREF_KEY_HIDE_SCORE, value).apply();
        } else {
            savedSharedData.edit().putBoolean(PREF_KEY_HIDE_SCORE, value).apply();
        }
    }

    public void putHideMenuButton(boolean value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putBoolean(PREF_KEY_HIDE_MENU_BUTTON, value).apply();
        } else {
            savedSharedData.edit().putBoolean(PREF_KEY_HIDE_MENU_BUTTON, value).apply();
        }
    }

    public void putHideAutoCompleteButton(boolean value) {
        if (hasSettingsOnlyForThisGame()) {
            savedGameData.edit().putBoolean(PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON, value).apply();
        } else {
            savedSharedData.edit().putBoolean(PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON, value).apply();
        }
    }

    public void saveMenuGamesList(ArrayList<Integer> list) {
        putSharedIntList(PREF_KEY_MENU_GAMES, list);
    }

    public void saveMenuOrderList(ArrayList<Integer> list) {
        putSharedIntList(PREF_KEY_MENU_ORDER, list);
    }

    public void copyToGameIndividualSettings() {
        savedGameData.edit().putBoolean(PREF_KEY_HIDE_MENU_BUTTON, getHideMenuButton()).apply();
        savedGameData.edit().putBoolean(PREF_KEY_HIDE_TIME, getSavedHideTime()).apply();
        savedGameData.edit().putBoolean(PREF_KEY_HIDE_SCORE, getSavedHideScore()).apply();
        savedGameData.edit().putBoolean(PREF_KEY_HIDE_AUTOCOMPLETE_BUTTON, getHideAutoCompleteButton()).apply();
        savedGameData.edit().putBoolean(PREF_KEY_4_COLOR_MODE, getSavedFourColorMode()).apply();

        savedGameData.edit().putString(PREF_KEY_MENU_BAR_POS_PORTRAIT, getSavedMenuBarPosPortrait()).apply();
        savedGameData.edit().putString(PREF_KEY_MENU_BAR_POS_LANDSCAPE, getSavedMenuBarPosLandscape()).apply();

        savedGameData.edit().putInt(PREF_KEY_GAME_LAYOUT_MARGINS_PORTRAIT, getSavedGameLayoutMarginsPortrait()).apply();
        savedGameData.edit().putInt(PREF_KEY_TEXT_COLOR, getSavedTextColor()).apply();
        savedGameData.edit().putInt(PREF_KEY_GAME_LAYOUT_MARGINS_LANDSCAPE, getSavedGameLayoutMarginsLandscape()).apply();
        savedGameData.edit().putString(PREF_KEY_BACKGROUND_COLOR, Integer.toString(getSavedBackgroundColor())).apply();
        savedGameData.edit().putInt(PREF_KEY_BACKGROUND_COLOR_TYPE, getSavedBackgroundColorType()).apply();
        savedGameData.edit().putInt(PREF_KEY_BACKGROUND_COLOR_CUSTOM, getSavedBackgroundCustomColor()).apply();
        savedGameData.edit().putInt(PREF_KEY_CARD_DRAWABLES, getSavedCardTheme()).apply();
        savedGameData.edit().putInt(PREF_KEY_CARD_BACKGROUND, getSavedCardBackground()).apply();
        savedGameData.edit().putInt(PREF_KEY_CARD_BACKGROUND_COLOR, getSavedCardBackgroundColor()).apply();
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/checkboxpreferences/CheckBoxPreferenceHideScore.java
public class CheckBoxPreferenceHideScore extends CustomCheckBoxPreference {

    public CheckBoxPreferenceHideScore(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CheckBoxPreferenceHideScore(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CheckBoxPreferenceHideScore(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CheckBoxPreferenceHideScore(Context context) {
        super(context);
    }

    @Override
    protected void onClick() {
        boolean value = !isChecked();
        prefs.putHideScore(value);
        setChecked(value);
    }

    public void update() {
        setChecked(prefs.getSavedHideScore());
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/LoadGame.java
public class LoadGame {

    private String gameName;
    private String sharedPrefName;
    private ArrayList<AllGameInformation> allGameInformation = new ArrayList<>();
    private int GAME_COUNT;

    /**
     * load the game class and set the shown name and the name used for the sharedPref of the
     * current game.
     *
     * @param activity The activity to get the strings from the xml file
     * @param index    The index of the game to start
     */
    public Game loadClass(AppCompatActivity activity, int index) {

        sharedPrefName = allGameInformation.get(index).getSharedPrefName();
        gameName = allGameInformation.get(index).getName(activity.getResources());

        switch (index) {
            default:
                Log.e("LoadGame.loadClass()", "Your games seems not to be added here?");//fallthrough
            case 0:
                return new AcesUp();
            case 1:
                return new Calculation();
            case 2:
                return new Canfield();
            case 3:
                return new FortyEight();
            case 4:
                return new Freecell();
            case 5:
                return new Golf();
            case 6:
                return new GrandfathersClock();
            case 7:
                return new Gypsy();
            case 8:
                return new Klondike();
            case 9:
                return new Maze();
            case 10:
                return new Mod3();
            case 11:
                return new NapoleonsTomb();
            case 12:
                return new Pyramid();
            case 13:
                return new SimpleSimon();
            case 14:
                return new Spider();
            case 15:
                return new Spiderette();
            case 16:
                return new TriPeaks();
            case 17:
                return new Vegas();
            case 18:
                return new Yukon();
        }
    }

    /**
     * Insert new games here and in loadClass(). The order is very important, so don't change it!
     * The resource id points to the name of the game, so it can be translated. The second parameter
     * is the prefix for the game saves (like order of the cards). It uses a separate sharedPref for
     * each game. The string with the game name have to match the sharedPref name like
     * "games_<sharedPrefName>". Look at the other game names for a hint! It is important for
     * the manual pages. It is also the prefix for the manual entries. So use it when writing manual
     * entries!
     * <p>
     * If you add a game at the end, no further actions has to be done, expect updating the game
     * selector images and adding a manual entry. If you add it somewhere else (eg to get an
     * alphabetical default order) you need to update getMenuShownList(), getOrderedGameList() and
     * loadClass() !
     */
    public void loadAllGames() {
        allGameInformation.clear();

        allGameInformation.add(new AllGameInformation(R.string.games_AcesUp, "AcesUp", false, 40));
        allGameInformation.add(new AllGameInformation(R.string.games_Calculation, "Calculation", false, 30));
        allGameInformation.add(new AllGameInformation(R.string.games_Canfield, "Canfield", false, 40));
        allGameInformation.add(new AllGameInformation(R.string.games_FortyEight, "FortyEight", false, 50));
        allGameInformation.add(new AllGameInformation(R.string.games_Freecell, "Freecell", false, 15));
        allGameInformation.add(new AllGameInformation(R.string.games_Golf, "Golf", true, 40));
        allGameInformation.add(new AllGameInformation(R.string.games_GrandfathersClock, "GrandfathersClock", true, 50));
        allGameInformation.add(new AllGameInformation(R.string.games_Gypsy, "Gypsy", false, 80));
        allGameInformation.add(new AllGameInformation(R.string.games_Klondike, "Klondike", true, 30));
        allGameInformation.add(new AllGameInformation(R.string.games_Maze, "Maze", false, 20));
        allGameInformation.add(new AllGameInformation(R.string.games_mod3, "mod3", true, 70));
        allGameInformation.add(new AllGameInformation(R.string.games_NapoleonsTomb, "NapoleonsTomb", false, 20));
        allGameInformation.add(new AllGameInformation(R.string.games_Pyramid, "Pyramid", true, 40));
        allGameInformation.add(new AllGameInformation(R.string.games_SimpleSimon, "SimpleSimon", false, 25));
        allGameInformation.add(new AllGameInformation(R.string.games_Spider, "Spider", false, 50));
        allGameInformation.add(new AllGameInformation(R.string.games_Spiderette, "Spiderette", false, 30));
        allGameInformation.add(new AllGameInformation(R.string.games_TriPeaks, "TriPeaks", true, 40));
        allGameInformation.add(new AllGameInformation(R.string.games_Vegas, "Vegas", false, 30));
        allGameInformation.add(new AllGameInformation(R.string.games_Yukon, "Yukon", true, 80));

        GAME_COUNT = allGameInformation.size();
    }

    /**
     * Gets the list of shown games in the game selection menu.
     * The order of the game is the DEFAULT PREF_KEY_ORDER!
     * <p>
     * If you add a game, the list lacks the newly added game. so you can insert it at the right
     * position, or it will be automatically added at the end.
     * <p>
     * 1 stands for show, 0 for not showing.
     *
     * @return the list of shown/not shown in the game selection menu
     */
    public ArrayList<Integer> getMenuShownList() {
        ArrayList<Integer> result = prefs.getSavedMenuGamesList();

        if (result.size() == 12) {               //Canfield
            result.add(1, 1);
        }
        if (result.size() == 13) {               //Grandfather's clock
            result.add(5, 1);
        }
        if (result.size() == 14) {               //Vegas
            result.add(13, 1);
        }
        if (result.size() == 15) {               //Calculation
            result.add(1, 1);
        }
        if (result.size() == 16) {               //Napoleons Tomb
            result.add(10, 1);
        }
        if (result.size() == 17) {               //Maze
            result.add(9, 1);
        }
        if (result.size() == 18) {               //Spiderette
            result.add(15, 1);
        }

        if (result.size() < getGameCount()) {
            for (int i = result.size(); i < getGameCount(); i++) {
                result.add(1);
            }
        }

        return result;
    }

    /**
     * Returns the game list as integers in order of the user settings. If the user didn't set up
     * a custom order yet, the default order will be returned. If there was added a new game,
     * it will the added at the end.
     * <p>
     * YOU DONT NEED TO ADD A NEW GAME HERE!
     *
     * @return the game list in order of the user settings.
     */
    public ArrayList<Integer> getOrderedGameList() {
        ArrayList<Integer> result = prefs.getSavedMenuOrderList();

        if (result.isEmpty()) {                                     //get default order
            for (int i = 0; i < getGameCount(); i++) {
                result.add(i);
            }
        }

        if (result.size() < getGameCount()) {                       //add new games at the end
            for (int i = result.size(); i < getGameCount(); i++) {
                result.add(i);
            }
        }

        return result;
    }

    public int getGameCount() {
        return GAME_COUNT;
    }

    /**
     * Uses the game information to return the DEFAULT order of the games.
     *
     * @param res Resources to load the strings
     * @return the default game name list as string array
     */
    public String[] getDefaultGameNameList(Resources res) {
        String[] list = new String[allGameInformation.size()];

        for (int i = 0; i < allGameInformation.size(); i++) {
            list[i] = allGameInformation.get(i).getName(res);
        }

        return list;
    }

    /**
     * Uses the game information to return the ORDERED names of the games.
     *
     * @param res Resources to load the strings
     * @return the default game name list as string array list
     */
    public ArrayList<String> getOrderedGameNameList(Resources res) {

        ArrayList<Integer> savedList = getOrderedGameList();
        ArrayList<String> returnList = new ArrayList<>(allGameInformation.size());
        String[] defaultList = getDefaultGameNameList(res);

        for (int i = 0; i < getGameCount(); i++) {
            returnList.add(defaultList[savedList.indexOf(i)]);
        }

        return returnList;
    }

    /**
     * Returns a list of all the sharedPref names
     *
     * @return the shared pref name list as string array
     */
    public String[] getSharedPrefNameList() {
        String[] list = new String[allGameInformation.size()];

        for (int i = 0; i < allGameInformation.size(); i++) {
            list[i] = allGameInformation.get(i).getSharedPrefName();
        }

        return list;
    }

    /**
     * Returns the ordered game information list
     *
     * @return teh game list
     */
    public ArrayList<AllGameInformation> getOrderedGameInfoList() {
        ArrayList<Integer> savedList = getOrderedGameList();
        ArrayList<AllGameInformation> returnList = new ArrayList<>(allGameInformation.size());

        for (int i = 0; i < getGameCount(); i++) {
            returnList.add(allGameInformation.get(savedList.indexOf(i)));
        }

        return returnList;
    }


    /**
     * Returns the shared pref prefix of the given game. Used in the manual, so on a click to the
     * game entries, the resources are loaded using the shared pref prefix in the form of eg:
     * manual_<gamePrefix>_structure or manual_<gamePrefix>_objective
     *
     * @param index Index of the game as in the default order
     * @return the shared pref prefix string
     */
    public String getSharedPrefNameOfGame(int index) {
        return allGameInformation.get(index).getSharedPrefName();
    }

    public String getGameName() {
        return gameName;
    }

    public String getGameName(Resources res, int index) {
        return allGameInformation.get(index).getName(res);
    }

    public String getSharedPrefName() {
        return sharedPrefName;
    }

    /**
     * little class to collect all needed game information in one array list.
     */
    public class AllGameInformation {

        private int shownNameResID;
        private String sharedPrefName;
        private boolean canStartWinnableGame;
        private int ensureMovabilityMoves;

        AllGameInformation(int shownNameResID, String sharedPrefName, boolean canStartWinnableGame, int ensureMovabilityMoves) {
            this.shownNameResID = shownNameResID;
            this.sharedPrefName = sharedPrefName;
            this.canStartWinnableGame = canStartWinnableGame;
            this.ensureMovabilityMoves = ensureMovabilityMoves;
        }

        public String getName(Resources res) {
            return res.getString(shownNameResID);
        }

        public String getSharedPrefName() {
            return sharedPrefName;
        }

        public boolean canStartWinnableGame() {
            return canStartWinnableGame;
        }

        public int getEnsureMovabilityMoves() {
            return ensureMovabilityMoves;
        }
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/checkboxpreferences/CheckBoxPreferenceFourColorMode.java
public class CheckBoxPreferenceFourColorMode extends CustomCheckBoxPreference {

    public CheckBoxPreferenceFourColorMode(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CheckBoxPreferenceFourColorMode(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CheckBoxPreferenceFourColorMode(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CheckBoxPreferenceFourColorMode(Context context) {
        super(context);
    }

    @Override
    protected void onClick() {
        boolean value = !isChecked();
        prefs.putFourColorMode(value);
        setChecked(value);
    }

    public void update() {
        setChecked(prefs.getSavedFourColorMode());
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/dialogs/DialogPreferenceOnlyForThisGame.java
public class DialogPreferenceOnlyForThisGame extends CustomDialogPreference {

    private Context context;
    private CheckBox widget;


    public DialogPreferenceOnlyForThisGame(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.dialog_settings_only_for_this_game);
        setDialogIcon(null);
        setDialogTitle(null);
        this.context = context;
    }

    @Override
    protected void onBindDialogView(View view) {
        TextView textView1 = view.findViewById(R.id.textViewDialogOnlyForThisGame1);
        TextView textView2 = view.findViewById(R.id.textViewDialogOnlyForThisGame2);
        TextView textView3 = view.findViewById(R.id.textViewDialogOnlyForThisGame3);

        //settings were opened from the main menu
        if (isNotInGame()) {
            String sharedPrefNames[] = lg.getSharedPrefNameList();
            String gameNames[] = lg.getDefaultGameNameList(context.getResources());

            ArrayList<String> gamesWithIndividualSettings = new ArrayList<>(sharedPrefNames.length);

            for (int i = 0; i < sharedPrefNames.length; i++) {
                SharedPreferences savedGameData = context.getSharedPreferences(sharedPrefNames[i], MODE_PRIVATE);

                if (savedGameData.getBoolean(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME, DEFAULT_SETTINGS_ONLY_FOR_THIS_GAME)) {
                    gamesWithIndividualSettings.add(gameNames[i]);
                }
            }

            textView1.setText(R.string.settings_dialog_only_for_this_game_information_2);
            textView2.setText(createBulletParagraph(gamesWithIndividualSettings.toArray(new CharSequence[0])));
            textView3.setText(R.string.settings_dialog_only_for_this_game_information_3);
            //settings are switching to individual settings
        } else if (!prefs.hasSettingsOnlyForThisGame()) {

            //build the list with bullet characters
            CharSequence strings[] = new CharSequence[]{
                    context.getString(R.string.settings_dialog_only_for_this_game_enable_2),
                    context.getString(R.string.settings_dialog_only_for_this_game_enable_3),
                    context.getString(R.string.settings_dialog_only_for_this_game_enable_4)
            };

            //set up the textView
            textView1.setText(R.string.settings_dialog_only_for_this_game_enable_1);
            textView2.setText(createBulletParagraph(strings));
            textView3.setText(R.string.settings_dialog_only_for_this_game_enable_5);
            //settings are switching back to normal settings
        } else {
            textView1.setText(R.string.settings_dialog_only_for_this_game_disable);
            textView2.setVisibility(GONE);
            textView3.setVisibility(GONE);
        }

        super.onBindDialogView(view);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            if (!isNotInGame()) {
                if (!prefs.hasSettingsOnlyForThisGame()) {
                    //copy all relevant settings before switching to game-individual settings
                    prefs.copyToGameIndividualSettings();

                    prefs.setSettingsOnlyForThisGame(true);

                } else {
                    prefs.setSettingsOnlyForThisGame(false);
                }

                if (widget != null) {
                    widget.setChecked(!widget.isChecked());
                }
            } else {
                //reset the setting for individual game settings for all games
                for (String name : lg.getSharedPrefNameList()) {
                    SharedPreferences savedGameData = context.getSharedPreferences(name, MODE_PRIVATE);

                    if (savedGameData.getBoolean(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME, DEFAULT_SETTINGS_ONLY_FOR_THIS_GAME)) {
                        savedGameData.edit().putBoolean(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME, false).apply();
                    }
                }

                ((Settings) getContext()).hidePreferenceOnlyForThisGame();
                showToast(context.getString(R.string.settings_dialog_only_for_this_game_removed_all), context);
            }
        }


        super.onDialogClosed(positiveResult);
    }

    /*
     * Get the layout from the preference, so I can get the imageView from the widgetLayout
     */
    @Override
    protected View onCreateView(ViewGroup parent) {
        View view = super.onCreateView(parent);
        view.setBackgroundResource(R.color.colorDrawerSelected);

        //get rid of the stupid single line restriction for the title
        TextView textView = view.findViewById(android.R.id.title);
        if (textView != null) {
            textView.setSingleLine(false);
        }

        widget = view.findViewById(R.id.preference_only_for_this_game_switch);

        if (isNotInGame()) {
            if (widget != null) {
                widget.setVisibility(GONE);
            }

            if (getNumberOfGamesWithIndividualSettings() > 0) {
                setTitle(context.getString(R.string.settings_dialog_only_for_this_game_information_1));
            }

        } else {
            setTitle(String.format(context.getString(R.string.settings_apply_only_for_this_game), lg.getGameName()));

            if (widget != null) {
                widget.setChecked(prefs.hasSettingsOnlyForThisGame());
            }
        }

        return view;
    }

    private int getNumberOfGamesWithIndividualSettings() {
        int numberOfGamesWithIndividualSettings = 0;

        for (String name : lg.getSharedPrefNameList()) {
            SharedPreferences savedGameData = context.getSharedPreferences(name, MODE_PRIVATE);

            if (savedGameData.getBoolean(PREF_KEY_SETTINGS_ONLY_FOR_THIS_GAME, DEFAULT_SETTINGS_ONLY_FOR_THIS_GAME)) {
                numberOfGamesWithIndividualSettings++;
            }
        }

        return numberOfGamesWithIndividualSettings;
    }

    private boolean isNotInGame() {
        return prefs.getSavedCurrentGame() == DEFAULT_CURRENT_GAME;
    }

    public boolean canBeHidden() {
        return isNotInGame() && getNumberOfGamesWithIndividualSettings() == 0;
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/dialogs/DialogPreferenceTextColor.java
public class DialogPreferenceTextColor extends CustomDialogPreference implements View.OnClickListener {

    final int colorBlack = 0xff000000;
    final int colorWhite = 0xffffffff;

    int colorValue;

    private ArrayList<LinearLayout> linearLayouts;
    private Context context;
    private ImageView image;

    public DialogPreferenceTextColor(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.dialog_text_color);
        setDialogIcon(null);
        this.context = context;
    }

    @Override
    protected void onBindDialogView(View view) {
        colorValue = prefs.getSavedTextColor();

        linearLayouts = new ArrayList<>();
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorBlack));
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorWhite));


        for (LinearLayout linearLayout : linearLayouts) {
            linearLayout.setOnClickListener(this);
        }

        super.onBindDialogView(view);
    }


    @SuppressWarnings("SuspiciousMethodCalls")
    public void onClick(View view) {
        if (view == ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE)) {
            AmbilWarnaDialog dialog = new AmbilWarnaDialog(context, colorValue, new AmbilWarnaDialog.OnAmbilWarnaListener() {
                @Override
                public void onOk(AmbilWarnaDialog dialog, int color) {
                    prefs.saveTextColor(color);
                    updateSummary();
                    getDialog().dismiss();
                }

                @Override
                public void onCancel(AmbilWarnaDialog dialog) {
                    // cancel was selected by the user
                }
            });
            dialog.show();
        } else if (view == ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEGATIVE)) {
            getDialog().dismiss();
        } else {
            int selectedColor = linearLayouts.indexOf(view) + 1;

            switch (selectedColor) {
                case 1:
                default:
                    colorValue = colorBlack;
                    break;
                case 2:
                    colorValue = colorWhite;
            }

            prefs.saveTextColor(colorValue);

            updateSummary();
            getDialog().dismiss();
        }
    }

    @Override
    protected void showDialog(Bundle state) {
        super.showDialog(state);

        ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(this);
        ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
    }

    /*
     * Get the layout from the preference, so I can get the imageView from the widgetLayout
     */
    @Override
    protected View onCreateView(ViewGroup parent) {
        View view = super.onCreateView(parent);

        image = view.findViewById(R.id.widget_layout_color_imageView);
        updateSummary();

        return view;
    }

    /**
     * Gets the saved data and updates the summary according to it
     */
    public void updateSummary() {
        int color = prefs.getSavedTextColor();

        //this forces redrawing of the color preview
        setSummary("");

        switch (color) {
            case colorBlack:
                setSummary(getContext().getString(R.string.black));
                break;
            case colorWhite:
                setSummary(getContext().getString(R.string.white));
                break;
            default:
                //show as hex string, but without the opacity part at the beginning
                setSummary(String.format("#%06X", (0xFFFFFF & color)));
                break;
        }

        if (image != null) {
            image.setImageResource(0);
            image.setBackgroundColor(color);
        }

    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/checkboxpreferences/CheckBoxPreferenceHideTime.java
public class CheckBoxPreferenceHideTime extends CustomCheckBoxPreference {

    public CheckBoxPreferenceHideTime(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CheckBoxPreferenceHideTime(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CheckBoxPreferenceHideTime(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CheckBoxPreferenceHideTime(Context context) {
        super(context);
    }

    @Override
    protected void onClick() {
        boolean value = !isChecked();
        prefs.putHideTime(value);
        setChecked(value);
    }

    public void update() {
        setChecked(prefs.getSavedHideTime());
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/classes/CustomPreferenceFragment.java
public class CustomPreferenceFragment extends PreferenceFragment {

    @Override
    public void onAttach(Context context) {
        reinitializeData(context);
        super.onAttach(context);
    }

    @Override
    public void onAttach(Activity activity) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            reinitializeData(activity);
        }
        super.onAttach(activity);
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/dialogs/DialogPreferenceBackgroundColor.java
public class DialogPreferenceBackgroundColor extends CustomDialogPreference implements View.OnClickListener {

    int backgroundType;
    int backgroundValue;
    int savedCustomColor;
    private ArrayList<LinearLayout> linearLayouts;
    private Context context;
    private ImageView image;

    public DialogPreferenceBackgroundColor(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.dialog_background_color);
        setDialogIcon(null);
        this.context = context;
    }

    @Override
    protected void onBindDialogView(View view) {

        backgroundType = prefs.getSavedBackgroundColorType();
        backgroundValue = prefs.getSavedBackgroundColor();
        savedCustomColor = prefs.getSavedBackgroundCustomColor();

        linearLayouts = new ArrayList<>();
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorBlue));
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorGreen));
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorRed));
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorYellow));
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorOrange));
        linearLayouts.add(view.findViewById(R.id.dialogBackgroundColorPurple));

        for (LinearLayout linearLayout : linearLayouts) {
            linearLayout.setOnClickListener(this);
        }

        super.onBindDialogView(view);
    }


    @SuppressWarnings("SuspiciousMethodCalls")
    public void onClick(View view) {
        if (view == ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE)) {
            AmbilWarnaDialog dialog = new AmbilWarnaDialog(context, savedCustomColor, new AmbilWarnaDialog.OnAmbilWarnaListener() {
                @Override
                public void onOk(AmbilWarnaDialog dialog, int color) {
                    backgroundType = 2;
                    backgroundValue = savedCustomColor = color;

                    prefs.saveBackgroundColorType(backgroundType);
                    prefs.saveBackgroundCustomColor(backgroundValue);
                    updateSummary();
                    getDialog().dismiss();
                }

                @Override
                public void onCancel(AmbilWarnaDialog dialog) {
                    // cancel was selected by the user
                }
            });
            dialog.show();
        } else if (view == ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEGATIVE)) {
            getDialog().dismiss();
        } else {
            backgroundValue = linearLayouts.indexOf(view) + 1;
            backgroundType = 1;

            prefs.saveBackgroundColorType(backgroundType);
            prefs.saveBackgroundColor(backgroundValue);

            updateSummary();
            getDialog().dismiss();
        }
    }

    @Override
    protected void showDialog(Bundle state) {
        super.showDialog(state);

        ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(this);
        ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
    }

    /*
     * Get the layout from the preference, so I can get the imageView from the widgetLayout
     */
    @Override
    protected View onCreateView(ViewGroup parent) {
        View view = super.onCreateView(parent);

        image = view.findViewById(R.id.widget_layout_color_imageView);
        updateSummary();

        return view;
    }

    /**
     * Gets the saved data and updates the summary according to it
     */
    public void updateSummary() {

        if (prefs.getSavedBackgroundColorType() == 1) {
            int drawableID;
            int stringID;
            switch (prefs.getSavedBackgroundColor()) {
                case 1:
                default:
                    stringID = R.string.blue;
                    drawableID = R.drawable.background_color_blue;
                    break;
                case 2:
                    stringID = R.string.green;
                    drawableID = R.drawable.background_color_green;
                    break;
                case 3:
                    stringID = R.string.red;
                    drawableID = R.drawable.background_color_red;
                    break;
                case 4:
                    stringID = R.string.yellow;
                    drawableID = R.drawable.background_color_yellow;
                    break;
                case 5:
                    stringID = R.string.orange;
                    drawableID = R.drawable.background_color_orange;
                    break;
                case 6:
                    stringID = R.string.purple;
                    drawableID = R.drawable.background_color_purple;
                    break;
            }

            if (image != null) {
                image.setImageResource(drawableID);
            }

            setSummary(context.getString(stringID));
        } else {
            int customColor = prefs.getSavedBackgroundCustomColor();

            //this forces redrawing of the color preview
            setSummary("");

            //show as hex string, but without the opacity part at the beginning
            setSummary(String.format("#%06X", (0xFFFFFF & customColor)));

            if (image != null) {
                image.setImageResource(0);
                image.setBackgroundColor(customColor);
            }
        }
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/checkboxpreferences/CheckBoxPreferenceHideAutoCompleteButton.java
public class CheckBoxPreferenceHideAutoCompleteButton extends CustomCheckBoxPreference {

    public CheckBoxPreferenceHideAutoCompleteButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CheckBoxPreferenceHideAutoCompleteButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CheckBoxPreferenceHideAutoCompleteButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CheckBoxPreferenceHideAutoCompleteButton(Context context) {
        super(context);
    }

    @Override
    protected void onClick() {
        boolean value = !isChecked();
        prefs.putHideAutoCompleteButton(value);
        setChecked(value);
    }

    public void update() {
        setChecked(prefs.getHideAutoCompleteButton());
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/SharedData.java
public class SharedData {

    public final static int OPTION_UNDO = 1, OPTION_NO_RECORD = 2, OPTION_REVERSED_RECORD = 3;

    //Strings
    public static String GAME = "game";
    public static String RESTART_DIALOG = "dialogRestart";
    public static String WON_DIALOG = "dialogWon";


    public static Game currentGame;

    public static Card[] cards;
    public static Stack[] stacks;

    public static Preferences prefs;
    public static Scores scores;

    public static GameLogic gameLogic;
    public static Animate animate;

    public static AutoComplete autoComplete;
    public static Timer timer;
    public static Sounds sounds;
    public static RecordList recordList;
    public static AutoMove autoMove;
    public static Hint hint;
    public static DealCards dealCards;

    public static WaitForAnimationHandler handlerTestIfWon;
    public static WaitForAnimationHandler handlerTestAfterMove;

    public static MovingCards movingCards = new MovingCards();
    public static LoadGame lg = new LoadGame();
    public static Bitmaps bitmaps = new Bitmaps();
    public static CardHighlight cardHighlight = new CardHighlight();
    public static BackgroundMusic backgroundSound = new BackgroundMusic();
    public static EnsureMovability ensureMovability;

    public static int activityCounter = 0;
    public static boolean stopUiUpdates = false;
    public static boolean isDialogVisible = false;

    private static Toast toast;

    /**
     * Reload the needed data. Because if the android device runs out of memory, the app gets
     * killed. If the user restarts the app and it loads  for example the settings activity, all
     * the strings and the shared preferences need to be reinitialized.
     *
     * @param context Used to get the resources
     */
    public static void reinitializeData(Context context) {
        //Bitmaps
        if (!bitmaps.checkResources()) {
            bitmaps.setResources(context.getResources());
        }

        if (lg.getGameCount() == 0) {
            lg.loadAllGames();
        }

        //SharedPrefs
        if (prefs == null) {
            prefs = new Preferences(context);
        }
    }

    /**
     * Moves a card to a stack.
     *
     * @param card        The card to move
     * @param destination The destination of the movement
     */
    public static void moveToStack(Card card, Stack destination) {
        moveToStack(card, destination, 0);
    }

    /**
     * Moves a card to a stack. but with an additional option
     *
     * @param card        The card to move
     * @param destination The destination of the movement
     * @param option      The option to apply
     */
    public static void moveToStack(Card card, Stack destination, int option) {
        ArrayList<Card> cards = new ArrayList<>();
        cards.add(card);

        ArrayList<Stack> destinations = new ArrayList<>();
        destinations.add(destination);

        moveToStack(cards, destinations, option);
    }

    /**
     * Moves multiple cards to a destination
     *
     * @param cards       The cards to move
     * @param destination The destination of the movement
     */
    public static void moveToStack(ArrayList<Card> cards, Stack destination) {
        moveToStack(cards, destination, 0);
    }

    /**
     * Moves multiple cards to a destination, with an additional option
     *
     * @param cards       The cards to move
     * @param destination The destination of the movement
     * @param option      The option to apply
     */
    public static void moveToStack(ArrayList<Card> cards, Stack destination, int option) {
        ArrayList<Stack> destinations = new ArrayList<>();

        for (int i = 0; i < cards.size(); i++)
            destinations.add(destination);

        moveToStack(cards, destinations, option);
    }

    public static void moveToStack(ArrayList<Card> cards, ArrayList<Stack> destinations) {
        moveToStack(cards, destinations, 0);
    }

    /**
     * Moves multiple cards to multiple destinations, with an additional option
     * <p>
     * moves a card to a stack by doing this:
     * - change the score according to the cards
     * - add the cards to the record list
     * - move every card one by one
     * - bring the moving cards to front
     * - and start handlers to call some methods
     *
     * @param cards        The cards to move
     * @param destinations The destinations of the movements
     * @param option       The option to apply
     */
    public static void moveToStack(ArrayList<Card> cards, ArrayList<Stack> destinations, int option) {

        if (!stopUiUpdates) {
            if (option == OPTION_UNDO) {
                scores.undo(cards, destinations);
            } else if (option == 0) {
                scores.move(cards, destinations);
                recordList.add(cards);
            } else if (option == OPTION_REVERSED_RECORD) {
                //reverse the cards and add the reversed list to the record
                ArrayList<Card> cardsReversed = new ArrayList<>();

                for (int i = 0; i < cards.size(); i++) {
                    cardsReversed.add(cards.get(cards.size() - 1 - i));
                }

                recordList.add(cardsReversed);
                scores.move(cards, destinations);
            }
            //else if (option == OPTION_NO_RECORD), do nothing
        }


        for (int i = 0; i < cards.size(); i++) {
            //this means to flip a card
            if (cards.get(i).getStack() == destinations.get(i)) {
                cards.get(i).flip();
            }
        }

        for (int i = 0; i < cards.size(); i++) {
            if (cards.get(i).getStack() != destinations.get(i)) {
                cards.get(i).removeFromCurrentStack();
                destinations.get(i).addCard(cards.get(i));
            }
        }

        for (Stack stack : destinations) {
            stack.updateSpacing();
        }

        for (Card card : cards) {
            card.bringToFront();
        }

        //following stuff in handlers, because they should wait until possible card movements are over.
        if (option == 0 && !stopUiUpdates) {
            handlerTestAfterMove.sendDelayed();
        }
    }

    /**
     * Little method I use to test if my code reaches some point
     *
     * @param text The text to show
     */
    public static void logText(String text) {
        Log.e("hey", text);
    }

    public static int min(int value1, int value2) {
        return value1 < value2 ? value1 : value2;
    }

    public static float min(float value1, float value2) {
        return value1 < value2 ? value1 : value2;
    }

    public static int max(int value1, int value2) {
        return value1 > value2 ? value1 : value2;
    }

    public static float max(float value1, float value2) {
        return value1 > value2 ? value1 : value2;
    }

    public static boolean leftHandedModeEnabled() {
        return prefs.getSavedLeftHandedMode();
    }

    public static boolean isLargeTablet(Context context) {
        return prefs.getSavedForcedTabletLayout() || ((context.getResources().getConfiguration().screenLayout
                & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE);
    }

    public static String stringFormat(String text) {
        return String.format(Locale.getDefault(), "%s", text);
    }

    public static int max(ArrayList<Integer> list) {
        int max = 0;

        for (int value : list) {
            if (value > max) {
                max = value;
            }
        }

        return max;
    }

    public static int min(ArrayList<Integer> list) {
        int min = list.get(0);

        for (int value : list) {
            if (value < min) {
                min = value;
            }
        }

        return min;
    }

    public static Random getPrng() {
        return new Random();


        /*Random random;                        //this one for testing

        try {
            logText("getting random data...");
            random = new AESCounterRNG();
        } catch (GeneralSecurityException e) {
            Log.e("PRNG Error", e.toString());
            random = new Random();
        }

        return random;*/


        //return new SecureRandom();        //or maybe use this
    }

    /**
     * Shows the given text as a toast. New texts override the old one.
     *
     * @param text The text to show
     */
    @SuppressLint("ShowToast")
    public static void showToast(String text, Context context) {
        if (toast == null) {
            toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
        } else
            toast.setText(text);

        toast.show();
    }

    /**
     * Uses the given string array to create a text paragraph. The strings are separated by bullet
     * characters.
     *
     * @param strings The string array to use for the text paragraph
     * @return a charSequence, which can directly be applied to a textView
     */
    static public CharSequence createBulletParagraph(CharSequence[] strings) {

        SpannableString spanns[] = new SpannableString[strings.length];

        //apply the bullet characters
        for (int i = 0; i < strings.length; i++) {
            spanns[i] = new SpannableString(strings[i] + (i < strings.length - 1 ? "\n" : ""));
            spanns[i].setSpan(new BulletSpan(15), 0, strings[i].length(), 0);
        }

        //set up the textView
        return TextUtils.concat(spanns);
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/dialogs/DialogPreferenceCardBackground.java
public class DialogPreferenceCardBackground extends CustomDialogPreference implements View.OnClickListener {

    private static int NUMBER_OF_CARD_BACKGROUNDS = 10;

    private LinearLayout[] linearLayoutsBackgrounds = new LinearLayout[NUMBER_OF_CARD_BACKGROUNDS];
    private ImageView[] imageViews = new ImageView[NUMBER_OF_CARD_BACKGROUNDS];

    private LinearLayout[] linearLayoutsColors = new LinearLayout[4];
    private Context context;
    private ImageView image;
    private TypedValue typedValue = new TypedValue();

    private int selectedBackground;
    private int selectedBackgroundColor;


    public DialogPreferenceCardBackground(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.dialog_settings_cards_background);
        setDialogIcon(null);
        setDialogTitle("");

        this.context = context;

        context.getTheme().resolveAttribute(R.attr.selectableItemBackground, typedValue, true);
    }

    @Override
    protected void onBindDialogView(View view) {

        linearLayoutsBackgrounds[0] = view.findViewById(R.id.settingsCardBackground0);
        linearLayoutsBackgrounds[1] = view.findViewById(R.id.settingsCardBackground1);
        linearLayoutsBackgrounds[2] = view.findViewById(R.id.settingsCardBackground2);
        linearLayoutsBackgrounds[3] = view.findViewById(R.id.settingsCardBackground3);
        linearLayoutsBackgrounds[4] = view.findViewById(R.id.settingsCardBackground4);
        linearLayoutsBackgrounds[5] = view.findViewById(R.id.settingsCardBackground5);
        linearLayoutsBackgrounds[6] = view.findViewById(R.id.settingsCardBackground6);
        linearLayoutsBackgrounds[7] = view.findViewById(R.id.settingsCardBackground7);
        linearLayoutsBackgrounds[8] = view.findViewById(R.id.settingsCardBackground8);
        linearLayoutsBackgrounds[9] = view.findViewById(R.id.settingsCardBackground9);

        linearLayoutsColors[0] = view.findViewById(R.id.dialogBackgroundsCardsBlue);
        linearLayoutsColors[1] = view.findViewById(R.id.dialogBackgroundsCardsRed);
        linearLayoutsColors[2] = view.findViewById(R.id.dialogBackgroundsCardsGreen);
        linearLayoutsColors[3] = view.findViewById(R.id.dialogBackgroundsCardsYellow);

        for (int i = 0; i < NUMBER_OF_CARD_BACKGROUNDS; i++) {
            linearLayoutsBackgrounds[i].setOnClickListener(this);
            imageViews[i] = (ImageView) linearLayoutsBackgrounds[i].getChildAt(0);
        }

        for (int i = 0; i < 4; i++) {
            linearLayoutsColors[i].setOnClickListener(this);
        }

        selectedBackground = prefs.getSavedCardBackground();
        selectedBackgroundColor = prefs.getSavedCardBackgroundColor();
        updateDialog();

        super.onBindDialogView(view);
    }

    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.settingsCardBackground0:
                selectedBackground = 0;
                break;
            case R.id.settingsCardBackground1:
                selectedBackground = 1;
                break;
            case R.id.settingsCardBackground2:
                selectedBackground = 2;
                break;
            case R.id.settingsCardBackground3:
                selectedBackground = 3;
                break;
            case R.id.settingsCardBackground4:
                selectedBackground = 4;
                break;
            case R.id.settingsCardBackground5:
                selectedBackground = 5;
                break;
            case R.id.settingsCardBackground6:
                selectedBackground = 6;
                break;
            case R.id.settingsCardBackground7:
                selectedBackground = 7;
                break;
            case R.id.settingsCardBackground8:
                selectedBackground = 8;
                break;
            case R.id.settingsCardBackground9:
                selectedBackground = 9;
                break;
            case R.id.dialogBackgroundsCardsBlue:
                selectedBackgroundColor = 0;
                break;
            case R.id.dialogBackgroundsCardsRed:
                selectedBackgroundColor = 1;
                break;
            case R.id.dialogBackgroundsCardsGreen:
                selectedBackgroundColor = 2;
                break;
            case R.id.dialogBackgroundsCardsYellow:
                selectedBackgroundColor = 3;
                break;
        }

        updateDialog();
    }

    /*
     * Get the layout from the preference, so I can get the imageView from the widgetLayout
     */
    @Override
    protected View onCreateView(ViewGroup parent) {
        View view = super.onCreateView(parent);

        image = view.findViewById(R.id.preference_cards_background_imageView);
        updateSummary();

        return view;
    }

    /**
     * Update the "selection shadow" and the pictures of the dialog
     */
    private void updateDialog() {

        //LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
        //params.
        for (int i = 0; i < NUMBER_OF_CARD_BACKGROUNDS; i++) {
            linearLayoutsBackgrounds[i].setBackgroundResource(i == selectedBackground ? R.drawable.settings_highlight : typedValue.resourceId);
        }

        for (int i = 0; i < NUMBER_OF_CARD_BACKGROUNDS; i++) {
            imageViews[i].setImageBitmap(bitmaps.getCardBack(i, selectedBackgroundColor));
        }

        for (int i = 0; i < 4; i++) {
            linearLayoutsColors[i].setBackgroundResource(i == selectedBackgroundColor ? R.drawable.settings_highlight : typedValue.resourceId);
        }
    }

    /**
     * save the selected background and update the summary
     */
    private void save() {
        prefs.saveCardBackground(selectedBackground);
        prefs.saveCardBackgroundColor(selectedBackgroundColor);

        updateSummary();
    }

    /**
     * Gets the bitmap for the card background preference icon and also set its summary
     */
    public void updateSummary() {
        Bitmap cardBack;

        int selectedBackground = prefs.getSavedCardBackground();
        int selectedBackgroundColor = prefs.getSavedCardBackgroundColor();

        if (image != null) {
            cardBack = bitmaps.getCardBack(selectedBackground, selectedBackgroundColor);
            image.setImageBitmap(cardBack);
        }

        setSummary(String.format(Locale.getDefault(), "%s %s",
                context.getString(R.string.settings_background), selectedBackground + 1));
    }

    /*
     * only save when result is positive
     */
    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            save();
        }
    }
}
app/src/main/java/de/tobiasbielefeld/solitaire/checkboxpreferences/CheckBoxPreferenceHideMenuButton.java
public class CheckBoxPreferenceHideMenuButton extends CustomCheckBoxPreference {

    public CheckBoxPreferenceHideMenuButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CheckBoxPreferenceHideMenuButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CheckBoxPreferenceHideMenuButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CheckBoxPreferenceHideMenuButton(Context context) {
        super(context);
    }

    @Override
    protected void onClick() {
        boolean value = !isChecked();
        prefs.putHideMenuButton(value);
        setChecked(value);
    }

    public void update() {
        setChecked(prefs.getHideMenuButton());
    }
}


Question: import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.support.v7.app.ActionBar;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import de.tobiasbielefeld.solitaire.LoadGame;
import de.tobiasbielefeld.solitaire.R;
import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceFourColorMode;
import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideAutoCompleteButton;
import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideMenuButton;
import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideScore;
import de.tobiasbielefeld.solitaire.checkboxpreferences.CheckBoxPreferenceHideTime;
import de.tobiasbielefeld.solitaire.classes.Card;
import de.tobiasbielefeld.solitaire.classes.CustomPreferenceFragment;
import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceBackgroundColor;
import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceCardBackground;
import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceCards;
import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceOnlyForThisGame;
import de.tobiasbielefeld.solitaire.dialogs.DialogPreferenceTextColor;
import de.tobiasbielefeld.solitaire.helper.Sounds;
import static de.tobiasbielefeld.solitaire.SharedData.*;
import static de.tobiasbielefeld.solitaire.helper.Preferences.*;
/*
 * Copyright (C) 2016  Tobias Bielefeld
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * If you want to contact me, send me an e-mail at tobias.bielefeld@gmail.com
 */

package de.tobiasbielefeld.solitaire.ui.settings;





/**
 * Settings activity created with the "Create settings activity" tool from Android Studio.
 */

public class Settings extends AppCompatPreferenceActivity {

    private Preference preferenceMenuBarPosition;
    private Preference preferenceMenuColumns;
    private Preference preferenceBackgroundVolume;
    private Preference preferenceMaxNumberUndos;
    private Preference preferenceGameLayoutMargins;

    private CheckBoxPreference preferenceSingleTapAllGames;
    private CheckBoxPreference preferenceTapToSelect;
    private CheckBoxPreference preferenceImmersiveMode;

    private DialogPreferenceCards preferenceCards;
    private DialogPreferenceCardBackground preferenceCardBackground;
    private DialogPreferenceBackgroundColor preferenceBackgroundColor;
    private DialogPreferenceTextColor preferenceTextColor;
    private DialogPreferenceOnlyForThisGame dialogPreferenceOnlyForThisGame;

    private CheckBoxPreferenceFourColorMode preferenceFourColorMode;
    private CheckBoxPreferenceHideAutoCompleteButton preferenceHideAutoCompleteButton;
    private CheckBoxPreferenceHideMenuButton preferenceHideMenuButton;
Answer:     private CheckBoxPreferenceHideScore preferenceHideScore;