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>&nbsp;<span id="blackScore">2</span>
<span class="spacer"></span><span class="white piece"></span>&nbsp;<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,这种的我不会回的。

用Dart写的黑白棋游戏的更多相关文章

  1. 黑白棋游戏 (codevs 2743)题解

    [问题描述] 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的2个方格称为相邻方 ...

  2. [CareerCup] 8.8 Othello Game 黑白棋游戏

    8.8 Othello is played as follows: Each Othello piece is white on one side and black on the other. Wh ...

  3. BZOJ2319 : 黑白棋游戏

    将01串按1分段,那么分析可得长度为$a$的段拼上长度为$b$的段的SG值为$a-[a\leq b]$. 设$f[i][j][k][l]$表示从后往前用了$i$个1,$j$个0,当前段长度为$k$,后 ...

  4. 洛谷 题解 P1225 【黑白棋游戏】

    看见很多dalao写了什么双向BFS,蒟蒻表示不会写啊. 怎么办办? 先来分析一下题目,一眼看去就是一个搜索题,考虑DFS与BFS. 先放一份DFS的代码: #include<bits/stdc ...

  5. 洛谷 - P1225 - 黑白棋游戏 - bfs

    神奇bug,没有记录pre就show了,找了1个小时. #include <bits/stdc++.h> using namespace std; #define ll long long ...

  6. BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)

    题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...

  7. 原生JS实战:写了个斗牛游戏,分享给大家一起玩!

    本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5869953.html 该程序是本人的个人作品,写的不好,未经本人允许,请 ...

  8. bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)

    黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...

  9. C#黑白棋制作~

    前些天自己复习一下C#语言 做了个黑白棋,望大家看一下,可能有些bug嘿嘿 链接如下 http://files.cnblogs.com/files/flyingjun/%E9%BB%91%E7%99% ...

随机推荐

  1. Testing - 测试基础 - 自动

    自动化测试模型 一个自动化测试框架就是一个集成体系,在这一体系中包含测试功能的函数库.测试数据源.测试对象识别标准,以及种可重用的模块. 自动化测试框架在发展的过程中,不断有新的模型(概念)被提出,目 ...

  2. AngularJS in Action读书笔记4(实战篇)——创建Statistic模块

    个人感觉<Angularjs in action>这本书写的很好,很流畅,循序渐进,深入浅出,关键是结合了一个托管于Github上的实例讲解的,有代码可查,对于初学者应该是个不错的途径.( ...

  3. 如何安装RHEL7.2x64 即红帽7.2虚拟机?

                                                   虚拟机RHEL7.2x64的安装步骤   第一步:创建虚拟机 第二步:典型安装下一步: 第三步:创建空的硬 ...

  4. Android中的FragmentManager的问题

    Fragment是构成灵活UI的重要部分.最近学习到Fragment的使用时候,碰到一个问题.主程序程序布局非常简单: <?xml version="1.0" encodin ...

  5. 前端工程化开发之yeoman、bower、grunt

    上两遍文章介绍了前端模块化开发(以seaJs为例)和前端自动化开发(以grunt为例)的流程,参见: http://www.cnblogs.com/luozhihao/p/4818782.html ( ...

  6. C#序列化s实体类成Xml,去除空格、换行符以及命名空间

    序列化实体类成为一个干净的Xml,不带空格.换行符以及命名空间 /// <summary> /// 序列化成XML /// </summary> /// <typepar ...

  7. js带上框架和防止被iframe的代码

    1.永远都会带着框架<script language="JavaScript"><!--if (window == top)top.location.href = ...

  8. 【C#】妈妈再也不用担心自定义控件如何给特殊类型的属性添加默认值了,附自定义GroupBox一枚

    ------------------更新:201411190903------------------ 经过思考和实践,发现套路中的第1条是不必要的,就是完全可以不用定义一个名为Default+属性名 ...

  9. qt 自动产生 Guid 方法

    strcpy(cmd->uid,QUuid::createUuid().toString().toStdString().c_str());

  10. 15天玩转redis —— 第四篇 哈希对象类型

    redis中的hash也是我们使用中的高频数据结构,它的构造基本上和编程语言中的HashTable,Dictionary大同小异,如果大家往后有什么逻辑需要用 Dictionary存放的话,可以根据场 ...