J'écris des fonctions liées au mahjong en JavaScript.S'il vous plaît aidez-moi à accélérer cet algorithme de mahjong
Voici ce que j'ai ci-dessous, avec le code pour les cas de test.
Notez que les mains mahjong sont représentées par des tableaux, avec:
- élément 0 étant le nombre total de carreaux dans la main
- éléments 1 à 34 étant le nombre de tuiles de chaque type dans la main
- premier craks, puis des points, puis BAMS, puis serpente, et les dragons enfin
La fonction de recherche d'attente s'exécute très lentement. Comment puis-je l'accélérer?
// 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 />");
vous obtiendriez probablement plus de réponses de meilleure qualité si vous ne tenez pas pour acquis que nous savons ce qu'est le mah-jong, ou quelles sont les expressions telles que wall, wait, etc. Et peut-être vous a expliqué les exigences fonctionnelles du tout. – RBarryYoung
Deux autres commentaires - votre fonction well_formed manquera quelques mains en saisissant les séries de trois (pungs) en premier. Par exemple, 345, 456, 567 dans le même costume perdraient immédiatement tous les 5s. En outre, vous ne considérez pas les kongs (quatre d'un genre) ici. Mais peut-être que ce dernier est délibéré? –
En ce qui concerne les kongs: j'ai décidé de ne pas les traiter pour le moment, et en tout cas, une main avec un * kong * déclaré ne contiendrait pour nous que onze tuiles (celles qui ne font pas partie du kong). Et ensuite: Quant à 345, 456, 567: si j'avais une main avec 344555667, oui, je supprimerais d'abord le 555 puis je vérifierais 344667. Ensuite, je réaliserais que ça ne marche pas, alors j'essaierais enlever 345, être laissé avec 455667, et voir que cela fonctionne. Un peu comme la façon standard de résoudre le problème des "huit reines". –