文档章节

【Nodejs】“快算24”扑克牌游戏算法 1.02

o
 osc_mervd488
发布于 2018/04/23 21:26
字数 2300
阅读 15
收藏 0

精选30+云产品,助力企业轻松上云!>>>

快算24是一种挺好的锻炼孩子算数能力的扑克牌游戏,它的游戏方式是把四张牌的牌面数值通过有限四则运算得到结果24,四张牌必须仅用一次。各地玩法还有点差别,有的只算1-10,其它抽出来;有的地方把整幅牌都算上,把其中J当作11,Q当作12,K当作13,小王当作15,大王当作18. 个人觉得后者不但省了理牌的功夫还更能锻炼人。

绝大多数四张牌的组合都容易算出来,有部分就要费点脑筋了,如5,5,5,1;3,7,3,7;12,12,12,10...,当然也有完全算不出来的,如5,7,8,11;1,1,6,11...从规律上讲,似乎5,7,11,13这样的素数参与越多越是难算。

算24也是有窍门的,那就是逐步缩小范围,具体来说是看三个数运算能否和第四个数通过加减乘除得到24,继而看三个数操作能否得到24和第四个数的四则运算结果,继而看两个数的操作能否得到第三个数和上次结果的四则运算结果。具体比如有2,3,4,12四个数,看到12后想2,3,4是否能组合个2出来,然后想到2*3-4的方案,或者2*(4-3)的方案。

按照这个思维我编了下面的程序。具体思路是这样的,先制作一个C4类(2,3,4,12,24),这个类会形成24种组合(以及六种特殊组合方式),再由24种组合生成6种子方案,子方案又生成六种孙方案,最后挑选出符合条件的结果。

//======================================================
// 算24 C4 1.02
// 整理代码,去掉一些多余冗杂的地方
// 2018年4月23日 完成
// 2019年3月2日修改
//======================================================

//======================================================
// C2类,用于判断两个数通过加减乘除运算能否得到某个结果
// C代表Caculate,2代表两个操作数
// op1:操作数1,op2:操作数2,result,结果
//======================================================
function C2(op1,op2,result){
	var obj=new Object();
	obj.op1=op1;
	obj.op2=op2;
	obj.result=result;

	obj.findComputeMethods=function(){
		var micro=0.000001 // 定义一个极小量,运算结果绝对值小于它就算相等

		var arr=[];

		// op1+op2
		if(Math.abs(result-(op1+op2))<micro){
			arr.push(op1+"+"+op2);	
		}
		
		// op1*op2
		if(Math.abs(result-op1*op2)<micro){
			arr.push(op1+"*"+op2);	
		}
		
		// op1-op2
		if(Math.abs(result-(op1-op2))<micro){
			arr.push(op1+"-"+op2);	
		}
		
		// op2-op1
		if(Math.abs(result-(op2-op1))<micro){
			arr.push(op2+"-"+op1);	
		}
		
		// op1/op2
		if(Math.abs(result-op1/op2)<micro){
			arr.push(op1+"/"+op2);	
		}
		
		// op2/op1
		if(Math.abs(result-op2/op1)<micro){
			arr.push(op2+"/"+op1);	
		}

		return arr;
	}

	return obj;
}

//======================================================
// C3类,用于判断三个数通过加减乘除运算能否得到某个结果
// C代表Caculate,3代表三个操作数
// op1:操作数1,op2:操作数2,op3:操作数3,result,结果
//======================================================
function C3(op1,op2,op3,result){
	var obj=new Object();
	obj.op1=op1;
	obj.op2=op2;
	obj.op3=op3;
	obj.result=result;

	obj.findComputeMethods=function(){
		var retArr=[];// 最终返回数组

		// 排列数组,三个操作数共有6种排列方式
		var permutationArr=[ 
							[this.op1,this.op2,this.op3],
							[this.op1,this.op3,this.op2],
							[this.op2,this.op1,this.op3],
							[this.op2,this.op3,this.op1],
							[this.op3,this.op2,this.op1],
							[this.op3,this.op1,this.op2], 
						   ]; 

		for(var i=0;i<permutationArr.length;i++){
			var arr=permutationArr[i];
			var op1=arr[0];
			var op2=arr[1];
			var op3=arr[2];

			// [op1,op2]-op3
			var c2=new C2(op1,op2,this.result+op3);
			var methods=c2.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"-"+op3);
			}

			// [op1,op2]/op3
			c2=new C2(op1,op2,this.result*op3);
			methods=c2.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"/"+op3);
			}

			// [op1,op2]+op3
			c2=new C2(op1,op2,this.result-op3);
			methods=c2.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"+"+op3);
			}

			// op3-[op1,op2]
			c2=new C2(op1,op2,op3-this.result);
			methods=c2.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push(op3+"-"+'('+methods[j]+")");
			}

			// [op1,op2]*op3
			c2=new C2(op1,op2,this.result/op3);
			methods=c2.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"*"+op3);
			}

			// op3/[op1,op2]
			c2=new C2(op1,op2,op3/this.result);
			methods=c2.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push(op3+"/"+'('+methods[j]+")");
			}
		}

		return retArr;
	};

	return obj;
}

