AngularJs 和 SignalR 中的 Group Sudoku





5.00/5 (19投票s)
一个 Group Sudoku 游戏,演示了 SignalR 在 AngularJs 应用程序中的用法
引言
有一句名言:“我们每个人都不如我们所有人”(肯尼思·H·布兰查德)。这很简单,意味着如果我们作为一个团队一起解决一个难题,我们可以比团队中的任何一个人都更快地解决它。让我们用数独来试试。是的,这里的数独不是关于与对手竞争,而是关于作为团队成员解决数独。在这里,每个人都用Angular js解决数独谜题,该谜题将通过signalR与其他人的屏幕同步。
在Web应用程序的任何领域,当涉及到服务器的实时更新时,SignalR和WebSockets都已证明是令人惊叹的技术。一些例子包括板球比分更新、股市相关应用、聊天应用或多人在线游戏。本文将演示在分组/团队数独Web应用程序中使用SignalR和AngularJs。从技术上讲,本文可以被视为一个简化的解决方案,演示了如何使用SignalR和AngularJs共同解决问题,即使我们居住在不同的地理位置。为了保持简单,没有使用数据库。所有数据都存储在静态字典/变量中,在您的实际应用程序中,您可能希望将其保存在持久化存储中。
背景
数独是有史以来最受欢迎的益智游戏之一。当我们过去解决数独时,我们会在纸上一起解决,我的同事会提供帮助,我们仍然会记录解决它花费的时间。这个谜题只是对同一个轮子的重新发明,但有多个转向。想法很简单,当你更新一个单元格时,同一个单元格应该为组中的所有成员更新,以便所有人都能更快地共同解决同一个问题。
关于游戏
游戏规则与流行的数独游戏相同。唯一的区别是:在这里你将与你的同事一起玩,而不是对抗他。(所有人都将获得双赢的结果。:P)。如果您不熟悉数独游戏的规则,请访问http://www.sudoku.com/。
以下是谜题的截图
Using the Code
现在,准备好理解构建游戏的代码。这款游戏是在Visual Studio 2015、AngularJs和SignalR中开发的。
Sudoku类
Sudoku
类包含网格、组名和级别。数独网格包含GridRow
的集合,而GridRow
又包含GridCells
的数组。GridCell
存储单元格值以及其他信息,如RowIndex
、ColIndex
、该单元格是否是谜题的一部分(Freezed
属性)等。
SudokuHub和SignalR通信
SudokuHub
类基本上是Signalr中心,负责客户端和服务器之间的通信,以发送消息集。该类中的两个主要函数是GetSudoku
和UpdateCell
。当用户第一次进入数独组时,会调用GetSudoku
方法。之后,每次用户更新单元格时都会调用UpdateCell
,并将相同的单元格广播给组中的所有成员。
public void GetSudoku(string groupName)
{
var group = _Gropus.FirstOrDefault(x => x.Name.Equals(groupName));
Clients.All.getSudoku(db.GetSudoku(groupName));
}
public void UpdateCell(string groupName, GridCell cell)
{
db.UpdateSudoku(groupName, cell);
var sudoku = db.GetSudoku(groupName); // updated sudoku.//
var updatedCell = sudoku.Grid[cell.RowIndex].Cells[cell.ColIndex];
// Trigger the update to all users of that Group.//
Clients.Group(groupName).cellUpdated(updatedCell, sudoku);
}
// Please download the source code to see the full class code.//
AngularJs视图
AngularJs视图只是一个包含9x9单元格的网格。这可以通过对sudoku.Grid
模型使用ng-repeat
来实现。
//
<div class="sudoku">
<div class="sudoku-row" ng-repeat="row in sudoku.Grid">
<input type="number" class="sudoku-cell"
ng-repeat="cell in row.Cells"
min="0" max="9" step="1"
maxlength="1" ng-readonly="cell.Freezed"
ng-class="{'sudoku-cell-readonly': cell.Freezed,
'has-success': cell.IsCorrect}"
ng-change="onCellChange(cell);" ng-model="cell.Data" />
</div>
</div>
//
sudokuService服务
名为sudokuService
的AngularJs服务已用于与SignalR服务器的所有通信。该服务主要包含三个方法:init
、on
和invoke
。顾名思义,init
方法用于初始化SignalR服务器连接,on
方法可用于注册事件处理程序,其中可以在客户端注册自定义SignalR事件。您的SignalR中心中需要有相应的服务器端signalr
方法。invoke
方法可用于从SignalR中心显式调用服务器端SignalR方法。
service.init = function () {
var deferred = $q.defer();
$.connection.hub.start().done(function () {
deferred.resolve();
}).fail(function () {
deferred.reject();
console.log('Could not Connect!');
});
return deferred.promise;
};
service.on = function (event, callback) {
service.sudokuHub.on(event, function (result) {
if (callback) {
callback(result);
}
if (!$rootScope.$$phase) {
$rootScope.$apply();
}
});
};
// Please see attached code for full source code.//
上面的代码片段演示了SignalR服务。service.init
方法返回promise
对象,以便在SignalR连接启动后可以轻松地进行任何调用。这可以以与Angularjs中任何promise相同的方式使用。service.on
方法接受2个参数:event
和callback
。callback
是用户希望在触发事件时调用的JavaScript函数。
sudokuPlayCtrl
sudokuPlayCtrl
是数独游戏视图的Angularjs控制器,负责处理与之相关的所有UI逻辑。它主要触发sudokuService
的三个方法:
init
:获取并初始化当前房间的数独onCellChange
:当用户更新数独网格单元格中的值时调用此方法。在这种情况下,它会在服务器端触发updateCell
方法,将相同的更新广播给房间中的所有成员。cellUpdated
:当其他人更新数独网格单元格时触发此事件。
创建分组
现在,您可以创建自己的分组,并与您的朋友、同事或家人一起玩。为此,只需点击数独主页上的创建分组链接,然后其他成员就可以加入同一分组。每个分组都应该有一套独立的数独游戏,并且可以由分组中的任何用户填充。
待办事项
与任何其他原型或概念一样,这个原型也在不断发展,并且在功能丰富方面还有很长的路要走。以下是我计划在不久的将来根据反馈和我的可用时间实现的:
创建数独
目前,该概念有一个硬编码的单一数独谜题。为了使其更有效,需要根据难度级别动态生成谜题。我很快就会提供相同的内容。
创建房间和邀请好友
当您可以创建私人房间并只能邀请您想一起玩的朋友时,团队数独的乐趣才会真正到来。您可能会在我的下一个更新中很快看到这一点。
自动验证选项
您不一定每次都正确。一旦您的朋友在任何单元格中输入了错误的值,您可能不希望被误导。在这种情况下,在广播更新的单元格时进行验证是有意义的。
着色和状态
还需要显示每个成员填写了多少单元格的状态,并为每个成员分配一个颜色。这样,您就可以轻松地看到每个成员的贡献以及他们以不同颜色填写的项目。
更多更新
当我收到反馈时,我会尝试在这里实现它们,并使其功能更丰富。目前,这只是一个简单的分组数独游戏,您可以集体解决难题。希望您能玩得开心。
关注点
除了与Angularjs进行SignalR通信之外,本文还可以被视为向初学者介绍Angularjs一些基本元素的示例,例如如何调用$q
服务,如何调用Angularjs服务等。
更新:由于此项目已经过时,我正在用.NET 6和Angular 12重写它。请继续关注下一版本。
历史
- 2015年12月8日:初始版本
- 2015年12月18日:增加了创建分组功能+问题修复