This website stores cookies. Click here to accept them.cookie information page

Week 5 - Objects - Now I have a proper deck of cards!

8th February 2012

@JonWebbOW

Blimey.  Week 5 and onto objects.  There was loads of new concepts here, so kudos to teach for getting it all across in an understandable way.  I think there was some kind of beta testing involved before the exercises went out, so this probably went a long way to help polish it up - thanks to all that did it!

Won't go into detail about the exercises, other than a note to self to read the question properly.  Sat at one point getting the right result (or so I thought) and the dreaded 'oops - try again' message only to realise after about half an hour of trying to do in different ways that I had not capitalised the first character of what was being output to console.  Grrrr.

But objects and methods open up a MASSIVE new horizon.  I'm going to need to try and find time to practice as have a feeling that a sound grasp of these concepts is going to be vital in going forwards.  I'm definitely not there yet - had to revisit the courses in order to create the below - a proper deck of cards!  

//Create constructor

function Card (value, suit, name) {

    this.value = value;

    this.suit = suit;

    this.name = name;

}

//Get card value for purpose of BlackJack

var getCardValue = function(cardNumber) {

    switch(cardNumber) {

        case 0: return 10;

        case 11: return 10;

        case 12: return 10;

        default: return cardNumber;

    }

};

//Get card suit

var getCardSuit = function(cardQuadrant) {

    switch (cardQuadrant) {

        case 1: return "Heart";

        case 2: return "Club";

        case 3: return "Diamond";

        case 4: return "Spade";

        default: return "Error - cardQuadrant not 1-4!";

    }

};

//Get name of card (UK standard!)

var getCardName = function(cardNumber) {

    switch (cardNumber) {

        case 0: return "Jack";

        case 1: return "Ace";

        case 11: return "Queen";

        case 12: return "King";

        default: return cardNumber;

    }

};

//Get which 'quadrant' the card is in

var getCardQuad = function(cardPosition) {

    return Math.floor((cardPosition/13)+1);

};

//Get position of card within that quadrant

var getCardNum = function(cardPosition) {

    return cardPosition % 13;

};

//Create new 'deck' array in global scope

var deck = new Array();

//cycle through numbers 0 to 51 and populate array with Card objects

for (i=0; i<52; i++) {

    var cardNum = getCardNum(i);

    var cardQuad = getCardQuad(i);

    deck[i] = new Card(getCardValue(cardNum), getCardSuit(cardQuad),

    getCardName(cardNum));

}

//Cycle through card objects in array and check that they are correctly populated

for (i=0; i<52; i++) {

    console.log(deck[i].name + " of " + deck[i].suit +"s has a value of " + deck[i].value);

}

Code can also be seen here): http://labs.codecademy.com/JYb#:workspace

There's loads of potential practice here:

