flutter: refactor
This commit is contained in:
parent
5a1acb80b6
commit
7a193ab116
|
@ -1,77 +1 @@
|
|||
enum Move { none }
|
||||
|
||||
enum MoveType { place, move, remove }
|
||||
|
||||
enum Color { noColor, black, white, count, draw, nobody }
|
||||
|
||||
enum Phase { none, ready, placing, moving, gameOver }
|
||||
|
||||
enum Action { none, select, place, remove }
|
||||
|
||||
enum GameOverReason {
|
||||
loseReasonNoReason,
|
||||
loseReasonlessThanThree,
|
||||
loseReasonNoWay,
|
||||
loseReasonBoardIsFull,
|
||||
loseReasonResign,
|
||||
loseReasonTimeOver,
|
||||
drawReasonThreefoldRepetition,
|
||||
drawReasonRule50,
|
||||
drawReasonBoardIsFull
|
||||
}
|
||||
|
||||
enum PieceType { none, blackStone, whiteStone, ban, count, stone }
|
||||
|
||||
enum Piece { none, blackStone, whiteStone, ban }
|
||||
|
||||
enum Square {
|
||||
SQ_0,
|
||||
SQ_1,
|
||||
SQ_2,
|
||||
SQ_3,
|
||||
SQ_4,
|
||||
SQ_5,
|
||||
SQ_6,
|
||||
SQ_7,
|
||||
SQ_8,
|
||||
SQ_9,
|
||||
SQ_10,
|
||||
SQ_11,
|
||||
SQ_12,
|
||||
SQ_13,
|
||||
SQ_14,
|
||||
SQ_15,
|
||||
SQ_16,
|
||||
SQ_17,
|
||||
SQ_18,
|
||||
SQ_19,
|
||||
SQ_20,
|
||||
SQ_21,
|
||||
SQ_22,
|
||||
SQ_23,
|
||||
SQ_24,
|
||||
SQ_25,
|
||||
SQ_26,
|
||||
SQ_27,
|
||||
SQ_28,
|
||||
SQ_29,
|
||||
SQ_30,
|
||||
SQ_31,
|
||||
}
|
||||
|
||||
const sqBegin = Square.SQ_8;
|
||||
const sqEnd = 32;
|
||||
const sqNumber = 40;
|
||||
const effectiveSqNumber = 24;
|
||||
|
||||
enum MoveDirection { clockwise, anticlockwise, inward, outward }
|
||||
|
||||
enum LineDirection { horizontal, vertical, slash }
|
||||
|
||||
enum File { A, B, C }
|
||||
|
||||
const fileNumber = 3;
|
||||
|
||||
enum Rank { rank_1, rank_2, rank_3, rank_4, rank_5, rank_6, rank_7, rank_8 }
|
||||
|
||||
const rankNumber = 8;
|
||||
|
|
|
@ -14,7 +14,7 @@ class Battle {
|
|||
}
|
||||
|
||||
init() {
|
||||
_position = Position.defaultPosition();
|
||||
_position = Position.init();
|
||||
_focusIndex = _blurIndex = Move.invalidIndex;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ class Battle {
|
|||
bool regret({steps = 2}) {
|
||||
//
|
||||
// 轮到自己走棋的时候,才能悔棋
|
||||
if (_position.side != Side.white) {
|
||||
if (_position.side != Color.white) {
|
||||
//Audios.playTone('invalid.mp3');
|
||||
return false;
|
||||
}
|
||||
|
@ -88,18 +88,16 @@ class Battle {
|
|||
_blurIndex = _focusIndex = Move.invalidIndex;
|
||||
}
|
||||
|
||||
BattleResult scanBattleResult() {
|
||||
GameResult scanBattleResult() {
|
||||
//
|
||||
final forPerson = (_position.side == Side.white);
|
||||
final forPerson = (_position.side == Color.white);
|
||||
|
||||
if (scanLongCatch()) {
|
||||
// born 'repeat' position by oppo
|
||||
return forPerson ? BattleResult.win : BattleResult.lose;
|
||||
return forPerson ? GameResult.win : GameResult.lose;
|
||||
}
|
||||
|
||||
return (_position.halfMove > 120)
|
||||
? BattleResult.draw
|
||||
: BattleResult.pending;
|
||||
return (_position.halfMove > 120) ? GameResult.draw : GameResult.pending;
|
||||
}
|
||||
|
||||
scanLongCatch() {
|
||||
|
|
|
@ -1,7 +1,79 @@
|
|||
/// 对战结果:未决、赢、输、和
|
||||
enum BattleResult { pending, win, lose, draw }
|
||||
enum MoveType { place, move, remove }
|
||||
|
||||
class Side {
|
||||
enum Phase { none, ready, placing, moving, gameOver }
|
||||
|
||||
enum Action { none, select, place, remove }
|
||||
|
||||
enum GameOverReason {
|
||||
loseReasonNoReason,
|
||||
loseReasonlessThanThree,
|
||||
loseReasonNoWay,
|
||||
loseReasonBoardIsFull,
|
||||
loseReasonResign,
|
||||
loseReasonTimeOver,
|
||||
drawReasonThreefoldRepetition,
|
||||
drawReasonRule50,
|
||||
drawReasonBoardIsFull
|
||||
}
|
||||
|
||||
enum PieceType { none, blackStone, whiteStone, ban, count, stone }
|
||||
|
||||
enum Square {
|
||||
SQ_0,
|
||||
SQ_1,
|
||||
SQ_2,
|
||||
SQ_3,
|
||||
SQ_4,
|
||||
SQ_5,
|
||||
SQ_6,
|
||||
SQ_7,
|
||||
SQ_8,
|
||||
SQ_9,
|
||||
SQ_10,
|
||||
SQ_11,
|
||||
SQ_12,
|
||||
SQ_13,
|
||||
SQ_14,
|
||||
SQ_15,
|
||||
SQ_16,
|
||||
SQ_17,
|
||||
SQ_18,
|
||||
SQ_19,
|
||||
SQ_20,
|
||||
SQ_21,
|
||||
SQ_22,
|
||||
SQ_23,
|
||||
SQ_24,
|
||||
SQ_25,
|
||||
SQ_26,
|
||||
SQ_27,
|
||||
SQ_28,
|
||||
SQ_29,
|
||||
SQ_30,
|
||||
SQ_31,
|
||||
}
|
||||
|
||||
const sqBegin = Square.SQ_8;
|
||||
const sqEnd = 32;
|
||||
const sqNumber = 40;
|
||||
const effectiveSqNumber = 24;
|
||||
|
||||
enum MoveDirection { clockwise, anticlockwise, inward, outward }
|
||||
|
||||
enum LineDirection { horizontal, vertical, slash }
|
||||
|
||||
enum File { A, B, C }
|
||||
|
||||
const fileNumber = 3;
|
||||
|
||||
enum Rank { rank_1, rank_2, rank_3, rank_4, rank_5, rank_6, rank_7, rank_8 }
|
||||
|
||||
const rankNumber = 8;
|
||||
|
||||
/// 对战结果:未决、赢、输、和
|
||||
enum GameResult { pending, win, lose, draw }
|
||||
|
||||
class Color {
|
||||
//
|
||||
static const unknown = '-';
|
||||
static const black = 'b';
|
||||
|
@ -15,15 +87,17 @@ class Side {
|
|||
return unknown;
|
||||
}
|
||||
|
||||
static bool sameSide(String p1, String p2) {
|
||||
static bool isSameColor(String p1, String p2) {
|
||||
return of(p1) == of(p2);
|
||||
}
|
||||
|
||||
static String opponent(String side) {
|
||||
if (side == white) return black;
|
||||
if (side == black) return white;
|
||||
return side;
|
||||
static String opponent(String color) {
|
||||
if (color == white) return black;
|
||||
if (color == black) return white;
|
||||
return color;
|
||||
}
|
||||
|
||||
String operator -(String c) => opponent(c);
|
||||
}
|
||||
|
||||
class Piece {
|
||||
|
@ -34,14 +108,6 @@ class Piece {
|
|||
static const whiteStone = 'w';
|
||||
static const ban = 'x';
|
||||
|
||||
static const Names = {
|
||||
noPiece: '',
|
||||
//
|
||||
blackStone: 'b',
|
||||
whiteStone: 'w',
|
||||
ban: 'x',
|
||||
};
|
||||
|
||||
static bool isBlack(String c) => 'b'.contains(c);
|
||||
|
||||
static bool isWhite(String c) => 'w'.contains(c);
|
||||
|
|
|
@ -28,130 +28,33 @@ Map<int, int> sqToLoc = {
|
|||
31: 0
|
||||
};
|
||||
|
||||
Map<int, int> locToSq;
|
||||
Map<int, int> locToSq = sqToLoc.map((k, v) => MapEntry(v, k));
|
||||
|
||||
class Position {
|
||||
//
|
||||
BattleResult result = BattleResult.pending;
|
||||
|
||||
String _sideToMove;
|
||||
List<String> _board; // 8 * 3
|
||||
GameResult result = GameResult.pending;
|
||||
String _sideToMove = Color.black;
|
||||
List<String> _board = List<String>(49); // 7 * 7
|
||||
MillRecorder _recorder;
|
||||
|
||||
Position.defaultPosition() {
|
||||
initDefaultPosition();
|
||||
}
|
||||
|
||||
void initDefaultPosition() {
|
||||
//
|
||||
locToSq = sqToLoc.map((k, v) => MapEntry(v, k));
|
||||
|
||||
_sideToMove = Side.black;
|
||||
_board = List<String>(64); // 7 * 7
|
||||
for (var i = 0; i < 64; i++) {
|
||||
Position.init() {
|
||||
for (var i = 0; i < _board.length; i++) {
|
||||
_board[i] ??= Piece.noPiece;
|
||||
}
|
||||
|
||||
// Debugging
|
||||
_board[sqToLoc[8]] = Piece.blackStone;
|
||||
//_board[7] = Piece.ban;
|
||||
//_board[8] = Piece.whiteStone;
|
||||
// Example
|
||||
//_board[sqToLoc[8]] = Piece.blackStone;
|
||||
|
||||
_recorder = MillRecorder(lastCapturedPosition: toFen());
|
||||
_recorder = MillRecorder(lastCapturedPosition: fen());
|
||||
}
|
||||
|
||||
Position.clone(Position other) {
|
||||
//
|
||||
_board = List<String>();
|
||||
|
||||
other._board.forEach((piece) => _board.add(piece));
|
||||
|
||||
_sideToMove = other._sideToMove;
|
||||
|
||||
_recorder = other._recorder;
|
||||
}
|
||||
|
||||
void putPiece(var pt, int index) {
|
||||
_board[index] = pt;
|
||||
}
|
||||
|
||||
String move(int from, int to) {
|
||||
//
|
||||
if (!validateMove(from, to)) return null;
|
||||
|
||||
final captured = _board[to];
|
||||
|
||||
final move = Move(from, to, captured: captured);
|
||||
//StepName.translate(this, move);
|
||||
_recorder.stepIn(move, this);
|
||||
|
||||
// 修改棋盘
|
||||
_board[to] = _board[from];
|
||||
_board[from] = Piece.noPiece;
|
||||
|
||||
// 交换走棋方
|
||||
_sideToMove = Side.opponent(_sideToMove);
|
||||
|
||||
return captured;
|
||||
}
|
||||
|
||||
// 验证移动棋子的着法是否合法
|
||||
bool validateMove(int from, int to) {
|
||||
// 移动的棋子的选手,应该是当前方
|
||||
if (Side.of(_board[from]) != _sideToMove) return false;
|
||||
return true;
|
||||
//(StepValidate.validate(this, Move(from, to)));
|
||||
}
|
||||
|
||||
// 在判断行棋合法性等环节,要在克隆的棋盘上进行行棋假设,然后检查效果
|
||||
// 这种情况下不验证、不记录、不翻译
|
||||
void moveTest(Move move, {turnSide = false}) {
|
||||
//
|
||||
// 修改棋盘
|
||||
_board[move.to] = _board[move.from];
|
||||
_board[move.from] = Piece.noPiece;
|
||||
|
||||
// 交换走棋方
|
||||
if (turnSide) _sideToMove = Side.opponent(_sideToMove);
|
||||
}
|
||||
|
||||
bool regret() {
|
||||
//
|
||||
final lastMove = _recorder.removeLast();
|
||||
if (lastMove == null) return false;
|
||||
|
||||
_board[lastMove.from] = _board[lastMove.to];
|
||||
_board[lastMove.to] = lastMove.captured;
|
||||
|
||||
_sideToMove = Side.opponent(_sideToMove);
|
||||
|
||||
final counterMarks = MillRecorder.fromCounterMarks(lastMove.counterMarks);
|
||||
_recorder.halfMove = counterMarks.halfMove;
|
||||
_recorder.fullMove = counterMarks.fullMove;
|
||||
|
||||
if (lastMove.captured != Piece.noPiece) {
|
||||
//
|
||||
// 查找上一个吃子局面(或开局),NativeEngine 需要
|
||||
final tempPosition = Position.clone(this);
|
||||
|
||||
final moves = _recorder.reverseMovesToPrevCapture();
|
||||
moves.forEach((move) {
|
||||
//
|
||||
tempPosition._board[move.from] = tempPosition._board[move.to];
|
||||
tempPosition._board[move.to] = move.captured;
|
||||
|
||||
tempPosition._sideToMove = Side.opponent(tempPosition._sideToMove);
|
||||
});
|
||||
|
||||
_recorder.lastCapturedPosition = tempPosition.toFen();
|
||||
}
|
||||
|
||||
result = BattleResult.pending;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String toFen() {
|
||||
String fen() {
|
||||
// TODO
|
||||
var fen = '';
|
||||
|
||||
|
@ -191,6 +94,86 @@ class Position {
|
|||
return fen;
|
||||
}
|
||||
|
||||
void putPiece(var pt, int index) {
|
||||
_board[index] = pt;
|
||||
}
|
||||
|
||||
String move(int from, int to) {
|
||||
//
|
||||
if (!validateMove(from, to)) return null;
|
||||
|
||||
final captured = _board[to];
|
||||
|
||||
final move = Move(from, to, captured: captured);
|
||||
//StepName.translate(this, move);
|
||||
_recorder.stepIn(move, this);
|
||||
|
||||
// 修改棋盘
|
||||
_board[to] = _board[from];
|
||||
_board[from] = Piece.noPiece;
|
||||
|
||||
// 交换走棋方
|
||||
_sideToMove = Color.opponent(_sideToMove);
|
||||
|
||||
return captured;
|
||||
}
|
||||
|
||||
// 验证移动棋子的着法是否合法
|
||||
bool validateMove(int from, int to) {
|
||||
// 移动的棋子的选手,应该是当前方
|
||||
//if (Color.of(_board[from]) != _sideToMove) return false;
|
||||
return true;
|
||||
//(StepValidate.validate(this, Move(from, to)));
|
||||
}
|
||||
|
||||
// 在判断行棋合法性等环节,要在克隆的棋盘上进行行棋假设,然后检查效果
|
||||
// 这种情况下不验证、不记录、不翻译
|
||||
void moveTest(Move move, {turnSide = false}) {
|
||||
//
|
||||
// 修改棋盘
|
||||
_board[move.to] = _board[move.from];
|
||||
_board[move.from] = Piece.noPiece;
|
||||
|
||||
// 交换走棋方
|
||||
if (turnSide) _sideToMove = Color.opponent(_sideToMove);
|
||||
}
|
||||
|
||||
bool regret() {
|
||||
//
|
||||
final lastMove = _recorder.removeLast();
|
||||
if (lastMove == null) return false;
|
||||
|
||||
_board[lastMove.from] = _board[lastMove.to];
|
||||
_board[lastMove.to] = lastMove.captured;
|
||||
|
||||
_sideToMove = Color.opponent(_sideToMove);
|
||||
|
||||
final counterMarks = MillRecorder.fromCounterMarks(lastMove.counterMarks);
|
||||
_recorder.halfMove = counterMarks.halfMove;
|
||||
_recorder.fullMove = counterMarks.fullMove;
|
||||
|
||||
if (lastMove.captured != Piece.noPiece) {
|
||||
//
|
||||
// 查找上一个吃子局面(或开局),NativeEngine 需要
|
||||
final tempPosition = Position.clone(this);
|
||||
|
||||
final moves = _recorder.reverseMovesToPrevCapture();
|
||||
moves.forEach((move) {
|
||||
//
|
||||
tempPosition._board[move.from] = tempPosition._board[move.to];
|
||||
tempPosition._board[move.to] = move.captured;
|
||||
|
||||
tempPosition._sideToMove = Color.opponent(tempPosition._sideToMove);
|
||||
});
|
||||
|
||||
_recorder.lastCapturedPosition = tempPosition.fen();
|
||||
}
|
||||
|
||||
result = GameResult.pending;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String movesSinceLastCaptured() {
|
||||
//
|
||||
var steps = '', posAfterLastCaptured = 0;
|
||||
|
@ -211,7 +194,7 @@ class Position {
|
|||
|
||||
get side => _sideToMove;
|
||||
|
||||
changeSideToMove() => _sideToMove = Side.opponent(_sideToMove);
|
||||
changeSideToMove() => _sideToMove = Color.opponent(_sideToMove);
|
||||
|
||||
String pieceAt(int index) => _board[index];
|
||||
|
||||
|
|
|
@ -34,14 +34,14 @@ class MillRecorder {
|
|||
|
||||
if (fullMove == 0) {
|
||||
fullMove++;
|
||||
} else if (position.side != Side.black) {
|
||||
} else if (position.side != Color.black) {
|
||||
fullMove++;
|
||||
}
|
||||
|
||||
_history.add(move);
|
||||
|
||||
if (move.captured != Piece.noPiece) {
|
||||
lastCapturedPosition = position.toFen();
|
||||
lastCapturedPosition = position.fen();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,14 +57,14 @@ class _BattlePageState extends State<BattlePage> {
|
|||
position.putPiece(flag % 2 == 0 ? 'b' : 'w', index);
|
||||
|
||||
// 仅 Position 中的 side 指示一方能动棋
|
||||
if (position.side != Side.black) return;
|
||||
if (position.side != Color.black) return;
|
||||
|
||||
final tapedPiece = position.pieceAt(index);
|
||||
print("Tap piece $tapedPiece at <$index>");
|
||||
|
||||
// 之前已经有棋子被选中了
|
||||
if (Battle.shared.focusIndex != Move.invalidIndex &&
|
||||
Side.of(position.pieceAt(Battle.shared.focusIndex)) == Side.black) {
|
||||
Color.of(position.pieceAt(Battle.shared.focusIndex)) == Color.black) {
|
||||
//
|
||||
// 当前点击的棋子和之前已经选择的是同一个位置
|
||||
if (Battle.shared.focusIndex == index) return;
|
||||
|
@ -72,7 +72,7 @@ class _BattlePageState extends State<BattlePage> {
|
|||
// 之前已经选择的棋子和现在点击的棋子是同一边的,说明是选择另外一个棋子
|
||||
final focusPiece = position.pieceAt(Battle.shared.focusIndex);
|
||||
|
||||
if (Side.sameSide(focusPiece, tapedPiece)) {
|
||||
if (Color.isSameColor(focusPiece, tapedPiece)) {
|
||||
//
|
||||
Battle.shared.select(index);
|
||||
//
|
||||
|
@ -81,16 +81,16 @@ class _BattlePageState extends State<BattlePage> {
|
|||
final result = Battle.shared.scanBattleResult();
|
||||
|
||||
switch (result) {
|
||||
case BattleResult.pending:
|
||||
case GameResult.pending:
|
||||
engineToGo();
|
||||
break;
|
||||
case BattleResult.win:
|
||||
case GameResult.win:
|
||||
gotWin();
|
||||
break;
|
||||
case BattleResult.lose:
|
||||
case GameResult.lose:
|
||||
gotLose();
|
||||
break;
|
||||
case BattleResult.draw:
|
||||
case GameResult.draw:
|
||||
gotDraw();
|
||||
break;
|
||||
}
|
||||
|
@ -118,16 +118,16 @@ class _BattlePageState extends State<BattlePage> {
|
|||
final result = Battle.shared.scanBattleResult();
|
||||
|
||||
switch (result) {
|
||||
case BattleResult.pending:
|
||||
case GameResult.pending:
|
||||
changeStatus('请走棋...');
|
||||
break;
|
||||
case BattleResult.win:
|
||||
case GameResult.win:
|
||||
gotWin();
|
||||
break;
|
||||
case BattleResult.lose:
|
||||
case GameResult.lose:
|
||||
gotLose();
|
||||
break;
|
||||
case BattleResult.draw:
|
||||
case GameResult.draw:
|
||||
gotDraw();
|
||||
break;
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ class _BattlePageState extends State<BattlePage> {
|
|||
|
||||
void gotWin() {
|
||||
//
|
||||
Battle.shared.position.result = BattleResult.win;
|
||||
Battle.shared.position.result = GameResult.win;
|
||||
//Audios.playTone('win.mp3');
|
||||
|
||||
showDialog(
|
||||
|
@ -239,7 +239,7 @@ class _BattlePageState extends State<BattlePage> {
|
|||
|
||||
void gotLose() {
|
||||
//
|
||||
Battle.shared.position.result = BattleResult.lose;
|
||||
Battle.shared.position.result = GameResult.lose;
|
||||
//Audios.playTone('lose.mp3');
|
||||
|
||||
showDialog(
|
||||
|
@ -262,7 +262,7 @@ class _BattlePageState extends State<BattlePage> {
|
|||
|
||||
void gotDraw() {
|
||||
//
|
||||
Battle.shared.position.result = BattleResult.draw;
|
||||
Battle.shared.position.result = GameResult.draw;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
|
|
Loading…
Reference in New Issue