//======================================================
// C4类,用于判断三个数通过加减乘除运算能否得到某个结果
// C代表Caculate,4代表两个操作数
// op1:操作数1,op2:操作数2,op3:操作数3,op4:操作数4,result,结果
//======================================================
function C4(op1,op2,op3,op4,result){
	var obj=new Object();
	obj.op1=op1;
	obj.op2=op2;
	obj.op3=op3;
	obj.op4=op4;
	obj.result=result;

	obj.findComputeMethods=function(){
		var retArr=[];// 返回数组

		var permutationArr=[	[this.op1,this.op2,this.op3,this.op4],
							 [this.op1,this.op2,this.op4,this.op3],
							 [this.op1,this.op3,this.op2,this.op4],
							 [this.op1,this.op3,this.op4,this.op2],
							 [this.op1,this.op4,this.op2,this.op3],
							 [this.op1,this.op4,this.op3,this.op2], 
								[this.op2,this.op1,this.op3,this.op4],
							 [this.op2,this.op1,this.op4,this.op3],
							 [this.op2,this.op3,this.op1,this.op4],
							 [this.op2,this.op3,this.op4,this.op1],
							 [this.op2,this.op4,this.op1,this.op3],
							 [this.op2,this.op4,this.op3,this.op1], 
								[this.op3,this.op1,this.op2,this.op4],
							 [this.op3,this.op1,this.op4,this.op2],
							 [this.op3,this.op2,this.op1,this.op4],
							 [this.op3,this.op2,this.op4,this.op1],
							 [this.op3,this.op4,this.op1,this.op2],
							 [this.op3,this.op4,this.op2,this.op1], 
								[this.op4,this.op1,this.op2,this.op3],
							 [this.op4,this.op1,this.op3,this.op2],
							 [this.op4,this.op2,this.op1,this.op3],
							 [this.op4,this.op2,this.op3,this.op1],
							 [this.op4,this.op3,this.op1,this.op2],
							 [this.op4,this.op3,this.op2,this.op1], 
			               ]; // 全排列数组,四个操作数共有24种排列方式

		for(var i=0;i<permutationArr.length;i++){
			var arr=permutationArr[i];
			
			var op1=arr[0];
			var op2=arr[1];
			var op3=arr[2];
			var op4=arr[3];			

			// [op1,op2,op3]-op4
			var c3=new C3(op1,op2,op3,this.result+op4);
			var methods=c3.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"-"+op4);
			}

			// [op1,op2,op3]/op4
			var c3=new C3(op1,op2,op3,this.result*op4);
			var methods=c3.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"/"+op4);
			}

			// [op1,op2,op3]+op4
			var c3=new C3(op1,op2,op3,this.result-op4);
			var methods=c3.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"+"+op4);
			}

			// op4-[op1,op2,op3]
			var c3=new C3(op1,op2,op3,op4-this.result);
			var methods=c3.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push(op4+"-"+'('+methods[j]+")");
			}

			// [op1,op2,op3]*op4
			var c3=new C3(op1,op2,op3,this.result/op4);
			var methods=c3.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push('('+methods[j]+")"+"*"+op4);
			}

			// op4/[op1,op2,op3]
			var c3=new C3(op1,op2,op3,op4/this.result);
			var methods=c3.findComputeMethods();
			for(var j=0;j<methods.length;j++){
				retArr.push(op4+"/"+'('+methods[j]+")");
			}

			// 以下为C4中特有的先成对组合再看运算结果的六种情况
			// op1*op2-op3*op4
			if(op1*op2-op3*op4==result){
				retArr.push(op1+"*"+op2+"-"+op3+"*"+op4);
			}

			// op1*op2+op3*op4
			if(op1*op2+op3*op4==result){
				retArr.push(op1+"*"+op2+"+"+op3+"*"+op4);
			}

			// op1/op2-op3/op4
			if(op1/op2-op3/op4==result){
				retArr.push(op1+"/"+op2+"-"+op3+"/"+op4);
			}

			// op1/op2+op3/op4
			if(op1/op2+op3/op4==result){
				retArr.push(op1+"/"+op2+"+"+op3+"/"+op4);
			}
	
			// op1*op2-op3/op4
			if(op1*op2-op3/op4==result){
				retArr.push(op1+"*"+op2+"-"+op3+"/"+op4);
			}

			// op1*op2+op3/op4
			if(op1*op2+op3/op4==result){
				retArr.push(op1+"*"+op2+"+"+op3+"/"+op4);
			}
		}

		return retArr;
	}

	return obj;
}

//======================================================
// 用来得到仅包含不重复元素的数组
// arr:传入的数组
//======================================================
function getDistinctArray(arr){
    var returnArr=new Array();

    var sortedArr=arr.sort();
    for(var i=0;i<sortedArr.length;i++){
        if(returnArr[returnArr.length-1]!=sortedArr[i]){
            returnArr.push(sortedArr[i]);
        }
    }

    return returnArr;
}

