gpt4 book ai didi

javascript - 请帮我加快这个麻将算法

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:12:07 26 4
gpt4 key购买 nike

我正在用 JavaScript 编写一些与麻将相关的函数。

下面是我的测试用例代码。

注意麻将牌是用数组表示的,有:

  • 元素0为手中牌的总数
  • 元素 1 到 34 是手中每种类型的牌数
    • 先是噼啪声,然后是点声,然后是砰声,然后是风声,最后是龙声

查找等待的函数运行得非常慢。我怎样才能加快速度?

// tiles are indexed as follows:
// 1..9 = 1 crak .. 9 crak
// 10..18 = 1 dot .. 9 dot
// 19..27 = 1 bam .. 9 bam
// 28..34 = east, south, west, north, white, green, red

var wall = new Array();
set_up_wall();

function set_up_wall() {
for (var i=1; i<=34; i++) wall[i] = 4;
wall[0]=136;
}

// draw tile from wall
function draw() {
var fudge = 1-(1e-14);
var n = Math.floor(Math.random()*wall[0]*fudge);
var i = 1;
while (n>=wall[i]) n-=wall[i++];
wall[i]--;
wall[0]--;
return i;
}

// get number of a tile (or 0 if honor)
// e.g. 8 bams = 8
function tilenum(i) {
if (i>27) return 0;
if (i%9==0) return 9;
return i%9;
}

// get suit of a tile (or 0 if honor)
function tilesuit(i) {
var eps = 1e-10;
return Math.ceil(i/9-eps)%4;
}

// is this a well-formed hand?
function well_formed(h) {
// this function is recursive
if (h[0]==2) return only_pairs(h);
if (h[0]==14) {
if (only_pairs(h)) return true;
if (thirteen_orphans(h)) return true;
}
if (h[0]%3 != 2) return false; // wrong no. of tiles in hand
// now we start splitting up the hand
// look for three of a kind
for (var i=1; i<=34; i++) {
if (h[i]>=3) {
// create new hand minus the three of a kind
hh = new Array();
for (var j=0; j<=34; j++) hh[j]=h[j];
hh[0]-=3;
hh[i]-=3;
if (well_formed(hh)) return true;
}
}
// look for a run of three
for (var i=1; i<=25; i++) {
if (tilenum(i)<=7) {
if (h[i]>=1 && h[i+1]>=1 && h[i+2]>=1) {
// create new hand minus the run
hh = new Array();
for (var j=0; j<=34; j++) hh[j]=h[j];
hh[0]-=3;
hh[i]--; hh[i+1]--; hh[i+2]--;
if (well_formed(hh)) return true;
}
}
}
// if we reach here, we have exhausted all possibilities
return false;
}

// is this hand all pairs?
function only_pairs(h) {
for (var i=1; i<=34; i++) if (h[i]==1 || h[i]>=3) return false;
return true;
}

// thirteen orphans?
function thirteen_orphans(h) {
var d=0;
var c=new Array(14, 1,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1);
for (var i=0; i<=34; i++) {
if (c[i]==0 && h[i]>0) return false;
if (h[i]!=c[i]) d++;
}
return d==1;
}

// this is inefficient
function waits(h) {
var w=new Array();
for (var j=0; j<=34; j++) w[j]=false;
if (h[0]%3!=1) return w; // wrong no. of tiles in hand
// so we don't destroy h
var hh = new Array();
for (var j=0; j<=34; j++) hh[j]=h[j];
for (var i=1; i<=34; i++) {
// add the tile we are trying to test
hh[0]++; hh[i]++;
if (hh[i]<5) { // exclude hands waiting for a nonexistent fifth tile
if (well_formed(hh)) {
w[0] = true;
w[i] = true;
}
}
hh[0]--; hh[i]--;
}
return w;
}

