I’m making a pomodoro timer app. When I go to the SettingsScreen and come back to the home screen it reset the setNum value to 0 and the done value to 0.
I need to keep those previous values when I come back from the SettingsScreen.
In the settings screen, If I changed
Navigator.of(context).push(MaterialPageRoute()
To this
Navigator.of(context).pop(MaterialPageRoute()
In home screen, it will keep the previous values and it won’t change setNum to 0 but then I cannot change Times from that screen.
How to solve this?
Home Screen
import 'dart:async';
import 'dart:ffi';
import 'package:audioplayers/audio_cache.dart';
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:pomodoroapp/model/menu_item.dart';
import 'package:pomodoroapp/model/pomodoro_status.dart';
import 'package:pomodoroapp/screens/report_screen.dart';
import 'package:pomodoroapp/screens/settings_screen.dart';
import 'package:pomodoroapp/utils/constants.dart';
import 'package:pomodoroapp/widget/custom_button.dart';
import 'package:pomodoroapp/widget/menu_items.dart';
import 'package:pomodoroapp/widget/progress_icons.dart';
class Home extends StatefulWidget {
//////////////////////// passed (changed) values //////////////////////
final pomodoroTimeChanged;
final shortBreakTimeChanged;
final longBreakTimeChanged;
Home(
{Key key,
this.pomodoroTimeChanged,
this.shortBreakTimeChanged,
this.longBreakTimeChanged})
: super(key: key);
#override
State<Home> createState() => _HomeState(
pomodoroTimeChanged, shortBreakTimeChanged, longBreakTimeChanged);
}
//////////////////////// main button labels ////////////////////////
const _btnTextStart = 'START';
const _btnTextResumePomodoro = 'RESUME';
const _btnTextResumeBreak = 'RESUME';
const _btnTextStartShortBreak = 'START';
const _btnTextStartLongBreak = 'START';
const _btnTextStartNewSet = 'START NEW SET';
const _btnTextPause = 'PAUSE';
const _btnTextReset = 'RESET';
#override
class _HomeState extends State<Home> {
//////////////////////// values //////////////////////
int pomodoroTime;
int shortBreakTime;
int longBreakTime;
//////////////////////// default times //////////////////////
int pomodoroTimeDefault = 5;
int shortBreakTimeDefault = 2;
int longBreakTimeDefault = 3;
int pomodoriPerSet = 4;
int pomodoroTimeChanged;
int shortBreakTimeChanged;
int longBreakTimeChanged;
_HomeState(this.pomodoroTimeChanged, this.shortBreakTimeChanged,
this.longBreakTimeChanged);
static AudioCache player = AudioCache();
int remainingTime = pomodoroTotalTime;
String mainBtnText = _btnTextStart;
PomodoroStatus pomodoroStatus = PomodoroStatus.pausedPomodoro;
Timer _timer;
int pomodoroNum = 0;
int setNum = 0;
//////////////////////// dispose, to avoid memory leak //////////////////////
#override
void dispose() {
_cancelTimer();
super.dispose();
}
/////////////////////// Update state function for changed value ///////////////////////
_updateStatepomodoroTime() {
setState(() {
remainingTime = pomodoroTime;
});
}
_updateStateShortBreakTime() {
setState(() {
remainingTime = shortBreakTime;
});
}
_updateStateLongBreakTime() {
setState(() {
remainingTime = longBreakTime;
});
}
#override
void initState() {
super.initState();
player.load('bell.mp3');
//////////////////// setting an initial value //////////////////////
if (pomodoroTimeChanged != null) {
pomodoroTime = pomodoroTimeChanged;
_updateStatepomodoroTime();
} else {
pomodoroTime = pomodoroTimeDefault;
}
if (shortBreakTimeChanged != null) {
shortBreakTime = shortBreakTimeChanged;
//_updateStateShortBreakTime();
_updateStatepomodoroTime();
} else {
shortBreakTime = shortBreakTimeDefault;
}
if (longBreakTimeChanged != null) {
longBreakTime = longBreakTimeChanged;
//_updateStateLongBreakTime();
_updateStatepomodoroTime();
} else {
longBreakTime = longBreakTimeDefault;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: Colors.grey[900],
appBar: PreferredSize(
preferredSize: Size.fromHeight(27.0),
child: AppBar(
backgroundColor: Colors.transparent,
automaticallyImplyLeading: false,
iconTheme: IconThemeData(color: Colors.white, size: 10.0),
elevation: 0,
actions: [
PopupMenuButton<MenuItem>(
onSelected: (item) => onSelected(context, item),
itemBuilder: (context) =>
[...MenuItems.itemsFirst.map(buildItem).toList()],
)
],
),
),
body: Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://firebasestorage.googleapis.com/v0/b/flutterbricks-1926c.appspot.com/o/images%2Fwidgets%2F1634411682152%2FScreen%20Shot%202021-10-16%20at%203.14.09%20PM.png?alt=media&token=ec556af9-6dff-4020-a530-2b1eec58dafe'),
fit: BoxFit.cover,
),
),
child: Center(
child: Column(
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularPercentIndicator(
radius: 220.0,
lineWidth: 15.0,
percent: _getPomodoroPercentage(),
circularStrokeCap: CircularStrokeCap.round,
center: Text(
_secondsToFormatedString(remainingTime),
style:
const TextStyle(fontSize: 40, color: Colors.white),
),
progressColor: statusColor[pomodoroStatus],
),
const SizedBox(
height: 12,
),
ProgressIcons(
total: pomodoriPerSet,
done: pomodoroNum - (setNum * pomodoriPerSet),
),
const SizedBox(
height: 12,
),
Text(
'#$setNum',
style: const TextStyle(fontSize: 15, color: Colors.grey),
),
const SizedBox(
height: 5,
),
Text(
statusDescription[pomodoroStatus],
style: const TextStyle(color: Colors.white),
),
const SizedBox(
height: 12,
),
const SizedBox(
height: 12,
),
CustomButton(
onTap: _mainButtonPressed,
text: mainBtnText,
),
CustomButton(
onTap: _resetButtonPressed,
text: _btnTextReset,
)
],
),
)
],
),
),
),
);
}
_secondsToFormatedString(int seconds) {
int roundedMinutes = seconds ~/ 60;
int remainingSeconds = seconds - (roundedMinutes * 60);
String remainingSecondsFormated;
if (remainingSeconds < 10) {
remainingSecondsFormated = '0$remainingSeconds';
} else {
remainingSecondsFormated = remainingSeconds.toString();
}
return '$roundedMinutes:$remainingSecondsFormated';
}
_getPomodoroPercentage() {
int totalTime;
switch (pomodoroStatus) {
case PomodoroStatus.runingPomodoro:
totalTime = pomodoroTime;
break;
case PomodoroStatus.pausedPomodoro:
totalTime = pomodoroTime;
break;
case PomodoroStatus.runningShortBreak:
totalTime = shortBreakTime;
break;
case PomodoroStatus.pausedShortBreak:
totalTime = shortBreakTime;
break;
case PomodoroStatus.runningLongBreak:
totalTime = longBreakTime;
break;
case PomodoroStatus.pausedLongBreak:
totalTime = longBreakTime;
break;
case PomodoroStatus.setFinished:
totalTime = pomodoroTime;
break;
}
double percentage = (totalTime - remainingTime) / totalTime;
return percentage;
}
_mainButtonPressed() {
switch (pomodoroStatus) {
case PomodoroStatus.pausedPomodoro:
_startPomodoroCountdown();
break;
case PomodoroStatus.runingPomodoro:
_pausePomodoroCountdown();
break;
case PomodoroStatus.runningShortBreak:
_pauseShortBreakCountdown();
break;
case PomodoroStatus.pausedShortBreak:
_startShortBreak();
break;
case PomodoroStatus.runningLongBreak:
_pauseLongBreakCountdown();
break;
case PomodoroStatus.pausedLongBreak:
_startLongBreak();
break;
case PomodoroStatus.setFinished:
setNum++;
_startPomodoroCountdown();
break;
}
}
_startPomodoroCountdown() {
pomodoroStatus = PomodoroStatus.runingPomodoro;
_cancelTimer();
if (_timer != null) {
_timer.cancel();
}
_timer = Timer.periodic(
Duration(seconds: 1),
(timer) => {
if (remainingTime > 0)
{
setState(() {
remainingTime--;
mainBtnText = _btnTextPause;
})
}
else
{
_playSound(),
pomodoroNum++,
_cancelTimer(),
if (pomodoroNum % pomodoriPerSet == 0)
{
pomodoroStatus = PomodoroStatus.pausedLongBreak,
setState(() {
remainingTime = longBreakTime;
mainBtnText = _btnTextStartLongBreak;
}),
}
else
{
pomodoroStatus = PomodoroStatus.pausedShortBreak,
setState(() {
remainingTime = shortBreakTime;
mainBtnText = _btnTextStartShortBreak;
}),
}
}
});
}
_startShortBreak() {
pomodoroStatus = PomodoroStatus.runningShortBreak;
setState(() {
mainBtnText = _btnTextPause;
});
_cancelTimer();
_timer = Timer.periodic(
Duration(seconds: 1),
(timer) => {
if (remainingTime > 0)
{
setState(() {
remainingTime--;
}),
}
else
{
_playSound(),
remainingTime = pomodoroTime,
_cancelTimer(),
pomodoroStatus = PomodoroStatus.pausedPomodoro,
setState(() {
mainBtnText = _btnTextStart;
}),
}
});
}
_startLongBreak() {
pomodoroStatus = PomodoroStatus.runningLongBreak;
setState(() {
mainBtnText = _btnTextPause;
});
_cancelTimer();
_timer = Timer.periodic(
Duration(seconds: 1),
(timer) => {
if (remainingTime > 0)
{
setState(() {
remainingTime--;
}),
}
else
{
_playSound(),
remainingTime = pomodoroTime,
_cancelTimer(),
pomodoroStatus = PomodoroStatus.setFinished,
setState(() {
mainBtnText = _btnTextStartNewSet;
}),
}
});
}
_pausePomodoroCountdown() {
pomodoroStatus = PomodoroStatus.pausedPomodoro;
_cancelTimer();
setState(() {
mainBtnText = _btnTextResumePomodoro;
});
}
_resetButtonPressed() {
pomodoroNum = 0;
setNum = 0;
_cancelTimer();
_stopCountdown();
}
_stopCountdown() {
pomodoroStatus = PomodoroStatus.pausedPomodoro;
setState(() {
mainBtnText = _btnTextStart;
remainingTime = pomodoroTime;
});
}
_pauseShortBreakCountdown() {
pomodoroStatus = PomodoroStatus.pausedShortBreak;
_pauseBreakCountdown();
}
_pauseLongBreakCountdown() {
pomodoroStatus = PomodoroStatus.pausedLongBreak;
_pauseBreakCountdown();
}
_pauseBreakCountdown() {
_cancelTimer();
setState(() {
mainBtnText = _btnTextResumeBreak;
});
}
_cancelTimer() {
if (_timer != null) {
_timer.cancel();
}
}
_playSound() {
player.play('bell.mp3');
}
PopupMenuItem<MenuItem> buildItem(MenuItem item) => PopupMenuItem<MenuItem>(
value: item,
child: Row(children: [
Icon(
item.icon,
color: Colors.black,
size: 20,
),
const SizedBox(
width: 12,
),
Text(item.text)
]),
);
void onSelected(BuildContext context, MenuItem item) {
switch (item) {
case MenuItems.itemSettings:
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SettingsScreen()),
);
break;
case MenuItems.itemReport:
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => ReportScreen()),
);
break;
}
}
}
class PopUpMenu extends StatelessWidget {
final List<PopupMenuEntry> menuList;
final Widget icon;
const PopUpMenu({Key key, this.menuList, this.icon}) : super(key: key);
#override
Widget build(BuildContext context) {
return PopupMenuButton(
itemBuilder: (context) => menuList,
icon: icon,
);
}
}
Settings Screen
import 'package:flutter/material.dart';
import 'package:numberpicker/numberpicker.dart';
import 'package:pomodoroapp/screens/home_screen.dart';
class SettingsScreen extends StatefulWidget {
const SettingsScreen({Key key}) : super(key: key);
#override
_SettingsScreen createState() => _SettingsScreen();
}
class _SettingsScreen extends State<SettingsScreen>
with TickerProviderStateMixin {
// Switch states
int _workSessionValue = 25;
int _shortBreakValue = 5;
int _longBreakValue = 15;
NumberPicker integerNumberPicker;
////////////////////// values to pass //////////////////////
int pomodoroTimeToChanged;
int shortBreakTimeToChanged;
int longBreakTimeToChanged;
// Work Session
_handleWorkValueChange(num value) {
if (value != null) {
setState(() {
_workSessionValue = value;
});
}
}
_handleWorkValueChangedExternally(num value) {
if (value != null) {
setState(() {
_workSessionValue = value;
});
integerNumberPicker.animateInt(value);
}
print('Updated pomodoro value: $_workSessionValue ');
pomodoroTimeToChanged = value * 60;
}
// Short break
_handleShortBreakValueChange(num value) {
if (value != null) {
setState(() {
_shortBreakValue = value;
});
}
}
_handleShortBreakValueChangedExternally(num value) {
if (value != null) {
setState(() {
_shortBreakValue = value;
});
integerNumberPicker.animateInt(value);
}
print('Updated short break value: $_shortBreakValue ');
shortBreakTimeToChanged = value * 60;
}
// Long Break
_handleLongBreakValueChange(num value) {
if (value != null) {
setState(() {
_longBreakValue = value;
});
}
}
_handleLongBreakChangedExternally(num value) {
if (value != null) {
setState(() {
_longBreakValue = value;
});
integerNumberPicker.animateInt(value);
}
print('Updated Long break value: $_longBreakValue ');
longBreakTimeToChanged = value * 60;
}
// Animation
AnimationController animationController;
String get timerString {
Duration duration =
animationController.duration * animationController.value;
return '${duration.inMinutes.toString().padLeft(2, '0')}\n${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
}
#override
void initState() {
super.initState();
animationController = AnimationController(
vsync: this, duration: const Duration(seconds: 1500));
}
//number pick values
#override
Widget build(BuildContext context) {
integerNumberPicker = NumberPicker.integer(
initialValue: _workSessionValue,
minValue: 1,
maxValue: 50,
onChanged: _handleWorkValueChange,
);
integerNumberPicker = NumberPicker.integer(
initialValue: _shortBreakValue,
minValue: 1,
maxValue: 50,
onChanged: _handleShortBreakValueChange,
);
integerNumberPicker = NumberPicker.integer(
initialValue: _longBreakValue,
minValue: 1,
maxValue: 50,
onChanged: _handleLongBreakValueChange,
);
//UI
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.chevron_left),
onPressed: () => {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => Home(
pomodoroTimeChanged: pomodoroTimeToChanged,
shortBreakTimeChanged: shortBreakTimeToChanged,
longBreakTimeChanged: longBreakTimeToChanged,
)))
},
),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("Timer",
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
fontSize: 32,
fontWeight: FontWeight.w700)),
const Divider(
thickness: 2,
color: Colors.black26,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
const Text(
"Pomodoro",
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w400),
),
Row(
children: <Widget>[
Container(
width: 30,
height: 30,
child: RawMaterialButton(
shape: const CircleBorder(),
onPressed: _showWorkSessionDialog,
fillColor: Colors.amber,
elevation: 0,
child: Text(
"$_workSessionValue",
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w500),
),
),
),
const Padding(
padding: EdgeInsets.all(5),
child: Text(
"min",
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w500),
),
)
],
)
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
const Text(
"Short Break",
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w400),
),
Row(
children: <Widget>[
Container(
width: 30,
height: 30,
child: RawMaterialButton(
shape: CircleBorder(),
onPressed: _showShortBreakDialog,
fillColor: Colors.amber,
elevation: 0,
child: Text(
"$_shortBreakValue",
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w500),
),
),
),
const Padding(
padding: EdgeInsets.all(5),
child: Text(
"min",
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w500),
),
)
],
)
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
const Text(
"Long Break",
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w400),
),
Row(
children: <Widget>[
Container(
width: 30,
height: 30,
child: RawMaterialButton(
shape: CircleBorder(),
onPressed: _showLongBreakDialog,
fillColor: Colors.amber,
elevation: 0,
child: Text(
"$_longBreakValue",
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w500),
),
),
),
const Padding(
padding: EdgeInsets.all(5),
child: Text(
"min",
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w500),
),
)
],
)
],
),
)
],
)
],
),
),
);
}
//dialog boxes
_showWorkSessionDialog() {
showDialog<int>(
context: context,
builder: (BuildContext context) {
return NumberPickerDialog.integer(
minValue: 0,
maxValue: 50,
initialIntegerValue: _workSessionValue,
title: const Text("Select a minute"),
);
},
).then(_handleWorkValueChangedExternally);
}
_showShortBreakDialog() {
showDialog<int>(
context: context,
builder: (BuildContext context) {
return NumberPickerDialog.integer(
minValue: 0,
maxValue: 50,
initialIntegerValue: _shortBreakValue,
title: const Text("Select a minute"),
);
},
).then(_handleShortBreakValueChangedExternally);
}
_showLongBreakDialog() {
showDialog<int>(
context: context,
builder: (BuildContext context) {
return NumberPickerDialog.integer(
minValue: 0,
maxValue: 50,
initialIntegerValue: _longBreakValue,
title: const Text("Select a minute"),
);
},
).then(_handleLongBreakChangedExternally);
}
}
I'm making a quiz app using Flutter.
I have created a timer of 30 seconds which should start when a new question comes up.
It works fine and it restarts after the next question comes.
But when I click on "Next Question" without choosing an option, it restarts the timer.
I have created that button in such a way that you cannot go to the next question without choosing an option first.
Code:
#override
void initState() {
starttimer();
_questions = getData();
super.initState();
}
int index = 0;
int score = 0;
bool isPressed = false;
bool isAlreadySelected = false;
int timer = 30;
String showtimer = "30";
bool canceltimer = false;
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t) {
setState(() {
if (timer < 1) {
t.cancel();
nextQuestion(index++);
} else if (canceltimer == true) {
t.cancel();
} else {
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void nextQuestion(int questionLength) {
canceltimer = false;
timer = 30;
if (index == 19 || score == 12) {
showDialog(
context: context,
barrierDismissible: false,
builder: (ctx) => ResultBox(
result: score,
questionLength: questionLength,
));
} else {
if (isPressed) {
setState(() {
index++;
isPressed = false;
isAlreadySelected = false;
starttimer();
});
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('Please select any option'),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.symmetric(vertical: 20.0),
));
starttimer();
}
}
}
void checkAnswerAndUpdate(bool value) {
if (isAlreadySelected) {
return;
} else {
if (value == true) {
score++;
setState(() {
isPressed = true;
isAlreadySelected = false;
canceltimer = true;
});
} else if (value == false) {
setState(() {
isPressed = true;
isAlreadySelected = false;
canceltimer = true;
});
}
}
}
void startOver() {
setState(() {
Text('You have already attempted the LL Test');
});
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _questions as Future<List<Question>>,
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Center(
child: Text('${snapshot.error}'),
);
} else if (snapshot.hasData) {
var extractedData = snapshot.data as List<Question>;
return Scaffold(
backgroundColor: background,
appBar: AppBar(
title: const Text('LL Test'),
backgroundColor: background,
shadowColor: Colors.transparent,
actions: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Text(
'Score: $score',
style: TextStyle(fontSize: 18.0),
),
)
],
),
body: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
children: [
// Countdown(
// animation: StepTween(begin: limitTime, end: 0)
// .animate(_controller),
// ),
QuestionWidget(
question: extractedData[index].title,
indexAction: index,
totalQuestions: extractedData.length,
),
const Divider(
color: neutral,
),
const SizedBox(height: 25.0),
for (int i = 0;
i < extractedData[index].options.length;
i++)
GestureDetector(
onTap: () => checkAnswerAndUpdate(
extractedData[index].options.values.toList()[i]),
child: OptionCard(
option: extractedData[index].options.keys.toList()[i],
color: isPressed
? extractedData[index]
.options
.values
.toList()[i] ==
true
? correct
: incorrect
: neutral,
),
),
Expanded(
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer,
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.w700,
fontFamily: 'Times New Roman',
color: neutral,
),
),
),
),
),
],
),
),
floatingActionButton: GestureDetector(
onTap: () => nextQuestion(extractedData.length),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: NextButton(),
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
);
}
} else {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 20.0),
Text(
'Please Wait While Questions Are Loading..',
style: TextStyle(
backgroundColor: Color.fromARGB(255, 4, 82, 6),
color: neutral),
),
],
),
);
}
return const Center(
child: Text('NoData'),
);
},
);
}
}
Is it something wrong in my code? What should I do so that timer doesn't startover?
did you call the starttimer() inside else condition?
try to remove it.
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('Please select any option'),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.symmetric(vertical: 20.0),
));
// starttimer(); this call the function even its not selected yet
}
I am making a tic tac toe game using Dart and needed a little help implementing a button for my game. I am not too sure exactly how to start making a method for the buttons on the tic tac toe screen. How would I start with the first button method? I was going to use void _button0() {} but just not sure how to go about it for the first one since I'm new to Dart.
Also do I need to make 9 seperate methods for each of the buttons for the tic tac toe game?
import 'package:flutter/material.dart';
import 'dart:math';
class HomePage extends StatefulWidget {
#override
HomePageState createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
// Constant Characters for each player
static const String humanPlayer = '1';
static const String computerPlayer = '2';
// Initial Text for Info Label
String text = "X's Turn";
// Constant for Board Size
static const boardSize = 9;
// Game Variables
var gameOver = false;
var win = 0;
var turn = 0;
var _mBoard = ["", "", "", "", "", "", "", "", ""];
var rnd = new Random(boardSize);
// Button Text Variables?
// Tic Tac Toe Game Code
void displayBoard() {
print("");
print(_mBoard[0] + " | " + _mBoard[1] + " | " + _mBoard[2]);
print("-----------");
print(_mBoard[3] + " | " + _mBoard[4] + " | " + _mBoard[5]);
print("-----------");
print(_mBoard[6] + " | " + _mBoard[7] + " | " + _mBoard[8]);
print("");
}
void checkGameOver(int win) {
print("");
if (win == 1) {
gameOver = true;
displayMessage("It's a tie.");
} else if (win == 2) {
gameOver = true;
displayMessage(humanPlayer + " wins!");
} else if (win == 3) {
gameOver = true;
displayMessage(computerPlayer + " wins!");
} else
displayMessage("There is a logic Problem!");
}
void displayMessage(String text) {
text = text;
print(text);
}
int checkWinner() {
// Check horizontal wins
for (int i = 0; i <= 6; i += 3) {
if (_mBoard[i] == (humanPlayer) &&
_mBoard[i + 1] == (humanPlayer) &&
_mBoard[i + 2] == (humanPlayer)) return 2;
if (_mBoard[i] == (computerPlayer) &&
_mBoard[i + 1] == (computerPlayer) &&
_mBoard[i + 2] == (computerPlayer)) return 3;
}
// Check vertical wins
for (int i = 0; i <= 2; i++) {
if (_mBoard[i] == (humanPlayer) &&
_mBoard[i + 3] == (humanPlayer) &&
_mBoard[i + 6] == (humanPlayer)) return 2;
if (_mBoard[i] == (computerPlayer) &&
_mBoard[i + 3] == (computerPlayer) &&
_mBoard[i + 6] == (computerPlayer)) return 3;
}
// Check for diagonal wins
if ((_mBoard[0] == (humanPlayer) &&
_mBoard[4] == (humanPlayer) &&
_mBoard[8] == (humanPlayer)) ||
(_mBoard[2] == (humanPlayer) &&
_mBoard[4] == (humanPlayer) &&
_mBoard[6] == (humanPlayer))) return 2;
if ((_mBoard[0] == (computerPlayer) &&
_mBoard[4] == (computerPlayer) &&
_mBoard[8] == (computerPlayer)) ||
(_mBoard[2] == (computerPlayer) &&
_mBoard[4] == (computerPlayer) &&
_mBoard[6] == (computerPlayer))) return 3;
for (int i = 0; i < boardSize; i++) {
// If we find a number, then no one has won yet
if (!(_mBoard[i] == (humanPlayer)) && !(_mBoard[i] == (computerPlayer)))
return 0;
}
// If we make it through the previous loop, all places are taken, so it's a tie*/
return 1;
}
void getComputerMove() {
int move;
// First see if there's a move O can make to win
for (int i = 0; i < boardSize; i++) {
if (_mBoard[i] != humanPlayer && _mBoard[i] != computerPlayer) {
String curr = _mBoard[i];
_mBoard[i] = computerPlayer;
if (checkWinner() == 3) {
print('Computer is moving to ${i + 1}');
return;
} else
_mBoard[i] = curr;
}
}
// See if there's a move O can make to block X from winning
for (int i = 0; i < boardSize; i++) {
if (_mBoard[i] != humanPlayer && _mBoard[i] != computerPlayer) {
String curr = _mBoard[i]; // Save the current number
_mBoard[i] = humanPlayer;
if (checkWinner() == 2) {
_mBoard[i] = computerPlayer;
print('Computer is moving to ${i + 1}');
return;
} else
_mBoard[i] = curr;
}
}
// Generate random move
do {
move = rnd.nextInt(boardSize);
} while (_mBoard[move] == humanPlayer || _mBoard[move] == computerPlayer);
print('Computer is moving to ${move + 1}');
_mBoard[move] = computerPlayer;
}
void _button0() {
}
//=====è
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Tic Tac Toe'),
leading: IconButton(
icon: Icon(
Icons.border_all,
semanticLabel: 'menu',
),
onPressed: () {},
),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.new_releases),
onPressed: () {},
tooltip: 'New Game',
),
IconButton(
icon: new Icon(Icons.refresh),
onPressed: () {},
tooltip: 'Quit Game',
),
PopupMenuButton(itemBuilder: (BuildContext context) {
return [
PopupMenuItem(
child: new GestureDetector(
onTap: () {},
child: new Text("About",
style: TextStyle(
fontWeight: FontWeight.bold,
)),
),
),
PopupMenuItem(
child: new GestureDetector(
onTap: () {
// Some Method
},
child: new Text(
"Settings",
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
];
})
]),
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///
///
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.start, children: [
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 100,
width: 100,
margin: const EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {
},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80.0,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
),
)),
Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {
},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
)),
Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
)),
]),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 100,
width: 100,
margin: const EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80.0,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
),
)),
Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
)),
Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
)),
]),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 100,
width: 100,
margin: const EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80.0,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
),
)),
Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
)),
Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10.0),
child: RaisedButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {},
child: Text(
"",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
)),
]),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 100,
width: 300,
margin: const EdgeInsets.all(10.0),
child: Text(
"X's Turn",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
),
)
],
),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 40,
width: 200,
margin: const EdgeInsets.all(10.0),
child: RaisedButton(
onPressed: () {},
child: Text(
"Reset App",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
),
))
]),
])));
}
}
You can copy paste run full code below
You can reference https://github.com/sbvkrishna/tictactoe-flutter
Step 1: You can create 9 Box(Button) with GridView.count and pass index to Box(Button) widget
GridView.count(
primary: false,
crossAxisCount: 3,
children: List.generate(9, (index) {
return Box(index);
}),
Step 2: You can put Button logic in onPressed and identify each Button with widget.index
class _BoxState extends State<Box> {
...
#override
Widget build(context) {
return MaterialButton(
padding: EdgeInsets.all(0),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
border: new Border.all(color: Colors.blue)),
child: Center(
child: Text(
_board[widget.index].toUpperCase(),
style: TextStyle(
fontSize: 45,
fontWeight: FontWeight.bold,
),
),
)),
onPressed: () {
if (_board[widget.index] == '') {
if (vsBot == false) {
if (currentMoves % 2 == 0)
_board[widget.index] = 'x';
else
_board[widget.index] = 'o';
} else if (!loading) {
loading = true;
_board[widget.index] = 'o';
if (currentMoves >= 8) {
} else
_bestMove(_board);
//print(_board);
}
//print(vsBot);
pressed();
}
});
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'package:flutter/gestures.dart';
import 'package:url_launcher/url_launcher.dart';
class About extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("About Me"),
),
body: aboutBody);
}
}
Widget get aboutBody {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [const Color(0xFFB3E5FC), const Color(0xFF2196F3)])),
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RichText(
text: TextSpan(children: [
TextSpan(
text: 'A Simple TicTacToe game made using ',
style: TextStyle(color: Colors.black, fontSize: 20),
),
TextSpan(
text: 'Flutter',
style: TextStyle(color: Colors.blue[900], fontSize: 20),
recognizer: TapGestureRecognizer()
..onTap = () {
launch('https://flutter.dev');
})
]),
),
Container(
height: 150,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
'Developed by Krishna S',
style: TextStyle(fontSize: 20),
),
Row(
children: <Widget>[
Icon(Icons.code),
InkWell(
child: Text(
' Github: sbvkrishna',
style: TextStyle(fontSize: 20, color: Colors.blue[900]),
),
onTap: () => {launch('https://github.com/sbvkrishna')},
)
],
),
Row(
children: <Widget>[
Icon(Icons.email),
Text(
' saladibalavijayakrishna#gmail.com',
style: TextStyle(fontSize: 18),
),
],
),
Text(''),
RichText(
text: TextSpan(children: [
TextSpan(
text: 'This Game\'s Source code is available at ',
style: TextStyle(color: Colors.black, fontSize: 20),
),
TextSpan(
text: 'Github',
style: TextStyle(color: Colors.blue[900], fontSize: 20),
recognizer: TapGestureRecognizer()
..onTap = () {
launch(
'https://github.com/sbvkrishna/tictactoe-flutter');
})
]),
),
],
),
)
],
));
}
int currentMoves = 0;
List<String> _board = ['', '', '', '', '', '', '', '', '']; //empty board
String status = '';
String winner = '';
var _gamePageState;
var _turnState;
var _context;
String _turn = 'First Move: X';
bool loading = false;
bool vsBot;
class GamePage extends StatefulWidget {
bool isBot;
GamePage(this.isBot) {
_resetGame();
vsBot = this.isBot;
if (vsBot) _turn = 'First Move: O';
}
#override
_GamePageState createState() => _GamePageState();
}
class _GamePageState extends State<GamePage> {
#override
Widget build(BuildContext context) {
_gamePageState = this;
return Scaffold(
appBar: AppBar(
//leading: Container(width: 0,height: 0,),
title: Text(vsBot ? 'Playing vs Bot' : 'Playing vs Friend'),
actions: <Widget>[
// IconButton(
// icon: Icon(Icons.settings_brightness),
// tooltip: 'Change Theme',
// onPressed: () {
// },
// ),
IconButton(
icon: Icon(Icons.info),
tooltip: 'About',
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return About();
}));
},
),
],
),
body: Container(
decoration: BoxDecoration(color: Colors.blue[200]),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[_BoxContainer(), Status()],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
awaitfn('Reset?', 'Want to reset the current game?', 'Go Back',
'Reset');
});
},
tooltip: 'Restart',
child: Icon(Icons.refresh),
),
);
}
}
class _BoxContainer extends StatelessWidget {
#override
Widget build(BuildContext context) {
_context = context;
return Container(
width: 300,
height: 300,
decoration: BoxDecoration(
color: Colors.white,
border: new Border.all(color: Colors.blue),
boxShadow: [
BoxShadow(
color: Colors.blue[100],
blurRadius: 20.0,
spreadRadius: 5.0,
offset: Offset(7.0, 7.0))
]),
child: Center(
child: GridView.count(
primary: false,
crossAxisCount: 3,
children: List.generate(9, (index) {
return Box(index);
}),
)));
}
}
class Box extends StatefulWidget {
final int index;
Box(this.index);
#override
_BoxState createState() => _BoxState();
}
class _BoxState extends State<Box> {
void pressed() {
print(currentMoves);
setState(() {
currentMoves++;
if (_checkGame()) {
awaitfnn();
} else if (currentMoves >= 9) {
awaitfn('It\'s a Draw', 'Want to try again?', 'Go Back', 'New Game');
}
_turnState.setState(() {
if (currentMoves % 2 == 0)
_turn = 'Turn: O';
else
_turn = 'Turn: X';
_gamePageState.setState(() {});
});
});
}
#override
Widget build(context) {
return MaterialButton(
padding: EdgeInsets.all(0),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
border: new Border.all(color: Colors.blue)),
child: Center(
child: Text(
_board[widget.index].toUpperCase(),
style: TextStyle(
fontSize: 45,
fontWeight: FontWeight.bold,
),
),
)),
onPressed: () {
if (_board[widget.index] == '') {
if (vsBot == false) {
if (currentMoves % 2 == 0)
_board[widget.index] = 'x';
else
_board[widget.index] = 'o';
} else if (!loading) {
loading = true;
_board[widget.index] = 'o';
if (currentMoves >= 8) {
} else
_bestMove(_board);
//print(_board);
}
//print(vsBot);
pressed();
}
});
}
}
class Status extends StatefulWidget {
#override
_StatusState createState() => _StatusState();
}
class _StatusState extends State<Status> {
#override
Widget build(BuildContext context) {
_turnState = this;
return Card(
margin: EdgeInsets.all(40),
child: Container(
width: 220,
height: 60,
padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Text(
_turn,
style: TextStyle(fontSize: 30),
textAlign: TextAlign.center,
),
));
}
}
//-------------------------------------TicTacToe game fns ---------------------------
bool _checkGame() {
for (int i = 0; i < 9; i += 3) {
if (_board[i] != '' &&
_board[i] == _board[i + 1] &&
_board[i + 1] == _board[i + 2]) {
winner = _board[i];
return true;
}
}
for (int i = 0; i < 3; i++) {
if (_board[i] != '' &&
_board[i] == _board[i + 3] &&
_board[i + 3] == _board[i + 6]) {
winner = _board[i];
return true;
}
}
if (_board[0] != '' && (_board[0] == _board[4] && _board[4] == _board[8]) ||
(_board[2] != '' && _board[2] == _board[4] && _board[4] == _board[6])) {
winner = _board[4];
return true;
}
return false;
}
void _resetGame() {
currentMoves = 0;
status = '';
_board = ['', '', '', '', '', '', '', '', ''];
_turn = 'First Move: X';
loading = false;
}
//------------------------------ Alerts Dialog --------------------------------------
void awaitfnn() async {
bool result = await _showAlertBox(
_context, '$winner won!', 'Start a new Game?', 'Exit', 'New Game');
if (result) {
_gamePageState.setState(() {
_resetGame();
});
} else {
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}
}
Future<bool> _showAlertBox(BuildContext context, String title, String content,
String btn1, String btn2) async {
return showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext _context) => AlertDialog(
title: Text(title.toUpperCase()),
content: Text(content),
actions: <Widget>[
RaisedButton(
color: Colors.white,
child: Text(btn1),
onPressed: () {
Navigator.of(context).pop(false);
},
),
RaisedButton(
color: Colors.white,
child: Text(btn2),
onPressed: () {
Navigator.of(context).pop(true);
},
)
],
));
}
awaitfn(String title, String content, String btn1, String btn2) async {
bool result = await _showAlertBox(_context, title, content, btn1, btn2);
if (result) {
_gamePageState.setState(() {
_resetGame();
});
}
}
//------------------------------ MIN-MAX ------------------------------------------
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a < b ? a : b;
}
String player = 'x', opponent = 'o';
bool isMovesLeft(List<String> _board) {
int i;
for (i = 0; i < 9; i++) {
if (_board[i] == '') return true;
}
return false;
}
int _eval(List<String> _board) {
for (int i = 0; i < 9; i += 3) {
if (_board[i] != '' &&
_board[i] == _board[i + 1] &&
_board[i + 1] == _board[i + 2]) {
winner = _board[i];
return (winner == player) ? 10 : -10;
}
}
for (int i = 0; i < 3; i++) {
if (_board[i] != '' &&
_board[i] == _board[i + 3] &&
_board[i + 3] == _board[i + 6]) {
winner = _board[i];
return (winner == player) ? 10 : -10;
}
}
if (_board[0] != '' && (_board[0] == _board[4] && _board[4] == _board[8]) ||
(_board[2] != '' && _board[2] == _board[4] && _board[4] == _board[6])) {
winner = _board[4];
return (winner == player) ? 10 : -10;
}
return 0;
}
int minmax(List<String> _board, int depth, bool isMax) {
int score = _eval(_board);
//print(score);
int best = 0, i;
if (score == 10 || score == -10) return score;
if (!isMovesLeft(_board)) return 0;
if (isMax) {
best = -1000;
for (i = 0; i < 9; i++) {
if (_board[i] == '') {
_board[i] = player;
best = max(best, minmax(_board, depth + 1, !isMax));
_board[i] = '';
}
}
return best;
} else {
best = 1000;
for (i = 0; i < 9; i++) {
if (_board[i] == '') {
_board[i] = opponent;
best = min(best, minmax(_board, depth + 1, !isMax));
_board[i] = '';
}
}
//print(best);
return best;
}
}
int _bestMove(List<String> _board) {
int bestMove = -1000, moveVal;
int i, bi;
for (i = 0; i < 9; i++) {
if (_board[i] == '') {
moveVal = -1000;
_board[i] = player;
moveVal = minmax(_board, 0, false);
_board[i] = '';
if (moveVal > bestMove) {
bestMove = moveVal;
bi = i;
}
}
}
_board[bi] = player;
_gamePageState.setState(() {});
loading = false;
_turnState.setState(() {
_turn = 'Turn: X';
currentMoves++;
});
return bestMove;
}
//---------------------------------------- API ----------------------------------
// Future gameAPI() async {
// var url = 'http://perfecttictactoe.herokuapp.com/api/v2/play';
// Map data = {
// "player_piece": "o",
// "opponent_piece": "x",
// "board": [
// {"id": "top-left", "value": _board[0]},
// {"id": "top-center", "value": _board[1]},
// {"id": "top-right", "value": _board[2]},
// {"id": "middle-left", "value": _board[3]},
// {"id": "middle-center", "value": _board[4]},
// {"id": "middle-right", "value": _board[5]},
// {"id": "bottom-left", "value": _board[6]},
// {"id": "bottom-center", "value": _board[7]},
// {"id": "bottom-right", "value": _board[8]}
// ]
// };
// var res = await http.post(url, body: json.encode(data));
// if (res.statusCode == 200) {
// var resBody = json.decode(res.body);
// if (resBody['status'] == 'success') {
// var newBoard = resBody['data'];
// if (newBoard['status'] == 'win') {
// winner = newBoard['winner'];
// awaitfnn();
// } else if (newBoard['status'] == 'draw') {
// awaitfn('It"s a Draw', 'Want to try again?', 'Go Back', 'New Game');
// }
// int i = 0;
// newBoard['board'].forEach((box) => {_board[i++] = box['value']});
// }
// _gamePageState.setState(() {});
// loading = false;
// _turnState.setState(() {
// _turn = 'Turn: X';
// currentMoves++;
// });
// }
// }
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("TicTacToe"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.info),
tooltip: 'About',
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return About();
}));
},
),
],
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [const Color(0xFFB3E5FC), const Color(0xFF2196F3)])),
padding: EdgeInsets.all(5),
child: Column(
children: <Widget>[
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.close,
size: 140,
color: Colors.lightBlue[800],
),
Icon(
Icons.radio_button_unchecked,
size: 108,
color: Colors.lightBlue[800],
)
],
),
),
Center(
child: Container(
width: 310,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RaisedButton(
padding: EdgeInsets.fromLTRB(10, 5, 10, 6),
child: Container(
width: 130,
child: Center(
child: Text(
'vs Bot',
style: TextStyle(
color: Colors.lightBlue[800], fontSize: 30),
),
)),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return GamePage(true);
}));
},
),
RaisedButton(
padding: EdgeInsets.fromLTRB(10, 5, 10, 6),
child: Container(
width: 130,
child: Center(
child: Text(
'vs Friend',
style: TextStyle(
color: Colors.lightBlue[800], fontSize: 30),
),
)),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return GamePage(false);
}));
},
),
],
),
),
)
],
)),
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TicTacToe',
theme: ThemeData(
primarySwatch: Colors.blue,
brightness: Brightness.light,
//fontFamily: ''
),
home: HomePage(),
);
}
}