Skip to content

Instantly share code, notes, and snippets.

@olaide-ekolere
Last active May 31, 2020 16:47
Show Gist options
  • Save olaide-ekolere/dc109b2c27c535792507b84803eb5842 to your computer and use it in GitHub Desktop.
Save olaide-ekolere/dc109b2c27c535792507b84803eb5842 to your computer and use it in GitHub Desktop.
A game of rock paper scissors using flutter
import 'package:flutter/material.dart';
import 'dart:math';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: HomeWidget(),
);
}
}
class HomeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: AnimatedContainer(
color: Colors.blue,
duration: Duration(seconds: 1),
padding: EdgeInsets.symmetric(
horizontal: 32.0,
vertical: 48.0,
),
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Highest',
style: Theme.of(context).textTheme.bodyText1.copyWith(
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
Text(
'$highestScore',
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
SizedBox(
height: 32.0,
),
Text(
'Rock\nPaper\nScissors',
style: Theme.of(context).textTheme.headline4.copyWith(
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
SizedBox(
height: 96.0,
),
_buildGameButton(
context,
'Start Game',
() => _startGame(context),
),
_buildGameButton(
context,
'Rules',
() => _showRules(context),
),
],
)),
),
));
}
_startGame(BuildContext context) {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (_) => GameWidget()));
}
_showRules(BuildContext context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => RulesWidget()));
}
}
class RulesWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blue,
padding: EdgeInsets.symmetric(
horizontal: 32.0,
vertical: 48.0,
),
child: Center(
child: Container(
width: 360,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_buildRulesTable(context),
SizedBox(
height: 48.0,
),
_buildGameButton(
context, 'BACK', () => Navigator.of(context).pop()),
],
),
),
),
),
),
);
}
Widget _buildRulesTable(BuildContext context) {
return Table(
border: TableBorder.all(
color: Colors.white, width: 1, style: BorderStyle.solid),
children: [
TableRow(children: [
TableCell(
child: Center(
child: Text(
'CASE',
style: Theme.of(context).textTheme.headline6,
))),
TableCell(
child: Center(
child: Text(
'WIN',
style: Theme.of(context).textTheme.headline6,
))),
TableCell(
child: Center(
child: Text(
'LOSE',
style: Theme.of(context).textTheme.headline6,
))),
]),
TableRow(children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Center(
child: Text(
'1',
style: Theme.of(context).textTheme.headline6,
))),
TableCell(child: _buildMoveTile(Move.Rock)),
TableCell(child: _buildMoveTile(Move.Scissors)),
]),
TableRow(children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Center(
child: Text(
'2',
style: Theme.of(context).textTheme.headline6,
))),
TableCell(child: _buildMoveTile(Move.Paper)),
TableCell(child: _buildMoveTile(Move.Rock)),
]),
TableRow(children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Center(
child: Text(
'3',
style: Theme.of(context).textTheme.headline6,
))),
TableCell(child: _buildMoveTile(Move.Scissors)),
TableCell(child: _buildMoveTile(Move.Paper)),
])
],
);
}
}
class GameWidget extends StatefulWidget {
createState() => _GameWidgetState();
}
class _GameWidgetState extends State<GameWidget> {
Game game;
@override
void initState() {
super.initState();
game = Game();
}
@override
Widget build(BuildContext context) {
double sectionHeight = MediaQuery.of(context).size.height / 2.0;
if (sectionHeight < 240) sectionHeight = 240;
return Scaffold(
body: Stack(children: <Widget>[
Table(
children: [
TableRow(children: [
TableCell(
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
height: sectionHeight,
padding: EdgeInsets.all(24.0),
color: game.top,
child: _buildTop(),
),
)
]),
TableRow(children: [
TableCell(
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
height: sectionHeight,
padding: EdgeInsets.all(24.0),
color: game.bottom,
child: _buildBottom()),
)
]),
],
),
Align(
alignment: Alignment.center,
child: Container(
color: Colors.white,
height: 8.0,
width: MediaQuery.of(context).size.width,
),
),
Align(
alignment: Alignment.center,
child: _buildCenter(),
),
]),
);
}
Widget _buildTop() {
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Container(height: 50, child: _buildHUD()),
Expanded(
child: Container(
child: Center(
child: _displayTile(game.status == Status.PlayerMove
? Icon(
Icons.hourglass_full,
)
: _buildMoveTile(game.opponent)),
)),
)
],
);
}
Widget _buildCenter() {
return Container(
width: 240,
height: 72,
padding: EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(25),
border: Border.all(color: Colors.white, width: 8)),
child: Center(
child: Text(
game.statusText,
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(color: Colors.white),
),
),
);
}
Widget _buildBottom() {
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Container(
child: Center(
child: GestureDetector(
onTap: _changeMove,
child: _displayTile(_buildMoveTile(game.player))
),
)),
),
Container(child: _buildActionButton()),
],
);
}
Widget _buildActionButton() {
return GestureDetector(
onTap: _doAction,
child: Container(
width: 240,
margin: EdgeInsets.only(
bottom: 16.0,
),
padding: EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
decoration: BoxDecoration(
border: Border.all(color: Colors.yellow, width: 4),
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: Text(
game.actionText,
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(color: Colors.yellow),
),
),
));
}
Widget _displayTile(Widget child) {
return Container(
height: 120.0,
width: 120.0,
decoration: BoxDecoration(
color: Colors.orange, borderRadius: BorderRadius.circular(60)),
child: Center(child: child));
}
Widget _buildHUD() {
return Stack(
children: [
Align(
alignment: Alignment.centerLeft,
child: _buildInfo('Score', game.wins),
),
Align(
alignment: Alignment.centerRight,
child: _buildInfo('Highcore', highestScore),
),
],
);
}
Widget _buildInfo(String title, int value) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title, textAlign: TextAlign.center),
Text('$value', textAlign: TextAlign.center)
],
);
}
_changeMove(){
if(game.status==Status.PlayerMove){
setState(()=>game.player = Move.values[(game.player.index+1)%Move.values.length]);
}
}
_doAction() {
if(game.status==Status.PlayerMove){
setState(()=>game.checkWinner());
}
else{
setState(()=>game.nextGame());
}
}
}
Widget _buildGameButton(BuildContext context, String text, Function f) {
return GestureDetector(
onTap: f,
child: Container(
width: 240,
margin: EdgeInsets.only(
bottom: 16.0,
),
padding: EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
decoration: BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: Text(
text,
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(color: Colors.black),
),
),
));
}
Widget _buildMoveTile(Move move) {
return Container(
padding: EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(
_getMoveIcon(move),
),
SizedBox(
height: 8.0,
),
Text(_getMoveText(move))
],
),
),
);
}
IconData _getMoveIcon(Move move) {
if (move == Move.Rock)
return Icons.public;
else if (move == Move.Scissors)
return Icons.content_cut;
else
return Icons.receipt;
}
String _getMoveText(Move move) {
if (move == Move.Rock)
return 'Rock';
else if (move == Move.Scissors)
return 'Scissors';
else
return 'Paper';
}
int highestScore = 0;
enum Move { Rock, Paper, Scissors } //scissors - content_cut
//rock - public
//paper - receipt
enum Status { PlayerMove, Win, Draw, Lost }
class Game {
Move player;
Move _opponent;
int _numberOfWins = 0;
bool _playerWin;
bool _opponentWin;
Status _status = Status.PlayerMove;
Random random = Random();
Game({this.player = Move.Rock});
Move get opponent => _opponent;
Status get status => _status;
int get wins => _numberOfWins;
String get statusText {
if (_status == Status.PlayerMove)
return 'Click to Change';
else if (_status == Status.Win)
return 'You Win!!!';
else if (_status == Status.Lost)
return 'You lost!!!';
else
return 'It was a tie';
}
String get actionText {
if (_status == Status.PlayerMove)
return 'SUBMIT';
else if (_status == Status.Win)
return 'NEXT';
else if (_status == Status.Lost)
return 'Try Again';
else
return 'Rematch';
}
Color get top {
if (_status == Status.PlayerMove) return Colors.blue;
else if(_opponentWin) return Colors.green;
else return Colors.red;
}
Color get bottom {
if (_status == Status.PlayerMove) return Colors.blue;
else if(_playerWin) return Colors.green;
else return Colors.red;
}
checkWinner() {
//create Opponent's move
_opponent = Move.values[random.nextInt(123)%Move.values.length];
_playerWin = _checkMove(player, _opponent);
_opponentWin = _checkMove(_opponent, player);
if (_playerWin) {
_numberOfWins += 1;
_status = Status.Win;
} else if (_playerWin == _opponentWin) {
_status = Status.Draw;
} else {
_status = Status.Lost;
if (_numberOfWins > highestScore) highestScore = _numberOfWins;
}
}
nextGame(){
if(_status==Status.Lost) _numberOfWins = 0;
_status = Status.PlayerMove;
}
bool _checkMove(Move a, Move b) {
bool win = false;
if (a == Move.Rock && b == Move.Scissors) {
win = true;
} else if (a == Move.Paper && b == Move.Rock) {
win = true;
} else if (a == Move.Scissors && b == Move.Paper) {
win = true;
}
return win;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment