我是Flutter编码方面的新手,对编码的经验也不是很丰富。我正在开发Tic Tac Toe游戏。它使用一列包含游戏按钮的行,一个显示轮到谁,谁获胜的信息标签以及一个新的游戏按钮。
我的教授为我们提供了示例代码,该示例代码在控制台中显示游戏板,但我真的对如何将游戏从控制台转换为实际用户界面感到困惑。
这是代码:
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(TTTApp());
}
class TTTApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Tic Tac Toe',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Tic Tac Toe'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _mText = "";
// Initial Text for infoLabel
String _text = "X's Turn";
// constant characters for each player
static const String HUMAN_PLAYER = "X";
static const String COMPUTER_PLAYER = "O";
// constant for board size
static const BOARD_SIZE = 9;
// Game variables
var gameOver = false;
var win = 0;
var turn = 0;
var _mBoard = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
var rnd = new Random(BOARD_SIZE);
// Print board to console
void displayBoard() {
print(_mBoard[0] + " | " + _mBoard[1] + " | " + _mBoard[2]);
print("-----------");
print(_mBoard[3] + " | " + _mBoard[4] + " | " + _mBoard[5]);
print("-----------");
print(_mBoard[6] + " | " + _mBoard[7] + " | " + _mBoard[8]);
}
// Check board for winner
int checkWinner() {
// Check horizontal wins
for (int i = 0; i <= 6; i += 3) {
if (_mBoard[i] == (HUMAN_PLAYER) &&
_mBoard[i + 1] == (HUMAN_PLAYER) &&
_mBoard[i + 2] == (HUMAN_PLAYER)) return 2;
if (_mBoard[i] == (COMPUTER_PLAYER) &&
_mBoard[i + 1] == (COMPUTER_PLAYER) &&
_mBoard[i + 2] == (COMPUTER_PLAYER)) return 3;
}
// Check vertical wins
for (int i = 0; i <= 2; i++) {
if (_mBoard[i] == (HUMAN_PLAYER) &&
_mBoard[i + 3] == (HUMAN_PLAYER) &&
_mBoard[i + 6] == (HUMAN_PLAYER)) return 2;
if (_mBoard[i] == (COMPUTER_PLAYER) &&
_mBoard[i + 3] == (COMPUTER_PLAYER) &&
_mBoard[i + 6] == (COMPUTER_PLAYER)) return 3;
}
// Check for diagonal wins
if ((_mBoard[0] == (HUMAN_PLAYER) &&
_mBoard[4] == (HUMAN_PLAYER) &&
_mBoard[8] == (HUMAN_PLAYER)) ||
(_mBoard[2] == (HUMAN_PLAYER) &&
_mBoard[4] == (HUMAN_PLAYER) &&
_mBoard[6] == (HUMAN_PLAYER))) return 2;
if ((_mBoard[0] == (COMPUTER_PLAYER) &&
_mBoard[4] == (COMPUTER_PLAYER) &&
_mBoard[8] == (COMPUTER_PLAYER)) ||
(_mBoard[2] == (COMPUTER_PLAYER) &&
_mBoard[4] == (COMPUTER_PLAYER) &&
_mBoard[6] == (COMPUTER_PLAYER))) return 3;
for (int i = 0; i < BOARD_SIZE; i++) {
// If we find a number, then no one has won yet
if (!(_mBoard[i] == (HUMAN_PLAYER)) && !(_mBoard[i] == (COMPUTER_PLAYER)))
return 0;
}
// If we make it through the previous loop, all places are taken, so it's a tie*/
return 1;
}
void computerTurn() {
var move;
displayMessage(COMPUTER_PLAYER + " MOVED, X's TURN");
// First see if there's a move O can make to win
for (int i = 0; i < BOARD_SIZE; i++) {
if (!(_mBoard[i] == (HUMAN_PLAYER)) &&
!(_mBoard[i] == (COMPUTER_PLAYER))) {
String curr = _mBoard[i];
_mBoard[i] = COMPUTER_PLAYER;
_mText = "O";
if (checkWinner() == 3) {
return;
} else
_mBoard[i] = curr;
}
}
// See if there's a move O can make to block X from winning
for (int i = 0; i < BOARD_SIZE; i++) {
if (!(_mBoard[i] == (HUMAN_PLAYER)) &&
!(_mBoard[i] == (COMPUTER_PLAYER))) {
String curr = _mBoard[i]; // Save the current number
_mBoard[i] = HUMAN_PLAYER;
if (checkWinner() == 2) {
_mBoard[i] = COMPUTER_PLAYER;
return;
} else
_mBoard[i] = curr;
}
}
// Generate random move
var count = 0;
do {
count = count + 1;
move = rnd.nextInt(9);
print("Computer random move is " + '$move');
} while (
(_mBoard[move] == HUMAN_PLAYER || _mBoard[move] == COMPUTER_PLAYER) &&
(count < 9));
if ((_mBoard[move] == HUMAN_PLAYER) || (_mBoard[move] == COMPUTER_PLAYER)) {
return;
} else {
print("Computer is making a random moving to " + '$move');
_mBoard[move] = COMPUTER_PLAYER;
}
}
void displayMessage(String text) {
setState(() {
_text = text;
print(_text);
});
}
void checkGameOver(int win) {
if (win == 1) {
gameOver = true;
displayMessage("It's a tie.");
} else if (win == 2) {
gameOver = true;
displayMessage(HUMAN_PLAYER + " wins!");
} else if (win == 3) {
gameOver = true;
displayMessage(COMPUTER_PLAYER + " wins!");
}
}
void _newGame() {
setState(() {
for (int i = 0; i < BOARD_SIZE; i++) _mBoard[i] = "";
win = 0;
gameOver = false;
turn = 0;
_text = "X's Turn";
});
}
按钮从0变为8,但是我在这里只显示了按钮0。
void _button0() {
setState(() {
if (_mBoard[0] == HUMAN_PLAYER || _mBoard[0] == COMPUTER_PLAYER) {
// _choice = "X";
print("That space is occupied. Please choose another space.");
return;
} else if (win == 0) {
if (turn == 0) {
_mBoard[0] = HUMAN_PLAYER;
_text = HUMAN_PLAYER + " MOVED, O's TURN";
print("onTap called. card #0 was pressed");
turn = 1;
_mText = "X";
win = checkWinner();
checkGameOver(win);
displayBoard();
}
if ((turn == 1) && (win == 0)) {
turn = 0;
// _mText1 = "O";
computerTurn();
win = checkWinner();
checkGameOver(win);
displayBoard();
}
}
});
}
第一行按钮,信息标签和新游戏按钮。
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
leading: new Icon(Icons.grid_on),
title: new Text("Tic Tac Toe"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.new_releases),
onPressed: () {
_newGame();
}),
body: new Container(
padding: EdgeInsets.all(14.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
//Start of the 1st Row
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// Button 0 in 1st Row
RaisedButton(
padding: const EdgeInsets.all(20.0),
onPressed: () {
_button0();
},
child: new Text(" ",
textAlign: TextAlign.center,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 40.0,
fontFamily: 'Roboto',
)),
color: Colors.grey[300],
),
//Button 1 in 1st Row
RaisedButton(
padding: const EdgeInsets.all(20.0),
onPressed: () {
_button1();
},
child: new Text(" ",
textAlign: TextAlign.center,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 40.0,
fontFamily: 'Roboto',
))),
//Button 2 in 1st Row
RaisedButton(
padding: const EdgeInsets.all(20.0),
onPressed: () {
_button2();
},
child: new Text(" ",
textAlign: TextAlign.center,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 40.0,
fontFamily: 'Roboto',
))),
]),
// end 1st Row
Padding(padding: const EdgeInsets.all(7.0)),
Text(
//Info Label
_text,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25.0),
),
Padding(padding: const EdgeInsets.all(35.0)),
Row(
//Start of the New Game button Row
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// New Game button
new RaisedButton(
padding:
const EdgeInsets.fromLTRB(50.0, 40.0, 50.0, 40.0),
color: Colors.grey[400],
onPressed: () {
_newGame();
},
child: new Text("New Game",
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20.0,
fontFamily: 'Roboto',
))),
])
])),
);
}
}
我不确定每次转弯后如何使“ X”和“ O”传递到凸起的按钮。我尝试使用类似于信息标签的字符串来完成此操作,但是我完全迷路了。我在想我需要某种保存按钮的数组吗?抱歉,我没有使用这种语言的经验。