function tiles_to_string(t) { // strictly for testing purposes
var n;
var ss="";
var s = "x 1c 2c 3c 4c 5c 6c 7c 8c 9c 1d 2d 3d 4d 5d 6d 7d 8d 9d ";
s += "1b 2b 3b 4b 5b 6b 7b 8b 9b Ew Sw Ww Nw Wd Gd Rd";
s=s.split(" ");
for (var i=1; i<=34; i++) {
n=t[i]*1; // kludge
while (n--) ss+=(" "+s[i]);
}
return ss;
}

// tests

var x;
x = new Array(13, 0,0,0,0,0,1,2,2,2, 2,2,2,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0);
document.write("Hand: "+tiles_to_string(x)+"<br />");
document.write("Waits: "+tiles_to_string(waits(x))+"<br /><br />");
x = new Array(13, 1,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1);
document.write("Hand: "+tiles_to_string(x)+"<br />");
document.write("Waits: "+tiles_to_string(waits(x))+"<br /><br />");
x = new Array(13, 0,0,0,0,0,0,0,0,0, 3,1,1,1,1,1,1,1,3, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0);
document.write("Hand: "+tiles_to_string(x)+"<br />");
document.write("Waits: "+tiles_to_string(waits(x))+"<br /><br />");
x = new Array(13, 4,0,0,3,3,3,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0);
document.write("Hand: "+tiles_to_string(x)+"<br />");
document.write("Waits: "+tiles_to_string(waits(x))+"<br /><br />");
x = new Array(13, 0,0,4,3,3,3,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0);
document.write("Hand: "+tiles_to_string(x)+"<br />");
document.write("Waits: "+tiles_to_string(waits(x))+"<br /><br />");

最佳答案

您有一个数组来保存手牌的内容,然后您在递归函数中创建一个新数组来保存减去一组特定图 block 的内容。不用创建所有这些数组,而是创建两个数组 - 一个用来存放正在考虑的手,另一个用来存放你已经考虑过的手上的牌 - 然后将它们都传递过来。所以这个:

hh = new Array();
for (var j=0; j<=34; j++) hh[j]=h[j];
hh[0]-=3;
hh[i]-=3;
if (well_formed(hh)) return true;

变成这样:

h[0]-=3;
h[i]-=3;
hc[0]+=3;
hc[i]+=3;
if (well_formed(h,hc)) return true;

您将 h 和 hc 传递过来,请记住,要重建整只手,您需要将这两个数组相加。但这可以在考虑 hnd 是否完整时出现。

编辑:我的意思更详细:编辑:我希望现在可以工作......第一次尝试时出现错字。

// is this a well-formed hand?
function well_formed(h) {
hc = new Array();
for (var i=0; i<=34; i++) hc[i]=0;
result = well_formed_recursive(h, hc);
for (var i=0; i<=34; i++) h[i]+=hc[i];
return result;
}

function well_formed_recursive(h, hc) {
// this function is recursive
if (h[0]==2) return only_pairs(h);
if (h[0]==14) {
if (only_pairs(h)) return true;
if (thirteen_orphans(h)) return true;
}
if (h[0]%3 != 2) return false; // wrong no. of tiles in hand
// now we start splitting up the hand
// look for three of a kind
for (var i=1; i<=34; i++) {
if (h[i]>=3) {
h[0]-=3;
h[i]-=3;
hc[0]+=3;
hc[i]+=3;
if (well_formed_recursive(h,hc)) return true;
}
}
// look for a run of three
for (var i=1; i<=25; i++) {
if (tilenum(i)<=7) {
if (h[i]>=1 && h[i+1]>=1 && h[i+2]>=1) {
h[0]-=3;
h[i]--; h[i+1]--; h[i+2]--;
hc[0]+=3;
hc[i]++; hc[i+1]++; hc[i+2]++;
if (well_formed_recursive(h,hc)) return true;
}
}
}
// if we reach here, we have exhausted all possibilities
return false;
}

关于javascript - 请帮我加快这个麻将算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1928899/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com