diff --git a/Flutter.md b/Flutter.md index e80605c..c4cdd57 100644 --- a/Flutter.md +++ b/Flutter.md @@ -71,3 +71,5 @@ Submission has to be done by sharing your github repo link and the .apk file of - Make a Pull request ## Submissions +repo:- https://github.com/Yash-Agarwal1708/CSOC22-Week1.git +.apk file:- https://drive.google.com/drive/folders/1ZLoLLxurfCRyIn_tm6dop0UVoR8PeXlx diff --git a/app-release.apk b/app-release.apk new file mode 100644 index 0000000..e470442 Binary files /dev/null and b/app-release.apk differ diff --git a/data_repo/img/progress_0.png b/data_repo/img/progress_0.png new file mode 100644 index 0000000..5bd6d3c Binary files /dev/null and b/data_repo/img/progress_0.png differ diff --git a/data_repo/img/progress_1.png b/data_repo/img/progress_1.png new file mode 100644 index 0000000..934ffd0 Binary files /dev/null and b/data_repo/img/progress_1.png differ diff --git a/data_repo/img/progress_2.png b/data_repo/img/progress_2.png new file mode 100644 index 0000000..f763fcc Binary files /dev/null and b/data_repo/img/progress_2.png differ diff --git a/data_repo/img/progress_3.png b/data_repo/img/progress_3.png new file mode 100644 index 0000000..a65312b Binary files /dev/null and b/data_repo/img/progress_3.png differ diff --git a/data_repo/img/progress_4.png b/data_repo/img/progress_4.png new file mode 100644 index 0000000..f3fafd1 Binary files /dev/null and b/data_repo/img/progress_4.png differ diff --git a/data_repo/img/progress_5.png b/data_repo/img/progress_5.png new file mode 100644 index 0000000..ccc374a Binary files /dev/null and b/data_repo/img/progress_5.png differ diff --git a/data_repo/img/progress_6.png b/data_repo/img/progress_6.png new file mode 100644 index 0000000..8906204 Binary files /dev/null and b/data_repo/img/progress_6.png differ diff --git a/data_repo/img/progress_7.png b/data_repo/img/progress_7.png new file mode 100644 index 0000000..cb3eed6 Binary files /dev/null and b/data_repo/img/progress_7.png differ diff --git a/data_repo/img/victory.png b/data_repo/img/victory.png new file mode 100644 index 0000000..33cc464 Binary files /dev/null and b/data_repo/img/victory.png differ diff --git a/lib/engine/hangman.dart b/lib/engine/hangman.dart new file mode 100644 index 0000000..56e7c2f --- /dev/null +++ b/lib/engine/hangman.dart @@ -0,0 +1,92 @@ +import 'dart:async'; + +class HangmanGame { + static const int hanged = 7; // number of wrong guesses before the player's demise + + final List wordList; // list of possible words to guess + final Set lettersGuessed = new Set(); + + List _wordToGuess; + int _wrongGuesses; + + StreamController _onWin = new StreamController.broadcast(); + Stream get onWin => _onWin.stream; + + StreamController _onLose = new StreamController.broadcast(); + Stream get onLose => _onLose.stream; + + StreamController _onWrong = new StreamController.broadcast(); + Stream get onWrong => _onWrong.stream; + + StreamController _onRight = new StreamController.broadcast(); + Stream get onRight => _onRight.stream; + + StreamController _onChange = new StreamController.broadcast(); + Stream get onChange => _onChange.stream; + + HangmanGame(List words) : wordList = new List.from(words); + + void newGame() { + // shuffle the word list into a random order + wordList.shuffle(); + + // break the first word from the shuffled list into a list of letters + _wordToGuess = wordList.first.split(''); + + // reset the wrong guess count + _wrongGuesses = 0; + + // clear the set of guessed letters + lettersGuessed.clear(); + + // declare the change (new word) + _onChange.add(wordForDisplay); + } + + void guessLetter(String letter) { + // store guessed letter + lettersGuessed.add(letter); + + // if the guessed letter is present in the word, check for a win + // otherwise, check for player death + if (_wordToGuess.contains(letter)) { + _onRight.add(letter); + + if (isWordComplete) { + _onChange.add(fullWord); + _onWin.add(null); + } + else { + _onChange.add(wordForDisplay); + } + } + else { + _wrongGuesses++; + + _onWrong.add(_wrongGuesses); + + if (_wrongGuesses == hanged) { + _onChange.add(fullWord); + _onLose.add(null); + } + } + } + + int get wrongGuesses => _wrongGuesses; + List get wordToGuess => _wordToGuess; + String get fullWord => wordToGuess.join(); + + String get wordForDisplay => wordToGuess.map((String letter) => + lettersGuessed.contains(letter) ? letter : "_").join(); + + // check to see if every letter in the word has been guessed + bool get isWordComplete { + for (String letter in _wordToGuess) { + if (!lettersGuessed.contains(letter)) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..616c591 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +import 'package:hangman/engine/hangman.dart'; +import 'package:hangman/ui/hangman_page.dart'; + +const List wordList = const ["PLENTY","ACHIEVE","CLASS","STARE","AFFECT","THICK","CARRIER","BILL","SAY","ARGUE","OFTEN","GROW","VOTING","SHUT","PUSH","FANTASY","PLAN","LAST","ATTACK","COIN","ONE","STEM","SCAN","ENHANCE","PILL","OPPOSED","FLAG","RACE","SPEED","BIAS","HERSELF","DOUGH","RELEASE","SUBJECT","BRICK","SURVIVE","LEADING","STAKE","NERVE","INTENSE","SUSPECT","WHEN","LIE","PLUNGE","HOLD","TONGUE","ROLLING","STAY","RESPECT","SAFELY"]; + +void main() => runApp(HangmanApp()); + +class HangmanApp extends StatefulWidget { + @override + State createState() => _HangmanAppState(); +} + +class _HangmanAppState extends State { + HangmanGame _engine; + + @override + void initState() { + super.initState(); + _engine = HangmanGame(wordList); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Hangman', + debugShowCheckedModeBanner: false, + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: HangmanPage(_engine), + ); + } +} diff --git a/lib/ui/hangman_page.dart b/lib/ui/hangman_page.dart new file mode 100644 index 0000000..69496cc --- /dev/null +++ b/lib/ui/hangman_page.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; + +import 'package:hangman/engine/hangman.dart'; + +const List progressImages = const [ + 'data_repo/img/progress_0.png', + 'data_repo/img/progress_1.png', + 'data_repo/img/progress_2.png', + 'data_repo/img/progress_3.png', + 'data_repo/img/progress_4.png', + 'data_repo/img/progress_5.png', + 'data_repo/img/progress_6.png', + 'data_repo/img/progress_7.png', +]; + +const String victoryImage = 'data_repo/img/victory.png'; + +const List alphabet = const [ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', +]; + +const TextStyle activeWordStyle = TextStyle( + fontSize: 30.0, + letterSpacing: 5.0, +); +class HangmanPage extends StatefulWidget { + final HangmanGame _engine; + + HangmanPage(this._engine); + + @override + State createState() => _HangmanPageState(); +} + +class _HangmanPageState extends State { + + bool _showPlayGame = true; + bool _showNewGame; + String _activeImage; + String _activeWord; + + @override + void _playGame() { + widget._engine.newGame(); + + this.setState(() { + _activeWord = ''; + _activeImage = progressImages[0]; + _showPlayGame = false; + }); + } + void _showInstructions() { + var _ins_text = 'Hangman is a simple word guessing game.\nPlayers try to figure out an unknown word by guessing letters.\nIf too many letters which do not appear in the word are guessed, the player loses.\n'; + showDialog( + context: context, + builder: (context) { + return Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)), + elevation: 16, + child: Container( + height: 400.0, + width: 460.0, + child: ListView( + children: [ + SizedBox(height: 40), + Center( + child: Text( + _ins_text, + style: TextStyle(fontSize: 24, color: Colors.blue, fontWeight: FontWeight.bold,), + textAlign: TextAlign.center, + ), + ), + ElevatedButton( + child: Text('Main Menu',style: TextStyle(fontSize: 30),), + onPressed: () => Navigator.pop(context), + ), + ], + ), + ), + ); + }, + ); + } + void initState() { + super.initState(); + + widget._engine.onChange.listen(this._updateWordDisplay); + widget._engine.onWrong.listen(this._updateGallowsImage); + widget._engine.onWin.listen(this._win); + widget._engine.onLose.listen(this._gameOver); + + this._newGame(); + } + + void _updateWordDisplay(String word) { + this.setState(() { + _activeWord = word; + }); + } + + void _updateGallowsImage(int wrongGuessCount) { + this.setState(() { + _activeImage = progressImages[wrongGuessCount]; + }); + } + + void _win([_]) { + this.setState(() { + _activeImage = victoryImage; + this._gameOver(); + }); + } + + void _gameOver([_]) { + this.setState(() { + _showNewGame = true; + }); + } + + void _newGame() { + widget._engine.newGame(); + + this.setState(() { + _activeWord = ''; + _activeImage = progressImages[0]; + _showNewGame = false; + }); + } + + Widget _renderBottomContent() { + if (_showNewGame) { + return new Container( + child: Column( + children: [ + ElevatedButton( + child: Text('New Game'), + onPressed: this._newGame, + ), + ElevatedButton( + child: Text('Instructions'), + onPressed: this._showInstructions, + ), + ], + ), + ); + } + else { + final Set lettersGuessed = widget._engine.lettersGuessed; + + return Wrap( + spacing: 1.0, + runSpacing: 1.0, + alignment: WrapAlignment.center, + children: alphabet.map((letter) => + MaterialButton( + child: Text(letter), + padding: EdgeInsets.all(2.0), + onPressed: lettersGuessed.contains(letter) ? null : () { + widget._engine.guessLetter(letter); + }, + )).toList(), + ); + } + } + + @override + Widget build(BuildContext context) { + if (_showPlayGame) { + return new Container( + child: Column( + children: [ + new Padding( + padding: const EdgeInsets.symmetric(vertical: 160.0), + ), + ElevatedButton( + child: Text('Play Game',style: TextStyle(fontSize: 30),), + onPressed: this._playGame, + ), + new Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + ), + ElevatedButton( + child: Text('Instructions',style: TextStyle(fontSize: 30),), + onPressed: this._showInstructions, + ), + ], + ), + ); + } + else { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + title: Text('Hangman'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Image + Expanded( + child: Image.asset(_activeImage), + ), + // Word + Padding( + padding: EdgeInsets.all(2.0), + child: Center( + child: Text(_activeWord, style: activeWordStyle), + ), + ), + // Controls + Expanded( + child: Center( + child: this._renderBottomContent(), + ), + ), + ], + ), + ), + ); + } + } +} diff --git a/lib/ui/instructions_page.dart b/lib/ui/instructions_page.dart new file mode 100644 index 0000000..e69de29