用Dart写的黑白棋游戏
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,这种的我不会回的。
用Dart写的黑白棋游戏的更多相关文章
- 黑白棋游戏 (codevs 2743)题解
[问题描述] 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的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 ...
- BZOJ2319 : 黑白棋游戏
将01串按1分段,那么分析可得长度为$a$的段拼上长度为$b$的段的SG值为$a-[a\leq b]$. 设$f[i][j][k][l]$表示从后往前用了$i$个1,$j$个0,当前段长度为$k$,后 ...
- 洛谷 题解 P1225 【黑白棋游戏】
看见很多dalao写了什么双向BFS,蒟蒻表示不会写啊. 怎么办办? 先来分析一下题目,一眼看去就是一个搜索题,考虑DFS与BFS. 先放一份DFS的代码: #include<bits/stdc ...
- 洛谷 - P1225 - 黑白棋游戏 - bfs
神奇bug,没有记录pre就show了,找了1个小时. #include <bits/stdc++.h> using namespace std; #define ll long long ...
- BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)
题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...
- 原生JS实战:写了个斗牛游戏,分享给大家一起玩!
本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5869953.html 该程序是本人的个人作品,写的不好,未经本人允许,请 ...
- bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)
黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...
- C#黑白棋制作~
前些天自己复习一下C#语言 做了个黑白棋,望大家看一下,可能有些bug嘿嘿 链接如下 http://files.cnblogs.com/files/flyingjun/%E9%BB%91%E7%99% ...
随机推荐
- adb shell 查看系统属性(用来判断特殊的操作系统)
一般来讲,在android程序开发中进行需要判断设备类型和系统版本 1.设备类型判断(android.os.Build.MODEL) 比如判断属于Google Nexus 5,Nexus 7,MIUI ...
- Windows Azure Web Site (8) 设置Web Site时区
<Windows Azure Platform 系列文章目录> 许多已经使用Azure Web Site的用户已经发现了,Azure Web Site默认的系统时间是UTC时区. 比如我们 ...
- Coreseek + Sphinx + Mysql + PHP构建中文检索引擎
首先明确几个概念 Sphinx是开源的搜索引擎,它支持英文的全文检索.所以如果单独搭建Sphinx,你就已经可以使用全文索引了.但是往往我们要求的是中文索引,怎么做呢?国人提供了一个可供企业使用的,基 ...
- qml基础学习 Canvas画笔
一.画布元素 自qt4.7发布qml以来,qml也在一直不断的完善中,在qt4时代使用qml时如果需要异形图,那我们只能让设计师来切图,这样的感觉是很不爽的,总感觉开发没有那么犀利.但是到了qt5这一 ...
- Html页面head标签元素的意义和应用场景
相信在html5之前,很少人会关注html页面上head里标签元素的定义和应用场景,可能记得住的只有"title"."keyword"和"descri ...
- CentOS matplotlib 安装
sudo yum install freetype-devel sudo yum install libpng-devel sudo pip install matplotlib
- 30天C#基础巩固----查找XML文件元素
一:XML文档 了解xml文档. 利用代码来创建XML文档. //引用命名空间+using System.Xml; XmlDocument xdoc=new XmlDocument(); XmlDec ...
- Auto Mapper01
在项目中一直在使用Auto Mapper技术,但是只是会简单的使用,对其里面的一些具体的细节和知识点不是很清楚,现在就跟着我从最基础的知识点来重新认识下,AutoMapper技术吧. ...
- 初探Spring - IOC原理
一.IOC是什么 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来降低代码之间的耦合度.其中最常见的方式叫做依赖注入(Dependency ...
- ASP.NET MVC使用SSI来实现页面静态化
页面静态化分为两种:伪静态和真静态,这里主要介绍的是真静态. 进入正题之前先简单介绍一下SSI和shtml: 1).SSI是Server Side Include的简称(服务器端嵌入) 2).shtm ...