1

I'm more of a media developer and not the best coder, but I find myself needing to learn javascript better. I'm creating a math card game where the human player and the automated player are each dealt 6 cards. Each player must combine (concatenate) three of the cards to make a top number and the other three for the bottom number. Those two numbers are then subtracted. For the automated player, I have to go through ever possible combination of the six cards, so when the two numbers are subtracted, it gets as close as possible to a target number. I'm not very good with arrays, so I started testing every possible combination and then comparing which one was closer (See example below). This is a very inefficient way of coding this, but I'm just not sure how to do it otherwise. Any help would be greatly appreciated.

The variables have already been declared.

alienTopNum = "" + alienNum1 + alienNum2 + alienNum3;
alienBottomNum = "" + alienNum4 + alienNum5 + alienNum6;
oldDiff = targetNum - (alienTopNum - alienBottomNum);
player.SetVar("AC1R1", alienNum1);
player.SetVar("AC2R1", alienNum2);
player.SetVar("AC3R1", alienNum3);
player.SetVar("AC4R1", alienNum4);
player.SetVar("AC4R1", alienNum5);
player.SetVar("AC4R1", alienNum6);
player.SetVar("ATR1", alienTopNum - alienBottomNum);
alienTopNum = "" + alienNum1 + alienNum2 + alienNum3;
alienBottomNum = "" + alienNum4 + alienNum6 + alienNum5;
newDiff = targetNum - (alienTopNum - alienBottomNum);
if (Math.abs(newDiff) < Math.abs(oldDiff)) {
    oldDiff = newDiff;
    player.SetVar("AC1R1", alienNum1);
    player.SetVar("AC2R1", alienNum2);   
    player.SetVar("AC3R1", alienNum3);
    player.SetVar("AC4R1", alienNum4);
    player.SetVar("AC4R1", alienNum6);   
    player.SetVar("AC4R1", alienNum5);
    player.SetVar("ATR1", alienTopNum - alienBottomNum);
}

etc....

ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
TheDeaner
  • 11
  • 1
  • It is rather difficult to make out your code as it is currently formatted as a quotation. If you would like for it to be rendered as code then you can use the button marked with curly braces {} in the question editor. It is also difficult to help at the moment as your question is unclear. Please check-in with the great guide here which explains what makes a good Stackoverflow question: https://stackoverflow.com/help/how-to-ask – John Nov 30 '17 at 01:07

1 Answers1

0

Store the dealt cards in an array rather than in individual variables, because that makes them a lot easier to handle when generating permutations. You don't say what values the cards can have, but as an example, given a "hand" of [1,2,3,4,5,6] if you get the permutations as an array of arrays:

[ [1,2,3,4,5,6], [1,2,3,4,6,5], [1,2,3,5,4,6], ...etc. ]

Then you can loop through that to process each permutation to take the first three "cards" and last three to get the current iteration's two numbers, subtract them, and see if the result is closer to the target than previous iterations' results.

The following does that, making use of the array permutation function that I found in this answer to another question. I'm not going to explain that algorithm because you can easily google up various permutation algorithms for yourself, but I have put comments in my bestPlay() function to explain how I process the permutations to figure out which is the best score for a hand.

I haven't tried to use your player or player.SetVar() method, but hopefully if you study this you can adapt it to use with your objects.

You didn't say what values the cards could have, so I've assumed a deck of twenty cards that repeats the numbers 0-9 twice.

function bestPlay(hand, target) {
  var perms = permutator(hand);            // Get all permutations for hand
  var best = perms[0];                     // Use the first as initial best
  var bestDiff = difference(best);
  for (var i = 1; i < perms.length; i++) { // Loop over the rest of the permutations
    var diff = difference(perms[i]);       // Get diff for current permutation
    if (Math.abs(target - diff) < Math.abs(target - bestDiff)) { // Check if
      best = perms[i];                     // current beats previous best
      bestDiff = diff;                     // and if so make it new best
    }
  }
  // Output the results for this hand:
  console.log(`Hand: ${hand.join(" ")}`);
  console.log(`Best Numbers: ${best.slice(0,3).join("")} ${best.slice(3).join("")}`);
  console.log(`Difference: ${bestDiff}`);
}

var hands = deal();
var target = 112;
console.log(`Target: ${target}`);
bestPlay(hands[1], target);
bestPlay(hands[2], target);

function difference(cards) {
  return Math.abs(cards.slice(0,3).join("") - cards.slice(3).join(""));
}

function deal() {
  var cards = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0];
  // shuffle
  cards.sort(function() { return Math.random() - 0.5; });
  // first hand is first six cards, second hand is next six
  return {
    1: cards.slice(0,6),
    2: cards.slice(6, 12)
  };
}

function permutator(inputArr) {
  var results = [];
  function permute(arr, memo) {
    var cur, memo = memo || [];
    for (var i = 0; i < arr.length; i++) {
      cur = arr.splice(i, 1);
      if (arr.length === 0) {
        results.push(memo.concat(cur));
      }
      permute(arr.slice(), memo.concat(cur));
      arr.splice(i, 0, cur[0]);
    }
    return results;
  }
  return permute(inputArr);
}

If you click the "Run Code Snippet" button several times you'll see that sometimes a given hand has a combination of numbers that exactly matches the target, sometimes it doesn't.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • nnnnnnn, thank you so much for your response and explanation! It is very appreciated and gets me in a really good direction. Thank you, thank you! – TheDeaner Dec 01 '17 at 20:38