Flutter Paper, Scissor and Rock Game

Flutter Paper, Scissor and Rock Game

Introduction

In this tutorial, we are going to use flutter to write a paper, rock and scissor game. It is going to test our understanding of the conditional statements, don't worry you will be able to follow through with this tutorial. We are going to use the basic widget like container, column and text to achieve this. Below is the image of the completed application we are setting out to build.

game views.png the image above shows us different state of the application.

The Rules of the Game.

  • The Paper covers Rock
  • The Scissor cuts Paper
  • The Rock breaks Scissor

When paper covers rocks, the player that chooses paper wins the round and his/her score will be increased by one. The player that chooses either scissor or rock over paper or scissors respectively wins the round and his/her score will be increased. When the two players pick the same item nothing happens and no score increment will be accorded to any person. Let's dive into the implementation of the UI.

Pre-requisite

  • Can set up flutter project
  • Nothing else

UI Implementation

we are going to create a file called util in the lib folder, this file is will take care of the responsiveness of the application. it will help us to adjust the font size of the application in different screen sizes

//  lib/util.dart
import 'package:flutter/material.dart';
ouble screenHeight(BuildContext context, double size) {}
double screenWidth(BuildContext context, double size) {}

class Ymargin extends StatelessWidget {}
class Xmargin extends StatelessWidget {}

screenHeight:

We have four methods that will help us to achieve the responsiveness of this application. The screenHeight method returns the height of the screen if the phone is in portrait mode or width as the new height when it is in the landscape. the parameter of size passed into the method enables us to work with height or width as the case may be. It returns double.

double screenHeight(BuildContext context, double size) {
  var potrait = MediaQuery.of(context).orientation;
  var height = potrait == Orientation.portrait
      ? MediaQuery.of(context).size.height
      : MediaQuery.of(context).size.width;

  return height * (size / 100);
}

screenWidth

It does the same thing as the screenHeight method but it returns the width of the screen size whether in portrait or landscape.

double screenWidth(BuildContext context, double size) {
  var potrait = MediaQuery.of(context).orientation;
  var width = potrait == Orientation.portrait
      ? MediaQuery.of(context).size.height
      : MediaQuery.of(context).size.width;

  return width * (size / 100);
}

margin

We use margin to separate two widgets in either column or row. we will use these util classes when we want space between widgets or when we do not want widgets to cluster together.

class Ymargin extends StatelessWidget {
  final double height;
  const Ymargin({Key key, this.height}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return SizedBox(height: screenHeight(context, height));
  }
}
class Xmargin extends StatelessWidget {
  final width;
  const Xmargin({Key key, this.width}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return SizedBox(height: screenHeight(context, width));
  }
}

At this point, we have been able to set up all the utils we are going to use to make this application to be responsive. The text style file will house the colours that we will be needing for this application. The winning score will be green, the losing score will be red while equal points will leave the text of the two scores to be blue.

the file for text style

// lib/style.dart
TextStyle equal(BuildContext context) =>
    TextStyle(fontSize: screenWidth(context, 5), color: Colors.blue);
TextStyle playerLead(BuildContext context) =>
    TextStyle(fontSize: screenWidth(context, 5), color: Colors.green);
TextStyle computer(BuildContext context) =>
    TextStyle(fontSize: screenWidth(context, 5), color: Colors.red);

goto main file and replace everything in the file with the code below

// lib/main.dart
import 'package:flutter/material.dart';
import 'package:game/paper_scissor_rock.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Music App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: PaperScissorRock(),
    );
  }
}

At this point, our focus has now turned to the full UI implementation of this game. create a file called paper_scissor_rock inside the lib folder. below is the code for the UI

We are using statefulWidget because we want to all our variable declared to be mutable. If the variables changes without rebuilding the state, the screen would not update to the latest values of these variables, because of this we are going to use setState to update the screen to the user. this is the UI we will get.

initial page.png

Game Logic

We need to represent these items with numerical values for easy evaluation for us. we will assign paper, scissor and rock to 0, 1, 2 respectively, with this assignment we are halfway done with our logic. Next is using normal conditional statements to increase player or computer scores depending on who wins the session, no score increment for a draw session. Going back to the rules, paper wins when pitched against rock, scissor wins against paper, rocks wins against scissor. computer picks on random based on what we have written. Explaining the logic with numbers. 0 wins 2, 1 wins 0 and 2 wins 1. We are going to check what each player picks but if by chance they pick the same item, it will be a draw. when a player wins each round or session we will display a message with text colour green but if computer wins we will display a message with colour text red. nothing will be displayed if it is a draw.

// paper = 0, scissor = 1, rock = 2
void play(int index) {
    int compIndex;
    Random rand = Random();
    compIndex = rand.nextInt(3);
    setState(() {
      youWin = true;
      result = "";
      if (index == 0 && compIndex == 2) {
        player++;
        result = " You Win !!!";
        winner = "Paper";
        action = "covers";
        loser = "Rock";
      } else if (index == 1 && compIndex == 0) {
        player++;
        result = " You Win !!!";
        winner = "Scissor";
        action = "cuts";
        loser = "Paper";
      } else if (index == 2 && compIndex == 1) {
        player++;
        result = " You Win !!!";
        winner = "Rock";
        action = "breaks";
        loser = "Scissor";
      } else if (index == compIndex) {
        result = "Draw !!!";
        winner = "";
        action = "";
        loser = "";
      } else {
        youWin = false;
        computerPlayer++;
        result = "You Lose !!!";
        if (index == 2 && compIndex == 0) {
          winner = "Paper";
          action = "covers";
          loser = "Rock";
        } else if (index == 0 && compIndex == 1) {
          winner = "Scissor";
          action = "cuts";
          loser = "Paper";
        } else if (index == 1 && compIndex == 2) {
          winner = "Rock";
          action = "breaks";
          loser = "Scissor";
        }
      }
    });
  }