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. Primer – 支撑 GitHub 的 CSS 工具包和准则

    Primer 是一个 CSS 工具包,支撑着 GitHub 的前端设计.它的目的仅限于提供通用部件,为我们的开发者提供最大的灵活性,并保持 GitHub 的独特风格.它基于 SCSS 建成,可以通过 ...

  2. 结合 CSS3 & Canvas 模拟人行走的效果

    HTML5 和 CSS3 技术给 Web 带来了新的利器,点燃了 Web 开发人员的激情.所谓只有想不到,没有做不到,的确如此.下面给大家分享一个结合 CSS3 & Canvas 模拟人行走的 ...

  3. MySQL(Navicat)运行.sql文件时报错:[Err] 2006 - MySQL server has gone away 的解决方法

    背景: 今天导入一个数据量很大的.sql文件时,报错: 原因: 可能是sql语句过长,超过mysql通信缓存区最大长度. 解决:1. 编辑 MySQL 安装目录下的 my.ini,在最后添加以下内容: ...

  4. Android的UI设计与后台线程交互

    本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...

  5. git gitignore文件失效处理

    这里讲的是使用 git ignore 时候的一种特殊情况   正常你在本地给项目添加了一些文件之后,一般都会自动全部跟踪,但是在这个时候你必须编辑一个ignore文件,把一些不需要跟踪到文件ignor ...

  6. codeMirror插件使用讲解

    codeMirror是一款十分强大的代码编辑插件,提供了十分丰富的API,最近在项目中用到了这款插件,于是在这里给大家分享下使用方法和心得: codeMirror调用非常方便 首先在页面中载入插件CS ...

  7. 安装windows系统的installutil

    /// 该服务必须在它可以执行之前安装.    /// 服务的安装和卸载“installutil.exe”“installutil.exe / U”的服务可执行文件作为最后一个参数.    ///  ...

  8. js 比较好的博客

    1.0 作者:cloudgamer http://www.cnblogs.com/cloudgamer/archive/2010/04/01/ImageZoom.html

  9. Ext.NET 4.1 系统框架的搭建(后台) 附源码

    Ext.NET 4.1 系统框架的搭建(后台) 附源码 代码运行环境:.net 4.5  VS2013 (代码可直接编译运行) 预览图: 分析图: 上面系统的构建包括三块区域:North.West和C ...

  10. Bootstrap学习笔记系列3-------Bootstrap简单表单显示

    表单布局 垂直或基本表单 基本的表单结构时BootStrap自带的,创建基本表单的步骤如下: 向父<form>元素添加role = "form": 为了获取最佳的间距, ...