Skip to content

Instantly share code, notes, and snippets.

@SerejaSerjik
Created October 21, 2023 08:56
Show Gist options
  • Select an option

  • Save SerejaSerjik/fce5d1f40ceb82836b4a58aecc0c07c0 to your computer and use it in GitHub Desktop.

Select an option

Save SerejaSerjik/fce5d1f40ceb82836b4a58aecc0c07c0 to your computer and use it in GitHub Desktop.
Wordle Game Cubit
import 'dart:async';
import 'dart:developer' as developer;
import 'dart:math';
import 'package:equatable/equatable.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:senior_app/core/core.dart';
import 'package:senior_app/data/data.dart';
import 'package:senior_app/di/di.dart';
import 'package:senior_app/domain/domain.dart';
import 'package:senior_app/utils/utils.dart';
part 'wordle_game_state.dart';
class WordleGameCubit extends HydratedCubit<WordleGameState> {
WordleGameCubit({
required PostWordleAnalyticsEnterToGame postWordleAnalyticsEnterToGame,
required PostWordleAnalyticsGameWin postWordleAnalyticsGameWin,
}) : _postWordleAnalyticsEnterToGame = postWordleAnalyticsEnterToGame,
_postWordleAnalyticsGameWin = postWordleAnalyticsGameWin,
super(WordleGameState.initial()) {
_checkForNewDay();
_initializeGame();
_startTimer();
}
final PostWordleAnalyticsEnterToGame _postWordleAnalyticsEnterToGame;
final PostWordleAnalyticsGameWin _postWordleAnalyticsGameWin;
final StreamController<String> _remainingTimeController =
StreamController<String>.broadcast();
Stream<String> get remainingTimeStream => _remainingTimeController.stream;
void updateBoardCell(int rowIndex, int colIndex, String value) {
// Creates a new list and also new lists for each inner list
final updatedBoard =
state.board.map((list) => List<String>.from(list)).toList();
var updatedTryWord = state.currentTryWord;
if (colIndex < 6 && rowIndex <= 5) {
final nextColIndex = colIndex + 1;
updatedBoard[rowIndex][colIndex] = value;
if (state.currentTryWord.length < 5) {
updatedTryWord += value;
}
emit(
state.copyWith(
board: updatedBoard,
currentCol: nextColIndex,
currentRow: rowIndex,
currentTryWord: updatedTryWord,
submittedInvalidWord: false,
),
);
}
}
void clearLastEditedCell() {
final updatedBoard = List<List<String>>.from(state.board);
if (state.currentCol >= 1) {
updatedBoard[state.currentRow][state.currentCol - 1] = '';
emit(
state.copyWith(
board: updatedBoard,
currentCol: state.currentCol - 1,
currentTryWord: state.currentTryWord
.substring(0, state.currentTryWord.length - 1),
submittedInvalidWord: false,
),
);
}
}
Future<void> checkWord() async {
final updatedCellStatuses = List<List<CellStatus>>.from(state.cellStatuses);
final updatedBoard = List<List<String>>.from(state.board);
if (state.wordOfTheDay == state.currentTryWord) {
//change status for win, change letters
for (var i = 0; i < state.wordOfTheDay.length; i++) {
updatedCellStatuses[state.currentRow][i] = CellStatus.correctPlace;
}
final updatedCurrentStreak = state.currentStreak + 1;
final updatedGamesPlayed = state.gamesPlayed + 1;
final updatedWinsCount = state.winsCount + 1;
final updatedMaxStreak = updatedCurrentStreak > state.maxStreak
? updatedCurrentStreak
: state.maxStreak;
sl<PrefManager>().wordleStats = [
updatedGamesPlayed,
updatedWinsCount,
updatedCurrentStreak,
updatedMaxStreak
];
await _postWordleAnalyticsGameWin.call(NoParams());
emit(
state.copyWith(
gameStatus: WordleGameStatus.won,
cellStatuses: updatedCellStatuses,
board: updatedBoard,
gamesPlayed: updatedGamesPlayed,
winsCount: updatedWinsCount,
currentStreak: updatedCurrentStreak,
maxStreak: updatedMaxStreak,
),
);
} else if (state.currentCol == 5 &&
!WordleConstants.wordsDict.keys.contains(state.currentTryWord)) {
emit(state.copyWith(submittedInvalidWord: true));
} else {
// Reset cell statuses for the current row
updatedCellStatuses[state.currentRow] =
List.filled(5, CellStatus.unguessed);
// Compare each letter in the current try word with the word of the day
for (var i = 0; i < state.wordOfTheDay.length; i++) {
if (state.wordOfTheDay[i] == state.currentTryWord[i]) {
updatedCellStatuses[state.currentRow][i] = CellStatus.correctPlace;
} else if (state.wordOfTheDay.contains(state.currentTryWord[i])) {
updatedCellStatuses[state.currentRow][i] = CellStatus.wrongPlace;
}
}
if (state.currentRow == 5 && state.currentCol == 5) {
//check for loss here
const updatedCurrentStreak = 0;
final updatedGamesPlayed = state.gamesPlayed + 1;
final updatedWinsCount = state.winsCount;
final updatedMaxStreak = updatedCurrentStreak > state.maxStreak
? updatedCurrentStreak
: state.maxStreak;
sl<PrefManager>().wordleStats = [
updatedGamesPlayed,
updatedWinsCount,
updatedCurrentStreak,
updatedMaxStreak
];
emit(
state.copyWith(
board: updatedBoard,
cellStatuses: updatedCellStatuses,
gameStatus: WordleGameStatus.lost,
gamesPlayed: updatedGamesPlayed,
currentStreak: updatedCurrentStreak,
),
);
} else {
emit(
state.copyWith(
board: updatedBoard,
cellStatuses: updatedCellStatuses,
currentTryWord: '',
currentRow: state.currentRow + 1,
currentCol: 0,
),
);
}
}
}
void showHint() {
emit(
state.copyWith(
showHint: true,
),
);
}
void resetGame() {
emit(WordleGameState.initial());
_generateNewWordOfTheDay();
checkLetterStatuses(
resetStatus: true,
);
}
void _startTimer() {
Timer.periodic(const Duration(seconds: 1), (_) {
final remainingTime = _getTimeUntilMidnight();
_remainingTimeController.add(remainingTime);
});
}
void _checkForNewDay() {
final now = DateTime.now();
final lastWordOfTheDayTime = sl<PrefManager>().lastWordOfTheDayTime;
// Uncomment the lines below to check for a new day instead of 2 minutes
// final DateTime currentDay = DateTime(now.year, now.month, now.day);
// final DateTime lastWordOfTheDayDate = DateTime(lastWordOfTheDayTime.year, lastWordOfTheDayTime.month, lastWordOfTheDayTime.day);
// Check if 2 minutes have passed since the last word of the day update
if (now.difference(lastWordOfTheDayTime).inMinutes >= 2) {
// If so, we update the word of the day time to the current time
sl<PrefManager>().lastWordOfTheDayTime = now;
// Then we generate a new word of the day and reset the game
resetGame();
}
}
void _generateNewWordOfTheDay() {
// Commenting out the old random word logic
// final random = Random();
// final index = random.nextInt(2152);
// final newWordOfTheDay = WordleConstants.wordsDict.keys.toList()[index];
// Adding the new logic to always use "vowel" as the word of the day
final newWordOfTheDay = "vowel";
emit(
state.copyWith(
wordOfTheDay: newWordOfTheDay,
showHint: false,
),
);
}
@override
WordleGameState? fromJson(Map<String, dynamic> json) {
return WordleGameState.fromJson(json);
}
@override
Map<String, dynamic>? toJson(WordleGameState state) {
return state.toJson();
}
Future<void> _initializeGame() async {
await _postWordleAnalyticsEnterToGame.call(NoParams());
final loadedState = fromJson(
HydratedBloc.storage.read(storageToken) as Map<String, dynamic>? ?? {},
);
if (loadedState != null) {
developer.log('state is not null: $loadedState');
// emit(WordleGameState.initial());
emit(loadedState);
} else {
emit(WordleGameState.initial());
}
}
String _getTimeUntilMidnight() {
final now = DateTime.now();
final midnight = DateTime(now.year, now.month, now.day + 1);
final difference = midnight.difference(now);
return difference.toString().split('.').first.padLeft(8, '0');
}
void checkLetterStatuses({bool resetStatus = false}) {
final newLetterStatuses = <String, KeyStatus>{};
final wordOfTheDay = state.wordOfTheDay;
final board = state.board;
for (final letter in WordleConstants.letters) {
if (!wordOfTheDay.contains(letter.toLowerCase())) {
// The letter is not in the word of the day.
newLetterStatuses[letter] = KeyStatus.notInWord;
} else {
// The letter is in the word of the day.
// Let's check if it was guessed.
var guessed = false;
for (final row in board) {
if (row.contains(letter.toLowerCase())) {
guessed = true;
break;
}
}
if (guessed) {
// The letter was guessed.
newLetterStatuses[letter] = KeyStatus.inWord;
} else {
// The letter wasn't guessed.
newLetterStatuses[letter] = KeyStatus.initial;
}
}
}
// At this point, newLetterStatuses contains updated statuses for all the letters.
// Let's update our state.
emit(state.copyWith(lettersStatutes: newLetterStatuses));
}
}
@isaacglover527-a11y
Copy link
Copy Markdown

This Wordle Game Cubit project is impressive for managing game state and analytics so efficiently. Wordle 6 buchstaben offers a fun twist on classic Wordle puzzles by challenging players with six-letter words, keeping engagement high. The game highlight how structured logic and creativity come together to make word games enjoyable and interactive.

@metapixle
Copy link
Copy Markdown

In the content marketing world, engaging storytelling is essential. Meta Pixle creates compelling, value-driven content that strengthens brand authority, builds trust, and encourages consistent audience interaction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment