Sudoku Solver in Flutter — Understanding Flutter State Management by Example — Part 1

Nikhil Heda
ITNEXT
Published in
6 min readApr 7, 2020

--

WARNING: These “series of” articles assume a basic understanding on Flutter and is NOT a tutorial (flutter documentation is really good for that), this is more of my exploration into flutter as a beginner — widgets, layouts, some design concepts, and mainly stuff about state management.

PS: This article is longer than I imagined it would be! — so split across multiple articles!

Hey guys!

I came across flutter, and was pretty impressed with what it had to offer — single framework for building applications on multiple platforms! So thought would explore it.

Went through some tutorials, read up on Dart (simple enough), built a sample example application on flutter and I had a basic understanding on flutter concepts — flutter CLI, widgets (stateful and stateless), widget trees, basic layouts, etc.

After getting comfortable with flutter, I went to build out an actual application — isn’t that the point!

Spent a weekend building a basic application in Flutter, and came across a lot of concepts and just had to share it.

This article is divided into 4 posts, if you are interested in any particular concept — jump ahead!—

Part 1: Introduction — Discussing layouts, widgets, functionality and shared state.

Part 2: Using basic stateful widgets for state management.

Part 3: Managing state using Inherited Widgets

Part 4: Providers!

The Application

We will be building a Sudoku Solver (I had built this out in Android — java/xml/custom drawables/adapters and all that “AWESOME” stuff 🙂). Happy to say, flutter is pretty amazing, the app that took me around a week to build in Android, took only a couple of days in Flutter.

What does it do?

It does what it says — it solves Sudoku puzzles! To start off, our Sudoku Solver has the following components:

  1. Sudoku Board — A grid of Sudoku Cells
  2. Sudoku Cell — The cell with a number/blank
  3. Key Pad — To select the number to fill in the board.

Basic user interaction

I have used snaps from my final application, which includes a bit more of layout tuning, not covering in this article.

Pretty simple. Let’s start.

Layouts and Widgets!

First thing we need is to build a basic layout — look and feel. A dummy app with no functionality but focused on layout design.

SudokuBoard widget

Sudoku Board

The most obvious widget for this was the GridView widget. It looks good, only thing with grid views is that it’s scrollable, and hardly the functionality you want in a Sudoku Grid. Enter… Tables!

Tables are pretty good, no scroll, can control borders, values, cell layouts, etc. So Winner!

SudokuCell widget

Sudoku Cell

No specific layout required for this, just went ahead with the Container widget.

Needed a click handler (as cells will be clicked to set the value to some number selected from the keypad), so just wrapped this widget around an InkResponse widget.

Also capturing row and column numbers, might be helpful.

KeyPad widget

Key Pad

Simple enough, need a grid of 10 numbers (0 to 9, using 0 as an eraser).

Grid View wont help, went with the Table widget again.

KeyPadCell widget

Key Pad Cell

Cells as Flat Buttons, as I want to register click handlers.

Also, capturing the number associated with this cell.

That’s pretty much it with layouts.

Widget Tree

Let’s look at the widget tree, this will give us a better understanding on how the widgets are related.

Final Screen

I played around a bit more with layouts

  1. Added rows, columns and padding for better alignment and spacing.
  2. Added table borders, and cell borders — this required a bit of logic for handling the thin and thick borders. Not rocket science.
  3. Added Solve and Reset buttons.

Not going into details — nothing much exciting here, just that it’s pretty easy compared to the raw android xml layouts, which is “not that convenient”. Let me know if you guys want me to elaborate on layout design!

Functionality!

This is a really good candidate to test basic state management in Flutter, because there is state everywhere in this app —

  1. Handling state within a widget (Sudoku Cell/Sudoku Board)
  2. State affecting state of other widgets (Key Pad numbers affecting state of Sudoku Cells)
  3. Change in state due to interactions with business logic (logic for solving puzzle).

Handling state efficiently is essential here, so let’s get into it.

Handling Shared State!

I will detail out this section as this is exciting stuff!

So I went through a lot of frustrating ways to get this working, learnt a lot about application design (sadly, the framework can’t do this for you!)

2 questions are very important while handling shared state —

  1. What is the shared state?
  2. Where/who should be responsible for it, to enable easy interactions?

What is the shared state?

There are 2 things being shared in our application:

  1. Sudoku board: A 2-d array of numbers which will be used to keep track of the board state. This will be read and modified by SudokuCell widgets.
  2. Active number: This keeps track of the number to be written on the board. This value is written by KeyPadCell and read by SudokuCell.

This is common for all the approaches. This is the shared state.

Who is responsible for this? — I will go through the designs I tried in this series, and answer this in different ways.

Other stuff in the app, not included in this post

Layout Tuning

  1. Adding in Borders/Table Borders to make the grid look like Sudoku board.
  2. Highlight colors — Highlighting the selected number on Key Pad and filled numbers on Sudoku Cell.
  3. Validations — Validating if the partially filled board is a valid sudoku puzzle.

Sudoku Solver Logic!

The logic used for solving the partially filled sudoku puzzle!

Let me know if you want me to elaborate on these aspects of this app! Would be happy to share it on another article!

--

--