最近闲了两天没事做,用js写了个斗地主,练习练习。代码和功能都很简陋,还有bug,咋只是聊聊自己的思路。
这里说说斗地主主要包含的功能:洗牌,发牌,玩家出牌、电脑出牌,出牌规则的验证,输赢啥的没有判断,只是实现了这几个主要功能,下面依次说说几个功能的实现:
1.洗牌:
var pukes=this.manage.pukes;//存放扑克牌的数组
//洗牌
for(var i=0;i<pukes.length;i++){
var tmp=pukes[i];
var index=util.random(i,pukes.length);//随机交换两张牌
pukes[i]=pukes[index];
pukes[index]=tmp;
}
2.发牌(简版默认是玩家自己为地主,电脑为农民),由于前面洗牌时已经将牌的顺序打乱,所以发牌只是简单的循环把pukes中的元素添加到每个玩家实例中的pukes字段中。
//发牌
var start=0;
for(var i=0;i<this.manage.pukes.length-3;i++) {
if(start==this.manage.players.length){
start=0;
}
this.manage.pukes[i].status=true;
this.manage.players[start].pukesLen++;
this.manage.players[start++].pukes.push(this.manage.pukes[i]);
}
for(var i=this.manage.pukes.length-3;i<this.manage.pukes.length;i++){
//地主多三张
this.manage.pukes[i].status=true;
this.manage.players[this.manage.curPlayerIndex].pukesLen++;
this.manage.players[this.manage.curPlayerIndex].pukes.push(this.manage.pukes[i]);
}
3.玩家出牌,玩家出牌分为电脑和玩家自己两个步骤,电脑出牌是非常傻瓜的出牌方式(有牌就出):
//出牌
if(this.options.playerIndex==this.manage.curPlayerIndex) {
var spks = [],gz=false; if (this.manage.curMaxPlayerIndex == this.options.playerIndex) {
this.manage.deskPukes = [];
}
if (this.isCompute) {
//电脑自动出牌
var start = 0;
var len=this.manage.deskPukes.length||1;
while (start < this.pukes.length) {
spks = [];
for (var i = 0,j=start; i <len&&j<this.pukes.length; i++) {
//随便选一张 可以出就行
if(this.pukes[j].status) {
spks.push(this.pukes[j++]);
}
}
if(spks.length) {
if (rules.valids(spks, this.manage.deskPukes)) {
gz = true;
break;
}
}
start++;
}
}
else {
//玩家选择出牌
for (var i = 0; i < this.pukes.length; i++) {
if (this.pukes[i].selected && this.pukes[i].status) {
spks.push(this.pukes[i]);
}
}
if (rules.valids(spks, this.manage.deskPukes)) {
gz=true;
}
else{
alert("出牌不符合规则!");
}
}
if(gz){
this.manage.curMaxPlayerIndex=this.options.playerIndex;
this.manage.deskPukes = [];
for (var i = 0; i < spks.length; i++) {
this.pukesLen--;
this.manage.deskPukes.push(spks[i]);
spks[i].status = false;
}
}
this.manage.renderPukes();
this.manage.renderCurDiscard();
if(this.isCompute||gz) {
this.manage.nextPlayer();
}
}
else{
alert("没轮到你出牌!");
}
4.出牌规则的验证,是很多函数组合起来,然后循环调用,如果遇到返回ture的即为出牌符合规则:
//以下为出牌规则
var rules={
_rules:[
new danzRule(),
new duiRule(),
new sandRule(),
new zandRule(),
new shunzRule(),
new liandRule()
],
valids:function(_pukes,_curPukes){
for(var i=0;i<this._rules.length;i++){
if(this._rules[i].valid(_pukes,_curPukes)){
return true;
}
}
return false;
}
}; function danzRule(){
//单张规则
}
danzRule.prototype.valid=function(_pukes,_curPukes){
//校验
var pukes=_pukes;//玩家的牌
var curPukes=_curPukes;//左面的牌
if(pukes&&pukes.length==1){
//比较牌面值
if(!curPukes||!curPukes.length){
return true;
}
if(curPukes[0].dians==2&&pukes[0].dians<15){
//2特殊处理
return false;
}
if(pukes[0].dians==2&&curPukes[0].dians<15){
//2特殊处理
return true;
}
return pukes[0].dians>curPukes[0].dians;
}
return false;
} function duiRule(_pukes,_curPukes){
//两张规则 }
duiRule.prototype.valid=function(_pukes,_curPukes){
//校验
var pukes=_pukes;//玩家的牌
var curPukes=_curPukes;//左面的牌
if(pukes&&pukes.length==2){
//比较牌面值
if(pukes[0].dians>14&&pukes[1].dians>14){
return true;
}
if(pukes[0].dians!=pukes[1].dians){
return false;
}
if(!curPukes||!curPukes.length){
return true;
}else {
if(curPukes.length!=2){
return false;
}
if (curPukes[0].dians > 14 && curPukes[1].dians > 14) {
return false;
}
if (curPukes[0].dians != curPukes[1].dians) {
return false;
}
if (curPukes[0].dians == 2) {
return false;
}
}
if(pukes[0].dians==2){
return true;
}
return pukes[0].dians>curPukes[0].dians;
}
return false;
} function sandRule(){
//三带
}
sandRule.prototype.valid=function(_pukes,_curPukes){
//校验 var pukes=_pukes;//玩家的牌
var curPukes=_curPukes;//左面的牌
if(pukes&&(pukes.length>=3)){
//比较牌面值
var books=getBooks(pukes);
if(!valid(books))return false;
if(!curPukes||!curPukes.length)return true;
if(curPukes.length!=books.length)return false;
var books2=getBooks(curPukes);
if(!valid(books2))return false;
return getSum(books)>getSum(books2);
}
return false; function getSum(books){
var sum=0;
for(var i=0;i<books.length;i++) {
if(books[i]==3){
if(i==2)return 9999;
sum+=i;
}
}
return sum;
}
function valid(books){
//验证三带是否有效
var counts3= 0,countsd= 0,d2=true,start=false,startIndex=-1; for(var i=0;i<books.length;i++) {
if(start&&books[i]==3&&startIndex!=(i-1)){
return false;
}else{
startIndex=i;
}
if(books[i]==3){
if(!start) {
start = true;
startIndex = i;
}
counts3++;
}
if(books[i]==1){
d2=false;
}
} for(var i=0;i<books.length;i++) {
if(d2&&books[i]==2){
countsd++;
}
else if(!d2&&books[i]==1){
countsd++;
}
}
return counts3>0&&counts3==countsd;
} function getBooks(pukes){
//返回三带的每个点数的个数
var books=[];
for(var i=0;i<pukes.length;i++){
if(!books[pukes[i].dians]){
books[pukes[i].dians]=1;
}else{
books[pukes[i].dians]++;
}
}
return books;
}
} function zandRule(){
//炸弹
}
zandRule.prototype.valid=function(_pukes,_curPukes){
var pukes=_pukes;//玩家的牌
var curPukes=_curPukes;//左面的牌
if(pukes&&pukes.length==4) {
if(!allEqual(pukes)){
return false;
}
if(!curPukes||(curPukes.length>0&&curPukes.length!=4)||!allEqual(curPukes)){
return true;
}
else{
if(pukes[0].dians==2){
return true;
}
if(curPukes[0].dians==2){
return false;
}
return pukes[0].dians>curPukes[0].dians;
} }
return false; function allEqual(pukes){
if(!pukes||!pukes.length)return false;
var base=pukes[0].dians;
for(var i=1;i<pukes.length;i++){
if(base!=pukes[i].dians){
return false;
}
}
return true;
} } function liandRule(){
//连对
}
liandRule.prototype.valid=function(_pukes,_curPukes) {
var pukes=_pukes;//玩家的牌
var curPukes=_curPukes;//左面的牌
if(pukes&&pukes.length>=6) {
if(!verificationCoherence(pukes)){
return false;
}
if(!curPukes||curPukes.length<=0){
return true;
}
if(!verificationCoherence(curPukes)){
return false;
}
if(pukes.length!=curPukes.length){
return false;
}
return getSumDians(pukes)>getSumDians(curPukes);
}
return false;
function getSumDians(pukes){
var sum=0;
for(var i=0;i<pukes.length;i++) {
sum+=pukes[i].dians;
}
return sum;
} function verificationCoherence(pukes){
//验证连贯性
if(!pukes||!pukes.length)return false;
var books=[];
for(var i=0;i<pukes.length;i++){
if(pukes[i].dians==2||pukes[i].dians>14){
return false;
}
if(!books[pukes[i].dians]){
books[pukes[i].dians]=1;
}else{
books[pukes[i].dians]++;
}
if(books[pukes[i].dians]>2){
return false;
}
}
var start=false; for(var i=0;i<books.length;i++) {
if(books[i]&&books[i]!=2){
return false;
}
if(books[i]==2&&!start){
start=true;
}
if(start&&books[i]!=2){
return false;
}
} return true;
}
}
function shunzRule(){
//顺子
}
shunzRule.prototype.valid=function(_pukes,_curPukes){
var pukes=_pukes;//玩家的牌
var curPukes=_curPukes;//左面的牌
if(pukes&&pukes.length>=5) {
if(!verificationCoherence(pukes)){
return false;
}
if(!curPukes||curPukes.length<=0){
return true;
}
if(!verificationCoherence(curPukes)){
return false;
}
if(pukes.length!=curPukes.length){
return false;
}
return getSumDians(pukes)>getSumDians(curPukes);
}
return false; function getSumDians(pukes){
var sum=0;
for(var i=0;i<pukes.length;i++) {
sum+=pukes[i].dians;
}
return sum;
} function verificationCoherence(pukes){
//验证连贯性
if(!pukes||!pukes.length)return false;
var books=[];
for(var i=0;i<pukes.length;i++){
if(pukes[i].dians==2||pukes[i].dians>14){
return false;
}
if(!books[pukes[i].dians]){
books[pukes[i].dians]=1;
}else{
return false;
}
}
var start=false;
for(var i=0;i<books.length;i++) {
if(books[i]==1&&!start){
start=true;
}
if(start&&!books[i]){
return false;
}
}
return true;
} }
以上4步,是我认为的主要的4个函数,其他的函数,如初始化,事件注册等,在源码已有注释,写的不好勿喷。