简陋的斗地主,js实现
最近闲了两天没事做,用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实现的更多相关文章
- 基于node.js+socket.io+html5实现的斗地主游戏(1)概述
一.游戏描述 说是斗地主游戏,其实是寝室自创的"捉双A",跟很多地方的捉红10.打红A差不多,大概规则是: 1.基础牌型和斗地主一样,但没有大小王,共52张牌,每人13张,这也是为 ...
- 用JS实现一个斗地主发牌器
//调用随机数,在我上一篇博文讲过这一个函数. function roundNum(min = 0, max = 0) { if (!isNaN(min) && !isNaN(max) ...
- JS实现简单斗地主效果
let play = document.querySelectorAll(".play"); let dizhupai = document.getElementById(&quo ...
- Vue.js——60分钟组件快速入门(下篇)
概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开 ...
- Vue.JS 对比其他框架
Angular 选择 Vue 而不选择 Angular,有下面几个原因,当然不是对每个人都适合: 在 API 与设计两方面上 Vue.js 都比 Angular 简单得多,因此你可以快速地掌握它的全部 ...
- Knockout.js随手记(4)
动态绑定下拉列表 在<select> data-bind的options选项如果绑定到ko.observableArray(),就可以动态新增选项效果,也就是可以利用其完成常见的级联效果的 ...
- 使用three.js创建3D机房模型-分享一
序:前段时间公司一次研讨会上,一市场部同事展现了同行业其他公司的3D机房,我司领导觉得这个可以研究研究,为了节约成本,我们在网上大量检索,最后找到一位前辈的博文[TWaver的技术博客],在那篇博文的 ...
- paip.php 与js 的相似性以及为什么它们这么烂还很流行。。
paip.php 与js 的相似性以及为什么它们这么烂还很流行.. php与js异常的流行,web 90%都被他们统治了.发现了他们有意思的一些共性.. 结构一番总结,得出了它们共有的特点.特性: = ...
- 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)
这几篇都是我原来首发在 segmentfault 上的地址:https://segmentfault.com/a/1190000005040834 突然想起来我这个博客冷落了好多年了,也该更新一下,呵 ...
随机推荐
- AngularJS学习篇(一)
AngularJS 使用 表达式 把数据绑定到 HTML. AngularJS 表达式 AngularJS 表达式写在双大括号内:{{ expression }}. AngularJS 表达式把数据绑 ...
- H5缓存
h5 namifest(已经被废弃):http://www.tuicool.com/articles/VvABB3Y service worker缓存:https://developer.mozill ...
- js数组遍历some,foreach,map,filter,every对比
1. [...].some(ck)函数 ---- 某个一个为true,则为true 对数组中每个元素执行一次ck函数,知道某个元素返回true,则直接返回true.如果都返回f ...
- jQuery选择器(内容过滤选择器)第四节
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- Nginx服务及编译安装
第1章 Nginx 1.1 nginx的概念 Nginx("engine x")是一个开源的.支持高性能.高并发的WWW服务和代理服务软件,具有高开发(特别是静态资源),占用系统资 ...
- 利用C#转换图片格式及转换为ico
注意:转换为ICO后效果不好. 源代码: using System;using System.Collections.Generic;using System.Text;using System.Dr ...
- [转载] HDFS简介
转载自http://www.csdn.net/article/2010-11-26/282582 http://subject.csdn.net/hadoop/ 一.HDFS的基本概念 1.1.数据块 ...
- 《Linux命令行与shell脚本编程大全》第十章 使用编辑器
主要介绍vim, nano, emacs,KWrite,Kate,GNOME 10.1 vim Unix系统最初的编辑器 10.1.1检查vim软件包 先搞明白你所用的Linux系统是哪种vim软件包 ...
- 单例模式/ThreadLocal/线程内共享数据
import java.util.Random; public class ThreadDemo3 { public static void main(String[] args) { for(int ...
- 一篇不错的Gibbs Sampling解释文章,通俗易懂
http://cos.name/2013/01/lda-math-mcmc-and-gibbs-sampling/ 直接原文的链接了.原文写的不错,是中文博客中说的比较明白的了. 但为了保留文章,随 ...