//======================================================
// 程序入口
//======================================================
function main(){
	var RESULT=24 // 定义24这个结果

	process.stdin.resume();    
    process.stdout.write("\033[33m 请输入四个数字,用逗号分隔: \033[39m");// 草黄色
    process.stdin.setEncoding('utf8');
    
    process.stdin.on('data',function(text){
        var input=text.trim();
        process.stdin.end();// 退出输入状态  

		var arrTemp=input.split(",");
		var op1=parseInt(arrTemp[0],10);
		var op2=parseInt(arrTemp[1],10);
		var op3=parseInt(arrTemp[2],10);
		var op4=parseInt(arrTemp[3],10);

		var c4=new C4(op1,op2,op3,op4,RESULT);
		var arr=getDistinctArray(c4.findComputeMethods());

		if(arr.length>0){
			for(var i=0;i<arr.length;i++){
				console.log(arr[i]+"="+RESULT);	
			}
		}else{
			console.log(input+"这四个数无法计算得到24");
		}
	});
}

// 开始
main();

  

运行效果是这样的:

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 12,2,3,8
((12-8)*2)*3=24
((12-8)*3)*2=24
((12/2)-3)*8=24
((12/3)+8)*2=24
((3*8)-12)*2=24
((3*8)/2)+12=24
((3/2)*8)+12=24
((8*3)-12)*2=24
((8*3)/2)+12=24
((8-2)*12)/3=24
((8-2)/3)*12=24
((8/2)*3)+12=24
(12-(8/2))*3=24
(3/(2/8))+12=24
(8-(2*3))*12=24
(8-(3*2))*12=24
(8/(2/3))+12=24
12/(3/(8-2))=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 4,4,4,4
((4*4)+4)+4=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 9,9,9,9
9,9,9,9这四个数无法计算得到24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 10,10,4,4
((10*10)-4)/4=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 8,8,8,8
8,8,8,8这四个数无法计算得到24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 6,6,6,6
((6*6)-6)-6=24
((6+6)+6)+6=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 5,5,5,5
5*5-5/5=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 3,3,3,3
((3*3)*3)-3=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 2,2,2,2
2,2,2,2这四个数无法计算得到24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 12,12,12,12
((12*12)/12)+12=24
((12+12)*12)/12=24
((12+12)+12)-12=24
((12+12)-12)+12=24
((12+12)/12)*12=24
((12-12)+12)+12=24
((12/12)*12)+12=24
(12-(12-12))+12=24
(12/(12/12))+12=24
12-((12-12)-12)=24
12-(12-(12+12))=24
12/(12/(12+12))=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 11,13,4,2
11,13,4,2这四个数无法计算得到24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 12,11,13,1
((1*13)-11)*12=24
((13*1)-11)*12=24
((13-11)*1)*12=24
((13-11)*12)*1=24
((13-11)*12)/1=24
((13-11)/1)*12=24
((13/1)-11)*12=24
(13-(1*11))*12=24
(13-(11*1))*12=24
(13-(11/1))*12=24
12/(1/(13-11))=24

C:\Users\horn1\Desktop\node.js\56-算24c41.02>node c24.js
 请输入四个数字,用逗号分隔: 8,7,9,10
(8/(10-7))*9=24
(9/(10-7))*8=24
8/((10-7)/9)=24
9/((10-7)/8)=24

还有:

 

各位家长可以在和孩子玩这个游戏实在算不出来时验证下看有没有解决方案。

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

Asp.net core之NLog

NuGet添加 NLog.Web.AspNetCore。 <PackageReference Include="Microsoft.AspNetCore.App" /> 添加配置文件 新建一个文件nlog.config(建议全部小写,linux系统中要注意), 并右键点击其属性......

一介草民Coder
6分钟前
0
0
.NET中的struct和class有什么区别? - What's the difference between struct and class in .NET?

问题: .NET中的struct和class有什么区别? 解决方案: 参考一: https://stackoom.com/question/3OT/NET中的struct和class有什么区别 参考二: https://oldbug.net/q/3OT/What-s-the-differ...

富含淀粉
48分钟前
23
0
android:layout_weight是什么意思? - What does android:layout_weight mean?

问题: I don't understand how to use this attribute. 我不明白如何使用这个属性。 Can anyone tell me more about it? 谁能告诉我更多关于它的事情? 解决方案: 参考一: https://stacko...

javail
今天
17
0
CSS背景不透明度[重复] - CSS Background Opacity [duplicate]

问题: This question already has an answer here: 这个问题已经在这里有了答案: How do I give text or an image a transparent background using CSS? 如何使用CSS为文本或图像提供透明背...

fyin1314
今天
31
0
node http 获取gb2312网页如何转为utf8

最初,我想当然认为是下述做法,但被证明是错误的 const http = require('http'), iconv = require('iconv-lite');const url = 'http://xxx';http.get(url, function(res) { var bo......

高延
今天
24
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部