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. js组件在线编辑器插件、图表库插件、文件树插件

    在线编辑器插件: 一.kindeditor 二.UEditor 图表库插件: 一.echart 二.highchart 文件树插件: 一.zTree -- jQuery 树插件 http://www. ...

  2. java并发编程实战学习(3)--基础构建模块

    转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...

  3. 在Springmvc中获取properties属性

    一些关键的属性一般都会拿出来作为配置,比如数据库连接等.在springmvc中也提供了获取property的类,比如@Value来获取.我接触spring很浅,基本上都是百度的问题解决方法,百度到@v ...

  4. Elasticsearch增删改查 之 —— Get查询

    GET API是Elasticsearch中常用的操作,一般用于验证文档是否存在:或者执行CURD中的文档查询.与检索不同的是,GET查询是实时查询,可以实时查询到索引结果.而检索则是需要经过处理,一 ...

  5. 百度地图与HT for Web结合的GIS网络拓扑应用

    在<HT for Web整合OpenLayers实现GIS地图应用>篇中介绍了HT for Web与OpenLayers的整合,不少朋友反应国内用得比较多的还是百度地图,虽然HT整合百度地 ...

  6. 3.openstack之mitaka搭建keystone认证服务

    认证服务keystone部署 一:安装和配置服务 1.建库建用户 mysql -u root -p CREATE DATABASE keystone; GRANT ALL PRIVILEGES ON ...

  7. 【转载】各浏览器CSS兼容问题

    CSS对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理方法并 整理了一下.对于web2.0的过度,请尽量用xhtml ...

  8. ASP.NET伪静态的方法及相关资料

    1. 添加URLRewriter.dll引用 2. 配置web.config的基本信息 <configSections> <section name="RewriterCo ...

  9. ASP.NET MVC SSO单点登录设计与实现(转载)

    实验环境配置 HOST文件配置如下: 127.0.0.1 app.com127.0.0.1 sso.com IIS配置如下: 应用程序池采用.Net Framework 4.0 注意IIS绑定的域名, ...

  10. bitbucket+sourcetree+p4merge for windows 版本控制

    这里选择bitbucket作为仓库的原因是,它能够在设置私有仓库的前提下组建5人团队 一:https://bitbucket.org/ 注册bitbucket 二:http://www.sourcet ...