- Shuffling - loads of different types to model to practice array manipulation (http://en.wikipedia.org/wiki/Shuffling)
- Dealing into hand arrays
- Method on card object to change value of Ace
- Pots, hitting, sticking, twisting, splitting, winning hands, moving money from player to player - actually, loads of stuff!

If anyone wants to have a punt at some interesting shuffle functions, or the method on the card object to change Ace value (with user prompts and input validation), or anything else, please post and I'll put up on the site.  Only rules are:

- Clarity over efficient code - I want to be able to understand it!  Commented code also good
- Use only functions/concepts taught by codecademy so far (see previous post)

Also - comments on my code are areas for improvement greatly welcomed!

Week 4 - Blackjack

2nd February 2012

@JonWebbOW

Good codecademy week.  Lots of content, and a bit more learning about the nature of an....... actually what is a collection of beginner programmers called?   I'll go for...... excitement of programmers.

Lessons aside, which were all useful, I'll concentrate on the project - Blackjack.

The project lesson was good.  Nicely paced project course with a little bit of emphasis on how to structure working on a project - start simple, test it works, add complexity, test it works, etc.

Good project I thought.  However, not a view shared by all.  

'why are we rolling a 52 sided dice? - this is not modelling the reality of the game' was the gist of one comment.

Well, yes.  There is nothing to stop the same card being dealt more than once.  But that's what the lesson (or spec) required, so that's why we're 'rolling a 52 sided dice'.   I have no doubt that in a future iteration of the lesson, this logical hole will be addressed.

'Hey everybody, check out my code - it uses the 'splice' function to remove the dealt card from the array of cards that I've set up' was the essense of another

'Your code shuffles the cards each time you deal.  This is wrong - it should shuffle first and then deal.  It's more efficient that way'

And so on.

Here is where I have a problem with the excitement of programmers.  Beginner programmers are now trying to teach other beginner programmers best practice, and are introducing functions that 'just do the job' with little explanation and very possibly little knowledge.   I have no doubt that this will escalate as people try to outdo each other.  "I've used a jquery plugin as an interface to the dealing function" I'm sure is not far away.

I'm not saying the comments are wrong (I really wouldn't know - I'm only on week 4 of code year!), but the danger is that others who are earlier on the learning-curve will pick up on these functions etc, and use them without really understanding why or what is actually happening (these new developers are known as a 'herd' of developers).  If this is the case, we will end up with a lot of people who sort of know what lots of functions etc do, but with no real underlying knowledge of how to program or good progamming practice.  Not the direction for me.

Don't get me wrong, I'm all for not relying on lessons alone, for trying different things out and sharing and getting ideas from others.  In fact, I googled and used the splice function before thinking that this is not the right road for me.  For me it's important to understand, practice, fail, succeed what I've been taught over finding a function that someone else has written that will do it for me.  If I do that, I might as well not bother.

So from now on, I'm going to try very hard to only use what we've been taught in the course.  And on that note, have made a function called mySplice that almost certainly is not as efficient as THE splice function. But I wrote it and therefore it is infinitely better.

Please note - the below is only loosely based on a pack of cards.  It is not intended to be a blackjack simulator,  It is not meant to model reality.  What is outside of the mySplice function is just a vehicle for it. All it ultimately does is write to the console 52 unique numbers (and apologises if it has no more numbers but you want more).

(you can also see it in action here: http://labs.codecademy.com/IRP/1#:workspace)

//Global array variable that is our pack of cards

var deck = [];

//This function just creates an array containing numbers 1 to 52

var populateDeck = function() {

  for (i=0; i<52; i++) {

deck[i] = i+1;

}

};

//This function removes an element from the array. It accepts the

//position of the element to be removed

var mySplice = function(element) {

//take each element in turn prior to the element to be removed and

//add to a temp array in the same position

var tempArray = [];

for (i=0; i<element; i++) {

tempArray[i] = deck[i];

}

//take each element in turn after the element to be removed and

//add to a temp array in the same position minus one place

//(meaning the element to be removed is not put into the

//temp array, and there are no empty elements (i.e. the temp array

//is one element shorter than the original array).

    for (i=element+1; i<deck.length; i++) {

tempArray[i-1] = deck[i];

}

//the deck array now assumes the temp array's elements

deck = tempArray;

};

//This function 'deals' a card from the array, and removes the element

//that it has 'dealt' (shortening the array). If there are no more

//cards it apologies. Which is nice.

var dealUnique = function() {

var card;

if (deck.length < 1) {

card="Sorry, there are no more cards in the deck";

} else {

var cardPosition = Math.floor(Math.random()*deck.length);

card = deck[cardPosition];

mySplice(cardPosition);

}

return(card);

};

//Initialising...

populateDeck();

//deal out all the cards (and try and deal out a few more)

for (j=0; j<60; j++) {

console.log(dealUnique());

}

Week 3 - Dice Game, no bugs and you don't need to declare a variable

25th January 2012

Week 3 and it's revision time!  I love revision.

@JonWebbOW

Conditionals lesson was all good.  Although a bit dull, I think being forced to type out statements a number of times is probably very good for helping to retain the information.  Introduction of switch statement (or is it case statement) very interesting.  Think it is time to revisit FizzBuzz with this new knowledge.

Ternary operators look to be a bit of a double-edged sword to me.  I like that they are quicker to write, but how readable are they going to be if you need them nested.  Let's see:

//if a creature has 4 legs and a long neck, it's a giraffe, if it has four legs but not a long neck it's an elephant, if it hasn't got four legs but has a long neck it's an ostrich, if it hasn't got four legs or long neck, it's a kangaroo

var result = "";
var legs = 2;
var longNeck = "y";

result = legs === 4 ? (longNeck === 'y' ? "giraffe" : "elephant") : (longNeck === "y" ? "Ostrich" : "Kangaroo");

That's quite simple, doesn't even check for 2 legs for the latter animals or handle for other number of legs, but already it is loads less readable (to me) than a nested if statement would be.  Maybe this will change with experience, but I think for my own sanity, will only use ternary operators for simple jobs.

Nothing to declare

What else?  Oh yeah, looks as though you don't have to declare variables!  That was sort of slipped in there!!!  From exercise 5.1 (conditionals in javascript):

var x = 12;
var y = 12;

if (x > y) {
result = "good job";
} else {
result = 20;
}

//Below is the above code written using the ternary operator

result = x > y ? "good job" : 20;

At no point is result being declared as a variable.  So does this mean I don't need to do so in future?  In what scope are the undeclared variables?  Any info gratefully received!

No bugs

After last week's issues with not being able to complete exercises despite being correct, I had no problems this time round.  I do hope however that the developers have not taken the 'easy' route for this (see 'codeacademy week 2 - some teething problems' in January code year blog)

And for my final trick - it ain't pretty, but if you don't roll the dice...

Jamming together a bit of html code from http://www.w3schools.com/js/js_functions.asp, namely:

<html>
<head>
<script type="text/javascript">
function displaymessage() {
alert("Hello World!");
}
</script>

</head>
<body>
<form>
<input type="button" value="Click me!" onclick="displaymessage()" />
</form>
</body>
</html>

With the dice function, gives me my first web-based javascript function button thing!

YeeHah!   Source Code here:

<html>
<head>
<script type="text/javascript">
// pick a random number between 1 and 6 for our roll of the die
var rollDice = function() {
var die1 = Math.floor(Math.random()*6 + 1); var die2 = Math.floor(Math.random()*6 + 1);
var score;
// This time if either die roll is 1 then score should be 0
if((die1 === 1) || (die2 === 1)) {
score = 0;
}
else if (die1 === die2) {
score = ((die1 + die2) * 2);
} else {
score = (die1 + die2);
}
 alert("You rolled a "+die1+" and a "+die2+" for a score of "+score);
};
</script>
</head>
<body>
<form>
<input type="button" value="Click me!" onclick="rollDice()" />
</form>
</body>
</html>

PS - My Code Year Experience Twitter account is...

18th January 2012

http://twitter.com/JonWebbOW

Not a lot there right now as just set it up, but follow for updates!

codeacademy week 2 - some teething problems

18th January 2012

@JonWebbOW

At last! Have a new lesson and a new exercise! This week taught me some important lessons - not all code related. It has also required me to make myself a couple of my own badges...

The first lesson was on functions. There was a previous optional lesson on function that I went through, so thought 'piece of cake'. Right from the off though, it seems that the way I was led to declare functions in the first exercise:

function functionName() {}

Differed from the way that we were instructed to do it in these lessons:

var functionName = function() {}

However, no explanation. I guess that if everything was explained in detail, then the learning model would be fundamentally different and I might as well read a book rather than learn in this experiential way that I prefer. I think it's the case that the inquisitive will do their homework - engaging them more than these lessons alone. Will be interesting if there is a conceptual difference, or whether it is simple another way of expressing exactly the same thing. Hopefully I will find time to research, and if there is a difference, hopefully I will understand! If so, will blog about it.

Nice easy exercises (if you did the optional functions one, it should be pretty straight forward). But wait - why am I getting 'Oops, try again' on exercise 1.4 'Fix me!'. Everything is correct. Console is outputting correctly - semi-colons all in the right place - all looks good. Why does it not work? I assume that this must be a bug and am about to move onto the next exercise when I notice there's a Q+A section (that's new). Clicking on there, I take a quick look - looks like others having similar problems, but they also have other problems in their code that mean it's hard for the more 'authoritave' users to agree it must be a bug. I therefore post up my code which I'm sure is correct and what is expected:

var fullName = "";

var name;

var firstLetter;

var fixName = function () {

  firstLetter = name.substring(0, 1);

  name = firstLetter.toUpperCase() + name.substring(1);

  fullName = fullName + " " + name;

};

 

name = prompt("Enter your first name (all in lower case):");

fixName();

name = prompt("Enter your second name (all in lower case):");

fixName();

console.log("And your full name is:" + fullName);

I get an authoritative response saying that of course it does not work as I'm not passing the variable 'name' to my function. Suitably admonished, I go back to my code to change, but then realise that name is in global scope so this in unnecessary, and I know that this works anyway as I get the right result in console. With a smug grin, I post back, mentioning 'P.S. 'name' does not need to be passed into the functions it is in global scope', to which I receive a reply of 'Oops - yes it is - thanks!'.

So already, two badges I'm awarding myself, and one good lesson

Badge 1: SMUG

smug face

Awarded for: 'P.S. name does not need to be passed into the functions as it is in global scope'

Lesson 1 - people who sound authoritative and know what they're talking about may well not. Take suggestions on board, but interrogate before just accepting it. I guess in time, I will learn who is right more than wrong and more easily take advice from them than others.

Badge 2 - Concerned that my SMUG badge winning post may lead others to accept future posts as gospel, I've awarded myself this one: Warning - On shaky ground!

exclamation mark

I know what you're thinking - an artist too? - is there no end to this guy's talents?!

Anyway, accepting it as a bug I move on through the rest of the exercises. All pretty straight forward, but were a couple more bugs that meant successfully completed exercises were not being marked complete. This led to lots of comments on the Q+A section suggesting that it was not acceptable, was a joke, etc etc - mostly in good humour. One less ranting suggestion was that exercises should be judged successful simply from the output to console rather than looking at what was in the code. While I understand the sentiment, I don't think that this would be a good idea. It would allow someone who has not yet understood a section to be able to pass it by simply by outputting what is required. E.g:

Write a function accepts a number and returns the highest prime factor of that number. Then call this function to output the highest prime factor of the number 10.

If I couldn't get my head around this, and just wanted to pass, I could simply write:

console.log("5");

Job done! Though the hole in my knowledge would inhibit me going forwards and I imagine as a result I would do this more and more until I was in a position where I had passed all the tests, but very little knowledge (or fun gaining it). I'm not sure how the developers who create the lessons write the code that decides whether something that has been successful or not, but I applaud them for not taking the easy route - the odd bug is a small price to pay. Fixes were put into place by the developers as soon as they had woken up and taken a look at the comments.

Oh, yeah, 'Hello, New York' was the exercise this week. All straight forward (again, there was a little bug which meant that you could only pass if parameters in a function were defined in a certain order).

Looking forward to the next one. Might have a go at updating fizzbuzz between now and then. Or maybe I should do that investigation into the different way of declaring functions...So much to do, so little time!

FizzBuzz

16th January 2012

@JonWebbOW

Right, down to the nitty gritty. My first application!

This was quite straightforward as expected (we're only on week 1!), but did highlight one important thing to me. There are many ways to skin the programming cat. Broadly, the solution you are led to is:

// for the numbers 1 through 20,

for (i=1; i<=20; i++) {

 

  // if the number is divisible by 3 and 5, write "FizzBuzz"

  if (( i % 3 == 0 ) && ( i % 5 == 0 )) {

    console.log("FizzBuzz");

  }

 

  // if the number is divisible by 3 only, write "Fizz"

  else if (i % 3 === 0) {

    console.log("Fizz");

  }

 

  // if the number is divisible by 5, write "Buzz"

  else if ( i % 5 == 0 ) {

    console.log("Buzz");

  }

 

  // otherwise, write just the number

  else {

    console.log(i);

  }

}

I would not have implemented in the way that they did - all those console.log lines made me nervous for some reason (might not be rational), and also it seemed quite specific to FizzBuzz. If the name changed to AlphaBeta, I would need to change three different lines, one of these changes is a bit redundant). So, sure in the knowledge that I would come up with a far better, cleaner and more elegant solution, I had a crack at 're-factoring' it:

// for the numbers 1 through 20,

for (i=1; i<=20; i++) {

  // Variable declare and assign

  var partOne = "";

  var partTwo = "";

  var fizzOrBuzz = false;

  var output = "";

  // if the number is divisible by 3, change partOne to "Fizz" and change fizzOrBuzz to true

  if ( i % 3 === 0 ) {

    partOne = "Fizz";

    fizzOrBuzz = true;

  }

  // if the number is divisible by 5, change partTwo to "Buzz" and change fizzOrBuzz to true

  if (i % 5 === 0) {

    partTwo = ("Buzz");

    fizzOrBuzz = true;

  }

  // If fizzOrBuzz = true, output = part1 and part2

  if (fizzOrBuzz) {

    output = partOne + partTwo;

  }

  // Else output = i

  else {

    output = i;

  }

  console.log(output);

}

It works, but it's not quite the clean and elegant solution I had in mind when I started - it required more variables than I thought it would and gets really ugly towards the end as I was determined to only have one console.log (which I still don't know is sensible anyway!).

