簡要說明
上頭又派發(fā)了新任務(wù),這次是完成斗地主,這一次的項目中,我加深了對nodejs工程的理解,學習了狀態(tài)機的使用,順便復(fù)習了下c語言(笑~)
對撲克牌的處理
這里采用的是將全部撲克合并成一張大圖,然后通過截取的辦法將撲克展現(xiàn)出來
.pokes{
background-position: -xpx -ypx;
}
其中x和y都為正數(shù),由于background-position一開始定位在圖片的左上角即0px,0px
,并且截圖的容器窗口位置不動,所以如果需要將窗口定位到對應(yīng)的撲克牌,需要將圖片向左向上移動,即-xpx,-ypx
獲取圖片中的對應(yīng)撲克牌的值和花色
這里采用先規(guī)定index再取value的方法.撲克牌一共有54張,將紅桃A到紅桃K的index設(shè)置為0到12.類似的梅花A到梅花K則是39到51,大小王取52、53.這樣設(shè)置index比較容易通過計算取出對應(yīng)的撲克牌,而比較大小和排序的時候需要獲取value以及花色(有可能),所以為圖方便,將index對應(yīng)的value和花色存儲在json文件里.
用c對文件進行寫入
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
using std::string;
int main(){
FILE *fout;
fout = fopen("D:/json.txt", "w+");
string str = "var data=[\n";
string LEVER = " {lever:";
string VALUE = ",value:";
string END = "},\n";
for (int i = 0; i < 64; i++)
{
int lever = i / 13;
int value = i % 13;
if (lever == 4){
if (value == 0){
value = 16;
str += LEVER + std::to_string(lever) + VALUE + std::to_string(value) + END;
}
else{
value = 15;
str += LEVER + std::to_string(lever) + VALUE + std::to_string(value) + END;
}
continue;
}
else{
if (value <= 1){
value += 13;
}
str += LEVER + std::to_string(lever) + VALUE + std::to_string(value) + END;
}
}
str += "];";
fprintf(fout, "%s", str.c_str());
//fprintf只支持c語言的字符串,所以需要轉(zhuǎn)型
for each (char var in str)
{
printf("%c",var);
}
return 0;
}
以上代碼完成了對A棍鳖、2和大小王的value特殊處理,最后把txt文件改為js就好了.
如何處理服務(wù)器發(fā)送過來的撲克牌
var modalBox = {
cardsSort:function (cards) {
cards.sort(this.comp);
},
comp:function (a,b) {
if(data[a].value>data[b].value){
return false;
}else if(data[a].value==data[b].value){
if(data[a].lever>data[b].lever){
return true;
}else{
return false;
}
}else {
return true;
}
}
}
//將傳進來的cards數(shù)組按照value從大到小排序,如果value一樣則按照花色排序(這個不重要)
桌子上坐滿人后再開始牌局
<div class="bc">
<div class="selectTable">
<div class="table">
</div>
<div class="seats">
<div class="seat">
<div class="place">
</div>
</div>
<div class="seat">
<div class="place">
</div>
</div>
<div class="seat">
<div class="place">
</div>
</div>
</div>
</div>
</div>
<script>
window.scriptData = JSON.stringify({{{scriptData}}});
window.scriptData=eval("("+window.scriptData+")");//轉(zhuǎn)換為json對象
console.log(window.scriptData);
</script>
<script src="/lib/myjs/myjs.js"></script>
<script src="/lib/card/netConnection.js"></script>
這是初始布局,后面的布局更新將用js進行實現(xiàn)而不是一次性預(yù)設(shè)多個布局通過display屬性來控制.
myjs.js文件,綁定place點擊事件
$(init);
var MODAL;
function init() {
new modal();
}
var modal = function () {//modalBox是一個對象,里面創(chuàng)建了很多函數(shù)
var ptrThis;
var modalBox = {
//省略部分代碼
init:function () {
ptrThis = this;
$("body").on("click",".place",function (e) {
socketFun.sit($(this));
})
},
insertImg:function ($this,obj) {
var $img = $("<img>");
$img.attr({
src:obj.imgUrl,
});
$this.attr("data-id",obj.id);
//存儲玩家id,用于以后的交互
$this.empty();
$this.append($img);
},
removeImg:function ($this) {
$this.empty();
},
//省略部分代碼
}
MODAL = modalBox;
return modalBox.init();
netConnection.js文件,專門用于客戶端與服務(wù)器后臺進行收發(fā)操作
var socket = io.connect('http://localhost:3000');
socket.on("connect",function () {
socket.emit("addUser",X._id); //添加用戶
})
socket.on("playerSit",function (obj) {
MODAL.insertImg($(".seat").eq(obj.index).children(),obj);
})
//服務(wù)器返回有玩家坐下
socket.on("leave",function (index) {
MODAL.removeImg($(".seat").eq(index).children());
})
//服務(wù)器返回有玩家離開(某個座位)
//如果一個玩家從一個座位坐到另一個座位,則會得到playerSit和leave兩個消息
var socketFun = {
sit:function ($this) {
/*
$(".seat").each(function () { //這里不能用$this.parent()來追蹤,因為$this.parent()只是找到三個seat中的一個而已,沒卵用
console.log($(this).children().attr("data-id"));
if($(this).children().attr("data-id")==X._id){
MODAL.removeImg($(this).children());
}
})
*/
var obj = {
id:X._id,
index:$this.parent().index()
}
console.log(obj);
socket.emit("sitSeat",obj);
}
}
ioServer.js
var seats = {};
//用于存儲三個座位的信息
var users = {};
//用于存儲用戶對應(yīng)的socket
socket.emit('connect'); //建立連接后由服務(wù)器發(fā)送鏈接成功的消息
socket.on("addUser",function (userId) {
var obj = {};
users[userId]=socket;
async.each(array, function (item,callback) {
if(seats.hasOwnProperty(item)&&seats[item].isSit==1){
User.findOne({_id:seats[item].id},function (err,doc) {
obj[item]={
id:doc._id,
imgUrl:doc.imgUrl,
index:item
}
//console.log(item);
//console.log(obj);
callback();
})
}else{
callback(); //一:這里必須增加回調(diào)函數(shù),否則無法使each的回調(diào)函數(shù)觸發(fā)二:就算findOne里面已經(jīng)發(fā)送過callback函數(shù)也不能再
//下面繼續(xù)發(fā)送callback职车,不然會發(fā)生錯誤,坑鹊杖!
}
},function (err) {
socket.emit("seatsInfo",obj)
//向第一次連接的用戶發(fā)送座位信息,哪個座位有人坐,哪個沒人坐
});
})
socket.on("sitSeat",function (obj) {
dbHelper.findUsrById(obj.id,function (success,doc) {
//dbHelper為對數(shù)據(jù)進行操作的封裝,略去
var msg = {
index:obj.index,
imgUrl:doc.imgUrl,
name:doc.username,
id:obj.id
}
if(!seats.hasOwnProperty(obj.index)||!seats[obj.index].isSit){ //沒人坐
seats[obj.index] = {
isSit:1,
id:obj.id,
imgUrl:doc.imgUrl,
isReady:false
};
socket.broadcast.emit("playerSit",msg);
socket.emit("playerSit",msg);
//只有坐下新位置才能判斷是否移除原來的位置
for(var i = 0;i<3;++i){
//不是index對應(yīng)的座位并且有人坐
if(i!=obj.index){
if(seats.hasOwnProperty(i.toString())&&seats[i].isSit){
if(seats[i].id==obj.id){
socket.broadcast.emit("leave",i);
socket.emit("leave",i);
seats[i].isSit = 0;
}
}
}
}
}
var count = 0;
for(var i = 0;i<3;++i){
if(seats.hasOwnProperty(i.toString())&&seats[i].isSit){
++count;
}
}
//console.log(users);
if(count==3){
for(var i = 0;i<3;++i){
users[seats[i].id].emit("gameStart",seats);
}
}
//console.log(seats);
})
})