JS制作的炸金花小游戏
03 Jun 2015学习JS的时候突然想起了小时候经常玩的一个游戏,叫做“炸金花”,然后就试着把这个小游戏做了出来,在整个游戏实现的过程中,获益匪浅。“炸金花”的业务流程主要是:构建一副牌->随机发牌->比较牌大小->显示牌及结果。下面是详细的实现过程。
构建一副扑克牌
众所周知,一副扑克牌有4个花色,每个花色13张点数,加上两个joker一共是54张,我们这里没有用到joker,所以是52张。构建扑克牌用到了一个很好玩的算法——洗牌算法。洗牌算法其实很简单,就是定义两个数组,一个数组存储花色,一个数组存储点数,两个数组相结合,就组成一副不含大小王的52张扑克牌。
//构建牌组
var arrcolor=["clubs","hearts","spade","diamonds"]; //花色
var arrnum=["02","03","04","05","06","07","08","09","10","11","12","13","14"]; //点数
for (var i=0; i<4;i++) {
for(var j=0;j<13;j++){
cords[k]=[arrcolor[i],arrnum[j]]; //含有52张牌的二维数组
k++;
}
};
洗牌算法还有其它的一些用法,比如随机起名字。一般玩游戏的时候系统会有一个随机起名的功能,那个功能就是洗牌算法实现的。定义两个数组,一个数组存储姓氏,一个数组存储名字,随机从两个数组中各取出一个值,就组成了一个随机的名字。
随机发牌
随机发牌就是从构建好的52张扑克牌中随机选出六张,分别发给电脑和玩家。这里有个地方需要注意一下就是选出的牌不能是重复的。我记得有道面试题是随机不重复输出1-1000之间的100数。想一想,要怎么写才能实现? 当时我在做这个小游戏时候,第一个想法是将含有52张牌数组打乱,然后随便取出前六个就行了,这个方法如果在PHP中很好实现,因为PHP中含有打乱数组的内置函数,JS中我没有找到类似的函数。所以就用了下面这个方法:
var randcords=new Array();
for(i=0;i<6;i++){
var cordnum=Math.ceil(Math.random()*(51-i));
randcords[i]=cords[cordnum];
cords.splice(cordnum,1);
}
取出一张牌后便将其删掉,从剩下的数组中继续取牌,就可获得六张不重复的随机扑克牌
比较牌大小
如何比较两个人手牌的大小呢?这个应该是这个游戏的关键,三张牌大小一样为暴子,颜色一样是清一色,点数连续是顺子,有两张点数相同为对子,暴子>清一色>顺子>对子,什么都没有则依次比较最大牌的点数。在我一筹莫展之时正好罗老师讲到灯开关的相关知识。然后我就用在了这里,而且成功了。
//计算电脑牌的权值
var pc_num=new Array(cords[0][1],cords[1][1],cords[2][1]);//将电脑牌的数字部分存入数组
var pc_num=pc_num.sort();//将电脑牌的数字部分排序
var pc_val=0;//初始化权值
if (pc_num[0]==pc_num[1]==pc_num[2]) { //判断是否为暴子
pc_val+=3*1e8;
}
if (cords[0][0]==cords[1][0]&&cords[1][0]==cords[2][0]) { //判断是否为清一色
pc_val+=2*1e8;
}
//判断是否为顺子
if (Number(pc_num[1])-Number(pc_num[0])==1&&Number(pc_num[2])-Number(pc_num[1])==1) {
pc_val+=1e8;
}
if (pc_num[0]==pc_num[1]||pc_num[1]==pc_num[2]) { //判断是否为对子
pc_val+=1e7;
var tem="";
tem=pc_num[2];
pc_num[2]=pc_num[1];
pc_num[1]=tem;
}
pc_val+=Number(pc_num.reverse().join("")); //计算电脑牌的最终权值
//计算玩家权值
var play_num=new Array(cords[3][1],cords[4][1],cords[5][1]);//将玩家牌的数字部分存入数组
var play_num=play_num.sort();//将电脑牌的数字部分排序
var play_val=0;//初始化权值
if (play_num[0]==play_num[1]==play_num[2]) { //判断是否为暴子
play_val+=3*1e8;
}
if (cords[3][0]==cords[4][0]&&cords[4][0]==cords[5][0]) { //判断是否为清一色
play_val+=2*1e8;
}
if (Number(play_num[1])-Number(play_num[0])==1&&Number(play_num[2])-Number(play_num[1])==1) { //判断是否为顺子
play_val+=1e8;
}
if (play_num[0]==play_num[1]||play_num[1]==play_num[2]) { //判断是否为对子
play_val+=1e7;
var tem="";
tem=play_num[2];
play_num[2]=play_num[1];
play_num[1]=tem;
}
play_val+=Number(play_num.reverse().join("")); //计算玩家牌的最终权值
//权值比较
if (pc_val>play_val) {
$("#result").text("电脑赢了!");
}else if(pc_val<play_val){
$("#result").text("你赢了!");
}else{$("#result").text("打平了!");}
这段代码比较多,其实道理很简单,就是定义一个八位的数(初始值8个0),如果是暴子,权值最高,将第八位变为1,如果是清一色则将第七位变为1,以此类推,最后比较两个人手牌的权值,权值高的赢。
显示牌及结果
这里就没什么可说的了,就是将取出的六张牌展示,然后显示比较结果OK啦!
//显示电脑的牌
$("#cord1").attr("src","img/"+randcords[0].join("-")+".png");
$("#cord2").attr("src","img/"+randcords[1].join("-")+".png");
$("#cord3").attr("src","img/"+randcords[2].join("-")+".png");
//显示玩家的牌
$("#cord4").attr("src","img/"+randcords[3].join("-")+".png");
$("#cord5").attr("src","img/"+randcords[4].join("-")+".png");
$("#cord6").attr("src","img/"+randcords[5].join("-")+".png");
总结
开始觉得难的东西其实并不难,多想想就会了,难的是开始觉得简单,却越做越觉得难的东西。