0

I am trying to compile the following CoffeeScript code into Javascript:

GetCard = ->
  do Math.floor do Math.random * 12

Results = ->
  do NewGame if prompt "You ended with a total card value of #{UserHand}. Would you like to play again?"
  else
    alert "Exiting..."

NewGame = ->
  UserHand = 0
  do UserTurn

UserTurn = ->
  while UserHand < 21
    if prompt "Would you like to draw a new card?" is "yes"
      CardDrawn = do GetCard
      UserHand += CardDrawn
      alert "You drew a #{CardDrawn} and now have a total card value of #{UserHand}."
    else
      do Results
      break

But the resulting Javascript prints the following errors to the console if you say yes:

Uncaught TypeError: number is not a function BlackJack.js:4
GetCard BlackJack.js:4
UserTurn BlackJack.js:22
NewGame BlackJack.js:14
onclick

CoffeeScript is also not setting UserHand to 0 for some reason. I am fairly new to Javascript and very new to CoffeeScript. I've searched around and read the CoffeeScript docs as well as the CoffeeScript Cookbook and as far as I can tell the CS code looks correct, while the JS doesn't:

var GetCard, NewGame, Results, UserTurn;

GetCard = function() {
  return Math.floor(Math.random() * 12)();
};

Results = function() {
  return NewGame(prompt("You ended with a total card value of " + UserHand + ". Would you like to play again?") ? void 0 : alert("Exiting..."))();
};

NewGame = function() {
  var UserHand;
  UserHand = 0;
  return UserTurn();
};

UserTurn = function() {
  var CardDrawn, _results;
  _results = [];
  while (UserHand < 21) {
    if (prompt("Would you like to draw a new card?") === "yes") {
      CardDrawn = GetCard();
      UserHand += CardDrawn;
      _results.push(alert("You drew a " + CardDrawn + " and now have a total card value of " + UserHand + "."));
    } else {
      Results();
      break;
    }
  }
  return _results;
};

Any help would be greatly appreciated. Thanks!

Update: Thanks for all the answers. I just got a little confused on the double parentheses and mistakenly used the do keyword to replace the parameter parenthesis instead of the function call parenthesis. I'm still confused on the global scope though. I know you can use the var keyword in plain JS, but on the CoffeeScript docs it specifies that you should never need to use it, as it manages scope for you?

4
  • the issue is here: Math.floor(Math.random() * 12)() (note the trailing brackets). As to why coffeescript added that, I don't know (I'm not familiar with it). At a guess, maybe because you have 2 do keywords in that line? Commented Aug 25, 2013 at 1:46
  • Also it is setting UserHand, but it is a local variable to NewGame. I guess you intended it to be a global variable. Again, I'm not familiar with coffeescript so I don't know exactly what you need to do there. Commented Aug 25, 2013 at 1:48
  • If you're new to JavaScript, stay away from CoffeeScript. Commented Aug 25, 2013 at 2:14
  • Thanks! Changing the GetCard statement to use parentheses instead of the do keyword worked. And I still haven't figured out why CS is setting UserHand as a local variable... maybe someone else will chime in. Commented Aug 25, 2013 at 2:30

2 Answers 2

1

After a little reading, it seems your first problem is because of the do operator. As far as I can tell, it is for creating closures within loops to bind current values to functions. Not what you need here.

I don't think there's anything wrong with simply:

GetCard = ->
    Math.floor( Math.random() * 12 )

The second issue is one of scope. UserHand is local to NewGame, so it isn't accessible in UserTurn (it is undefined there). You could make it global, or pass it as a parameter, but it looks to me like NewGame only needs the result anyway:

NewGame = ->
    hand = UserTurn() // set hand to whatever the UserHand is from UserTurn

UserTurn = ->
    UserHand = 0
    while UserHand < 21
        if prompt "Would you like to draw a new card?" is "yes"
        (etc)
    UserHand // return the final UserHand value after the loop

I'd also suggest rethinking a few names; some are a little confusing. And while you've broken it up at many good points, there are still some odd choices (e.g. why is going over 21 handled by UserTurn but stopping handled by another function?)

Sign up to request clarification or add additional context in comments.

Comments

0
GetCard = ->
  Math.floor(Math.random() * 12)

You need the parens there to clarify that you want to invoke Math.random with no arguments. Otherwise a functionName something means "invoke functionName with something as the first argument".

In general, only omit parens for function calls when it is dead-obvious, otherwise it is an ambiguous thing that hampers readability.

OK:

someFunc 1, 2, 3

Unclear:

someFunc someOtherFunc someArg

(aside...)

You should review the do keyword. It is only useful for a very specific purpose and almost all of your uses are unnecessary/incorrect.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.