最近闲了两天没事做,用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个函数,其他的函数,如初始化,事件注册等,在源码已有注释,写的不好勿喷。

附上源码:http://files.cnblogs.com/files/csbt/DDZ.zip

简陋的斗地主,js实现的更多相关文章

  1. 基于node.js+socket.io+html5实现的斗地主游戏(1)概述

    一.游戏描述 说是斗地主游戏,其实是寝室自创的"捉双A",跟很多地方的捉红10.打红A差不多,大概规则是: 1.基础牌型和斗地主一样,但没有大小王,共52张牌,每人13张,这也是为 ...

  2. 用JS实现一个斗地主发牌器

    //调用随机数,在我上一篇博文讲过这一个函数. function roundNum(min = 0, max = 0) { if (!isNaN(min) && !isNaN(max) ...

  3. JS实现简单斗地主效果

    let play = document.querySelectorAll(".play"); let dizhupai = document.getElementById(&quo ...

  4. Vue.js——60分钟组件快速入门(下篇)

    概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开 ...

  5. Vue.JS 对比其他框架

    Angular 选择 Vue 而不选择 Angular,有下面几个原因,当然不是对每个人都适合: 在 API 与设计两方面上 Vue.js 都比 Angular 简单得多,因此你可以快速地掌握它的全部 ...

  6. Knockout.js随手记(4)

    动态绑定下拉列表 在<select> data-bind的options选项如果绑定到ko.observableArray(),就可以动态新增选项效果,也就是可以利用其完成常见的级联效果的 ...

  7. 使用three.js创建3D机房模型-分享一

    序:前段时间公司一次研讨会上,一市场部同事展现了同行业其他公司的3D机房,我司领导觉得这个可以研究研究,为了节约成本,我们在网上大量检索,最后找到一位前辈的博文[TWaver的技术博客],在那篇博文的 ...

  8. paip.php 与js 的相似性以及为什么它们这么烂还很流行。。

    paip.php 与js 的相似性以及为什么它们这么烂还很流行.. php与js异常的流行,web 90%都被他们统治了.发现了他们有意思的一些共性.. 结构一番总结,得出了它们共有的特点.特性: = ...

  9. 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)

    这几篇都是我原来首发在 segmentfault 上的地址:https://segmentfault.com/a/1190000005040834 突然想起来我这个博客冷落了好多年了,也该更新一下,呵 ...

随机推荐

  1. 用python爬取微博数据并生成词云

    很早之前写过一篇怎么利用微博数据制作词云图片出来,之前的写得不完整,而且只能使用自己的数据,现在重新整理了一下,任何的微博数据都可以制作出来,放在今天应该比较应景. 一年一度的虐汪节,是继续蹲在角落默 ...

  2. 译:Asp.Net Identity与Owin,到底谁是谁?

    送给正在学习Asp.Net Identity的你 :-) 原文出自 trailmax 的博客AspNet Identity and Owin. Who is who. Recently I have ...

  3. 《Spark Python API 官方文档中文版》 之 pyspark.sql (一)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  4. 暑假练习赛 007 A - Time

    A - Time Description standard input/outputStatements A plane can go from city X to city Y in 1 hour ...

  5. Is It A Tree?

    Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  6. String类型

    String字符串的length属性返回的是该字符串里面16位字符的数量,如果字符串包含double-byte的字符,那么返回的数量可能不对   字符串一旦创建就修改不了 var lang = “Ja ...

  7. Python模糊查询本地文件夹去除文件后缀(7行代码)

    Python模糊查询本地文件夹去除文件后缀 import os,re def fuzzy_search(path): word= input('请输入要查询的内容:') for filename in ...

  8. httpwebrequest 用GET方法时报无法发送具有此谓词类型的内容正文

    如下一段小程序,运行结果报无法发送具有此谓词类型的内容正文的错误,其实原因很简单,因为用的是GET的方式进行提交,而GetRequestStream()是用来在post提交的时候写post的内容的流, ...

  9. gcc调试 学习1

    gdb进入调试 b 6 在第6行设置断点 d 2 删除num为2的断点 info b 查看断点 run 运行 n 执行到断点1 s 如果下一条是函数就进入函数 n 继续执行 print i  输出i的 ...

  10. [转载] Linux curl命令详解

    转载自http://www.linuxdiyf.com/linux/2800.html 命令:curl在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的htt ...