Photo by Tony Pepe on Unsplash

Getting Started on Flutter World: Part 3—Dart Language

Cassia Barbosa

--

Hey, folks! You're here again, welcome! Well, before we get started creating amazing apps, we need to know how to really code. Because of that, I'm really gonna take a time to explain you about Dart language:

a client-optimized language for developing fast apps on any platform, also forming the foundation of Flutter. Dart provides the language and runtimes that power Flutter apps, but Dart also supports many core developer tasks like formatting, analyzing, and testing code.

I'm gonna present you some Dart's particularities building a card game. Here is the rules:

To simulate we have a shuffled deck of 52 cards enumerated 0 to 9, you will enter a range of value, for example, between 2 and 7, and after that, system will give you a card in that range, and it will take a card in that range also for itself. If the number of your card is greater than its, you will gain 3 points, if the system one is greater than yours, system will gain 3 points, but it the value of both cards is the same, nothing happens with pontuation. It will win who has more points after 26 frames.

Object oriented

Dart allows us to create objects that contain data and functions. They are called classes, and they create objects which contain some data and behaviors that are necessary on application. Shall we go deeper into dart's code peculiarities?

Creating a new class:

Go to VSCode, create a new folder, and inside of it, create a new file called player.dart:

class Player {
String _name;
int _points = 0;

get total => _points;
get name => _name;

Player({String name = "Unknown"}) : _name = name;

void updatePontuation() {
_points += 1;
}
}

There are two private variables (_ annotation is to make a variable or function private) and before to give it a name, we need (almost always, I'll explain it soon) to add the type of it. Please, don't forget to add ;annotation, we use it to finish a command.

Now that you know the private annotation, let's talk about get methods: if we have declared some variable as private inside our class and if we need to use that variable out of class, we need to create a new get variable, and with => annotation, we are gonna say, when we call the new get variable, we are actually requesting the value of the private one.

Well, to use the class we need constructors. As you can see,_points has its own initial value, so we don't need to add it on constructor, but,_name doesn't. Because of that, we are saying on constructor we want aString value, called here as name. But, we are also passing a default value on constructor, it means, if I do not pass the value, the program will assume the default value is that one the I passed on constructor.

The last part to take a look on that class is about the method updatePontuation(). It's a simple function where value of _points variable will be incremented, and nothing will be returned, because of that I use void before its name.

Perfect! Now we have a player, let's implement our Game class to play the game.

Creating classes in different files:

Creating a new file now called game.dart.

import './player.dart';

class Game {
int initalRange = -1;
int finalRange = -1;
var player = Player();
Player system = Player(name: "System");

Game();

play(int playerSortedValue, int systemSortedValue) {
if (playerSortedValue > systemSortedValue) {
player.updatePontuation();
} else {
system.updatePontuation();
}
}

List<Player> finish() {
return [this.player, this.system];
}
}

The first thing we need to pay attention is about import: I created that class in a different file of Player one, so, to use Player here in Game class, I need to give it the path.

As variables, we have two curious ones, 'player' and 'system': they are variable from my previous defined type Player, but one of it I've added the type var before. With that, I'm using the dynamic type, it means I 'll let me compiler knows the type only when I create the object.

Jumping to play method, I'm creating a function that will receive two int no named parameters, I mean, when I call the function, I'll not see the name of each parameter on code, but, when I add the values, I need to respect the other. After that, it will do some computation, it won't return anything, and I'm not adding void before its name. YES, void can be omitted :)

Any doubts? I hope not! So, let's to take a look on our main.dart file, it will be a little bigger than the others.

main.dart:

Now, create a new file called main.dart.
Yeah, Dart needs a main file, it’s where our application runs.

import './game.dart';
import 'dart:io';
import 'dart:math';

main() {
var game = Game();

int _numberOfFrame = 1;

for (_numberOfFrame; _numberOfFrame <= 26; _numberOfFrame++) {
while (game.initalRange == -1 || game.initalRange > 10) {
print("Enter the inital value of range $_numberOfFrame");

game.initalRange = int.parse(stdin.readLineSync()!);
}

while (game.finalRange == -1 || game.finalRange > 10) {
print("Enter the final value of range $_numberOfFrame");

game.finalRange = int.parse(stdin.readLineSync()!);
}

var playerValue =
game.initalRange + Random().nextInt(game.finalRange - game.initalRange);
var systemValue =
game.initalRange + Random().nextInt(game.finalRange - game.initalRange);
print(
"The range of frame #$_numberOfFrame will be between ${game.initalRange} and ${game.finalRange}.\nYour sorted value was: $playerSortedValue\nSystem's sorted value was: $systemSortedValue");

game.play(playerValue, systemValue);

game.initalRange = -1;
game.finalRange = -1;
}

var results = game.finish();

if (results[0].total > results[1].total) {
print("${results[0].name} has won!");
} else if (results[0].total < results[1].total) {
print("${results[1].name} has won!");
} else {
print("You tied!");
}
}

Here is where we're adding the logic of the game: for 26 times, we are asking a range and we are sorting one value for player and another one for system. Calling game.play(playerValue, systemvalue), we are updating only the points of the winner of the frame. Pay attention: I'm using others variables whose names don't match with defined parameters on function, because I omitted the parameters when I created the function. To have also here the names of the parameters, I must create a function like this:

play({required int playerSortedValue, required int systemSortedValue}) {
if (playerSortedValue > systemSortedValue) {
player.updatePontuation();
} else {
system.updatePontuation();
}
}

And on main, I must call like this:

game.play(playerSortedValue: playerValue, systemSortedValue: systemValue);
The range of frame #$_numberOfFrame

Interpolation:

On an application without any interface, we need to show what is happening on it, and users must understand it. That being said, a great way is to print variables and actions that is being taken. So, to use some variable inside a string, we can do in two ways: or we use $ annotation before the variable, like in "The range of frame #$_numberOfFrame", or we can use "The range of frame #{$_numberOfFrame}" with #${variableName} annotation.

Ok, now, we can go to terminal inside VSCode and run this command:

dart main.dart

and, play our funny game!

Well, guys, that's all for today! I tried to present you the basic of basics to create a good code on Dart. See you later, when Matias Silveiro is gonna focus on FLUTTER and he is gonna talk about WIDGETS ❤.

--

--