2013年11月,Dart语言1.0稳定版SDK发布,普天同庆。从此,网页编程不再纠结了。
在我看来,Dart语法简直就是C#的升级版,太像了。之所以喜欢Ruby的一个重要理由是支持mixin功能,而Dart也引入了mixin特性。
最棒的是Google提供了集成开发环境——Dart Editor和Dartium,有非常强大的编辑和调试功能,既能编写网页程序,也能编写服务器端程序。
把网站上的主要文档看完一遍后,再把SDK下载解压,就能用Dart编程了。
第一个程序写什么呢?做了一个黑白棋游戏。
直接上代码:
<!DOCTYPE html> <html>
<head>
<meta charset="utf-8">
<title>Reversi</title>
<link rel="stylesheet" href="reversi.css">
</head>
<body>
<h1>黑白棋</h1> <p id="score"><span class="black piece"></span> <span id="blackScore">2</span>
<span class="spacer"></span><span class="white piece"></span> <span id="whiteScore">2</span></p> <table id="board">
</table> <p id="message"></p> <script type="application/dart" src="reversi_ui.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
棋盘界面的生成和用户事件处理:
import 'dart:html';
import 'reversi_game.dart'; var chess = new ChessBoard();
var cells = new Map<DivElement,BoardCell>();
var blackScore = querySelector("#blackScore");
var whiteScore = querySelector("#whiteScore");
var message = querySelector("#message"); void main() {
TableElement board = querySelector("#board");
for(int i=;i<ChessBoard.BoardSize;i++){
var row = board.addRow();
for(int j=;j<ChessBoard.BoardSize;j++){
var cell = row.addCell();
var piece = new DivElement();
cell.children.add(piece);
piece.onClick.listen(placePiece);
cells[piece] = chess.cells[i][j];
}
}
updateCells();
} void updateCells(){
cells.forEach((piece, boardCell){
piece.classes.clear();
if(!boardCell.isEmpty){
piece.classes.add(boardCell.piece);
}
});
blackScore.text = chess.blackScore.toString();
whiteScore.text = chess.whiteScore.toString();
message.text = chess.message;
} void placePiece(MouseEvent event) {
var piece = event.target;
var boardCell = cells[piece];
if(chess.placePiece(boardCell)){
updateCells();
piece.classes.add('last');
}else if(boardCell.isEmpty){
message.text = chess.message;
piece.classes.add('last');
}
}
游戏的逻辑部分:
class BoardCell {
int row;
int col;
var piece; BoardCell(this.row, this.col); bool get isEmpty{
return piece == null;
}
} class CellPos {
int row;
int col;
CellPos(this.row, this.col);
} class ChessBoard {
static const BoardSize = ;
static const white = 'white';
static const black = 'black'; var currentTurn = black;
List<List<BoardCell>> cells;
int blackScore = ;
int whiteScore = ; bool gameOver = false;
String tip; ChessBoard(){
cells = new List<List<BoardCell>>();
for(int i=;i<BoardSize;i++){
var row = new List<BoardCell>();
for(int j=;j<BoardSize;j++){
var cell = new BoardCell(i, j);
row.add(cell);
}
cells.add(row);
} cells[][].piece = white;
cells[][].piece = black;
cells[][].piece = black;
cells[][].piece = white; tip = "游戏开始";
} switchTurn(){
currentTurn = getReverse(currentTurn);
} String getReverse(String piece){
if(piece == black){
return white;
}else if(piece == white){
return black;
}else{
return null;
}
} bool placePiece(BoardCell cell){
if(cell.isEmpty){
var success = reverseOpponents(cell, currentTurn);
if(success){
cell.piece = currentTurn;
calculateScore();
switchTurn();
if(canPlacePiece(currentTurn)){
tip = null;
}else{
switchTurn();
if(canPlacePiece(currentTurn)){
tip = "${players[getReverse(currentTurn)]}无棋";
}else{
gameOver = true;
}
}
return true;
}else{
tip = "落子无效";
}
}
return false;
} static List<CellPos> w(int row, int col){
List<CellPos> adjacentCells = [];
for(int j = col - ; j >= ; j--){
adjacentCells.add(new CellPos(row, j));
}
return adjacentCells;
} static List<CellPos> e(int row, int col){
List<CellPos> adjacentCells = [];
for(int j = col + ; j < BoardSize; j++){
adjacentCells.add(new CellPos(row, j));
}
return adjacentCells;
} static List<CellPos> n(int row, int col){
List<CellPos> adjacentCells = [];
for(int i = row - ; i >= ; i--){
adjacentCells.add(new CellPos(i, col));
}
return adjacentCells;
} static List<CellPos> s(int row, int col){
List<CellPos> adjacentCells = [];
for(int i = row + ; i < BoardSize; i++){
adjacentCells.add(new CellPos(i, col));
}
return adjacentCells;
} static List<CellPos> ne(int row, int col){
List<CellPos> adjacentCells = [];
for(int i = row - , j = col + ; i >= && j < BoardSize; i--, j++){
adjacentCells.add(new CellPos(i, j));
}
return adjacentCells;
} static List<CellPos> se(int row, int col){
List<CellPos> adjacentCells = [];
for(int i = row + , j = col + ; i < BoardSize && j < BoardSize; i++, j++){
adjacentCells.add(new CellPos(i, j));
}
return adjacentCells;
} static List<CellPos> sw(int row, int col){
List<CellPos> adjacentCells = [];
for(int i = row + , j = col - ; i < BoardSize && j >= ; i++, j--){
adjacentCells.add(new CellPos(i, j));
}
return adjacentCells;
} static List<CellPos> nw(int row, int col){
List<CellPos> adjacentCells = [];
for(int i = row - , j = col - ; i >= && j >= ; i--, j--){
adjacentCells.add(new CellPos(i, j));
}
return adjacentCells;
} var directions = [n, ne, e, se, s, sw, w, nw]; List<BoardCell> findReverible(BoardCell cell, String piece){
List<BoardCell> allOpponents = [];
for(var direction in directions){
List<BoardCell> opponents = [];
for(var cellPos in direction(cell.row, cell.col)){
var nextCell = cells[cellPos.row][cellPos.col];
if(nextCell.piece == getReverse(piece)){
opponents.add(nextCell);
}else{
if(nextCell.piece == piece){
allOpponents.addAll(opponents);
}
break;
}
}
}
return allOpponents;
} bool reverseOpponents(BoardCell cell, String piece){
List<BoardCell> allOpponents = findReverible(cell, piece);
if(allOpponents.length > ){
allOpponents.forEach((opp){opp.piece=piece;});
return true;
}else{
return false;
}
} bool canPlacePiece(String piece){
for(int i=;i<BoardSize;i++){
for(int j=;j<BoardSize;j++){
var cell = cells[i][j];
if(cell.isEmpty &&
findReverible(cell, piece).length > ){
return true;
}
}
}
return false;
} calculateScore(){
whiteScore = ;
blackScore = ;
for(int i=;i<BoardSize;i++){
for(int j=;j<BoardSize;j++){
var piece = cells[i][j].piece;
if(piece == white){
whiteScore++;
}else if(piece == black){
blackScore++;
}
}
}
} var players = {black:"黑方", white:"白方"}; String get message {
if(gameOver){
if(whiteScore > blackScore){
return "白方胜!";
}else if(whiteScore < blackScore){
return "黑方胜!";
}else{
return "双方平局!";
}
}
if(tip == null){
return "${players[currentTurn]}走棋";
}else{
return "$tip,${players[currentTurn]}走棋";
}
}
}
开发完成后,用dart2js转成javascript,然后拷贝到网站服务器上,就可以在线玩了。
以上只是一个简单的界面和走棋逻辑,接下来要做的是加入人工智能,可以人机对战;使用WebSocket通信,实现联网对战。
这部分的代码就不贴上来了。
点此打开试玩
联网对弈功能需要运行游戏服务器程序,目前只能在局域网使用。
想要完整源代码的朋友可以发邮件给我:251024877@qq.com。不要在评论中留下email,这种的我不会回的。