Guess Word Design For HangMan Game

We have already covered designing the Stick Figure of our HangMan game in our previous posts. Now, we move onto next phase of our game and that is the guess word design part.

Guess Word Design

Our HangMan game which we are building in Flutter is going to need an interface where users can guess the right word. As per the rule of the game, users can guess one character at a time.

So, we need an interface which allows the player to guess one character at a time.

DecisionMentor app

Setup Guess Word Puzzle Widget

We start by creating a widget called Puzzle which takes the word to guess as parameter.

class Puzzle extends StatefulWidget {
  final String guessWord;

  const Puzzle({Key key, this.guessWord}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _PuzzleState();
}

The state of the widget will dynamically change on the length of the guess word.

For example, if the word to guess was “HANGMAN”, we need an interface that allows 7 letters to be guessed. If the word was only “HANG”, the interface should allow 4 letters for guessing.

class _PuzzleState extends State<Puzzle> {

  int _selectedBoxIndex = 0;

  void _updateSelectedIndex(int i) {
    setState(() {
      _selectedBoxIndex = i;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Wrap(
        spacing: 8.0,
        runSpacing: 8.0,
        children: List.generate(widget.guessWord.length, (i){
          return _buildSingleCharacterBox(i);
        })
      )
    );
  }

  Widget _buildSingleCharacterBox(int index) {
    return GestureDetector(
      onTap: () {
        _updateSelectedIndex(index);
      },
      child: Container(
        height: 48.0,
        width: 48.0,
        decoration: BoxDecoration(
          color: index == _selectedBoxIndex ? Colors.limeAccent : Colors.white,
          borderRadius: BorderRadius.circular(4.0)
        ),
      ),
    );
  }
}

To identify which character the user is currently guessing, we have used _selectedBoxIndex`. The selected box is updated whenever the player taps on any box.

For ensuring the individual characters are wrapped well in a growing list we have made use of the Wrap widget.

View Design In Action

Next, update the GameState widget to include the Puzzle widget and see things in action.

import 'package:flutter/material.dart';
import 'package:hangman/hangman_painter.dart';
import 'package:hangman/puzzle.dart';

class GameStage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _GameStage();
  }
}

class _GameStage extends State<GameStage> {
  @override
  Widget build(BuildContext context) {
    var mediaQd = MediaQuery.of(context).size;
    return Scaffold(
      body: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topRight,
              end: Alignment.bottomLeft,
              colors: [Colors.blue, Colors.red]
            )
          ),
          padding: EdgeInsets.all(24.0),
          width: mediaQd.width,
          height: mediaQd.height,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Container(
                width: 270,
                height: mediaQd.height,
                padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 12.0),
                child: CustomPaint(
                  painter: HangManPainter(),
                  size: Size(
                    (270 - 24.0),
                    (mediaQd.height - 24.0),
                  ),
                ),
              ),
              Expanded(
                child: Container(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      Puzzle(guessWord: "HANaskjdasGMAN",)
                    ],
                  )
                ),
              )
            ],
          )),
    );
  }
}
HangMan Guess Word Design 1
HangMan Guess Word Design 1

Next, we need a mechanism for the player to pick a guess character.

Guess Letter Design

With similar approach as before, we can easily create CharacterPicker widget in Flutter for our game.

import 'package:flutter/material.dart';

class CharacterPicker extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _CharacterPickerState();
}

class _CharacterPickerState extends State<CharacterPicker> {
  var _alphabets = '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';

  List<String> _guessedLetters;

  @override
  void initState() {
    super.initState();
    _guessedLetters = List<String>();
  }

  @override
  Widget build(BuildContext context) {
    var alphabetArr = _alphabets.split(',');
    return Container(
      child: Wrap(
        spacing: 8.0,
        runSpacing: 8.0,
        children: List.generate(alphabetArr.length, (i){
          var letter = alphabetArr[i];
          return _buildSingleCharacter(letter);
        })
      )
    );
  }

  Widget _buildSingleCharacter(String letter) {
    return GestureDetector(
      onTap: () {
        setState(() {
          _guessedLetters.add(letter);
        });        
      },
      child: Container(
        width: 24.0,
        height: 24.0,
        decoration: BoxDecoration(
          color: _guessedLetters.contains(letter)? Colors.grey : Colors.white,
          borderRadius: BorderRadius.circular(4.0)
        ),
        child: Center(child: Text(letter)),
      ),
    );
  }
}

CharacterPicker is quite identical with Puzzle widget except that it has an array of alphabets and selected alphabets.

If the alphabet is previously selected, we set it to grey color, else it is colored as white.

View Demo With Character Picker

Again, update the GameStage widget to include the CharacterPicker widget.

...
Expanded(
child: Container(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: <Widget>[
      CharacterPicker(),
      Puzzle(guessWord: "HANGMAN",)
    ],
  )
),
)
...

Run the app once again.

HangMan Character Picker Design
HangMan Character Picker Design

Wrapping Up

We have now designed the interface to show the players an interface to guess the puzzle word. Also, user can pick any letter to guess from the given array of alphabets.

What now remains is to tie all the things up together. We want to make everything functional.

Whenever user picks a letter to guess, if the letter is correct, reveal it inside the guess word. Else, begin hanging the Stick Figure!

Continue the series: Managing State Of HangMan Game