Sure that this can most definitely be improved on in future interations. I guess it does make it less specific to FizzBuzz in that I only need to change two lines of code if the name changes, and there is now only one console.log line in there, but it still feels a bit on the ugly side.

I think that each time I carry out a new exercise, or if I have a flash of inspiration, I will revisit and re-work the code to try and improve on each of the previous applications.

Looking forward to the next application that should be out tomorrow!

Code Academy (www.codeacademy.com) – Why?

15th January 2012

I'm doing this for fun really. Also, it will allow me to tell the real developers in the office that I, too, am a programmer as I've done an online course. They really won't like that.

The blunt reality is that in order to become a proficient programmer, you need to dedicate yourself to learning code, and applying that learning day in day out to not necessarily neatly packaged problems. Even after many years, developers will find a new way of doing something, therefore there is not a point where someone has finished learning, it just a question of how far down the road one has travelled that separates the professionals from the merely interested.

Despite being a speck in their rear view mirrors, being on the same road will however hopefully mean that I will be able to converse a little better in their language, and understand some of the pitfalls/obstacles/reasons that result in the response "how long is a piece of string?" when I ask how long a seemingly very simple task will take.

Not sure whether javascript is the right place to start, but it is all that's on offer from www.codeacademy.com for code year which is my chosen first car for my journey, so javascript it is.

In order that I get the full driving experience, I am not going to consult with the developers in the office for the best way to do something, though I will allow myself to talk with them about concepts in an abstract way. If anyone is at the same place as me and has comments or questions, then please feel free to comment on these posts.

If you have started the code academy courses already, then great - If not, it definitely worth a look. I'm not sure that it will take you far fast, but it is very good at getting concepts over in an easily digestible way – and you get badges and points and everything!

I've managed to complete the tutorials and they were all enjoyable and got a lot of information over quickly. That the exercises do not allow you to progress until you have completed the current one is great. Means that you really do have to understand a concept (or get there by brute force I suppose, but this would probably take longer) before moving on. Exceptions to this are when it is not completely clear what is expected and you can sit there for some time until you guess correctly what the system expects.

Next blog post is all about the first Application – FizzBuzz!

Jon

© Alberon Ltd 2017

8 Standingford House
26 Cave Street
Oxford
OX4 1BA

01865 596 144

Oxford Web is a trading name of Alberon Ltd, registered company no. 5765707 (England & Wales).