info343/homework/5/writeup.php

<section>
   <?= head("Introduction") ?>
   
   <p>This assignment practices DOM element creation and special effects. For it you will build a game of <a href="http://en.wikipedia.org/wiki/Concentration_(game)">Memory</a> (also known as Concentration).</p>
   
   <p>Memory is a card game which involves placing shuffled pairs of cards face-down at random, and turning over two at a time. When the two cards match, they are removed; when they do not, they are turned face down again.</p>
   
   <p>The object of the game is to remove all cards in as few turns as possible. This requires remembering the location of previously-seen cards when their match is uncovered.</p>
   
   <p>You will turn in <strong>at least</strong> the following files:</p>
            
   <style type="text/css">
      dl.filelist {
/*         margin-left: 1em; */
      }
      
      dl.filelist dt {
         float: left;
         clear: left;
         height: 1.4em;
      }
      
      dl.filelist dd {
         margin-left: 10em;
/*         background-color: fuchsia;*/
         margin-bottom: .5em;
         position: relative;
         white-space: nowrap;
      }
   </style>
   
   <dl class="filelist">
      <dt><samp>memory.html</samp></dt>
         <dd>The HTML skeleton for the game.</dd>
      <dt><samp>memory.css</samp></dt>
         <dd>Your CSS styles for the game.</dd>
      <dt><samp>memory.js</samp></dt>
         <dd>Your JavaScript code for the game.</dd>
   </dl>
   
   <p class="note important" style="clear: left">Your file names must match these <em>exactly</em> — with precisely the same capitalization and spacing.</p>
   
   <p>(If you have any additional files that are part of your design for the page, you’ll be able to submit them as well.)</p>
   
   
   <?= subhead("Content &amp; Resources") ?>
   
   <p>You are provided with the following three skeleton files, containing some basic code to start you off:</p>
   
   <p class="resource"><a href="memory.html">memory.html</a></p>
   <p class="resource"><a href="memory.css">memory.css</a></p>
   <p class="resource"><a href="memory.js">memory.js</a></p>
   
   <p>The HTML skeleton file requires almost no modification; the only change you should make is to include additional CSS or JavaScript files if needed — for example, if you want to include the jQuery UI library or a CSS3 web font.</p>
   
   <p>The CSS and JavaScript files contain some basic components to get you started. To these files you will add whatever code necessary to complete the assignment.</p>
   
</section>

<section>
   <?= head("Page Layout &amp; Behavior") ?>
   
   <p>When completed, your page will look as follows:</p>
   
   <figure id="expected-output" class="expectedoutput">
      <a href="output/hw4_expected_output_initial_ff15_lion.png">
         <img src="output/hw4_expected_output_initial_ff15_lion.png" alt="Expected output when the page is loaded." />
      </a>
      <figcaption>Expected output when the page is loaded.</figcaption>
   </figure>
   
   <figure class="example">
      <a href="output/hw4_expected_output_gameplay_ff15_lion.png">
         <img src="output/hw4_expected_output_gameplay_ff15_lion.png" alt="During gameplay." />
      </a>
      <figcaption>During gameplay.</figcaption>
   </figure>
   
   <p>The cards are placed face-down in a 6 × 3 grid. When clicked, a card “flips” in an animated motion to reveal its front side.</p>
   
   <p>When a second card is clicked, if it matches the first card, the two will be removed from the page. If it doesn’t match, the two are flipped back over.</p>
   
   <p>Each card is <strong>150 pixels</strong> square, with <strong>25 pixels</strong> of space between each row and column — meaning the cards will be placed in multiples of <strong>175 pixels</strong>. (A <code>.card</code> class in the provided CSS file defines its width and height.)</p>
   
   <p>There is a div called <code>#board</code> which acts as the container for your cards. As defined in the provided CSS, it is 1025 pixels wide (= six 150px cards + five 25px spaces), 500 pixels tall <span style="white-space: nowrap">(= three</span> 150px cards + two 25px spaces), and centered horizontally on the page.</p>
   
   
   <?= subhead("Creating the Cards") ?>
   
   <p>Each “card” actually consists of three components:</p>
   
   <ul>
      <li>A “front face” image, which is the image revealed when flipped.</li>
      <li>A “back face” image, which is the uniform texture all backs show when cards are face down.</li>
      <li>A div containing both images.</li>
   </ul>
   
   <p>The HTML for these cards, if it were to be written directly into the HTML file, would look as follows:</p>
   
<pre><code>&lt;div class=&quot;card&quot;&gt;
&lt;img class=&quot;front&quot; src=&quot;<var>front image filename</var>&quot; alt=&quot;<var>description</var>&quot; /&gt;
&lt;img class=&quot;back&quot; src=&quot;<var>back texture filename</var>&quot; alt=&quot;<var>description</var>&quot; /&gt;
&lt;/div&gt;</code></pre>
   
   <p>However, these cards will actually be generated dynamically by your JavaScript code when the page loads. Your cards should use the same (or similar) classes as above.</p>
   
   <p class="note"><em style="font-family: 'Droid Sans'; font-style: normal; color: red">You are not allowed to edit the HTML file to add these cards; they must be generated by your JavaScript code.</em></p>
   
   <p class="note"><strong>Tip:</strong> For debugging and testing, you may find it helpful to make the <code>.back</code> face translucent using the <code>opacity</code> property so you can see the <code>.front</code> face through it.</p>
   
   
   <?= subhead("Placing the Cards Randomly") ?>
   
   <p>The provided JavaScript code contains a nested for-loop which creates a list of available spaces as soon as the script loads. These spaces are represented by JavaScript objects indicating a row and column in the grid.</p>
   
   <p>After the nested for-loop has run, the global variable <code>SPACES</code> is a list of objects as follows:</p>
   
<pre><code>[
{ col: 0, row: 0 }, { col: 0, row: 1 }, { col: 0, row: 2 },
{ col: 1, row: 0 }, { col: 1, row: 1 }, { col: 1, row: 2 },
{ col: 2, row: 0 }, { col: 2, row: 1 }, { col: 2, row: 2 },
...
]</code></pre>
   
   <p>When choosing a space for a card, you should randomly select one of these, place the card at the location indicated, and then remove that space from the <code>SPACES</code> list so that it isn’t chosen again for placement.</p>
   
   <p class="note">Arrays have a <a href="http://www.w3schools.com/jsref/jsref_splice.asp"><code>.splice()</code></a> function which can be used to remove an element from that array.</p>
   
   <p>This <code>SPACES</code> global is an array like any other, and the objects inside it can be used like normal objects:</p>
   
<pre><code>var spc = SPACES[Math.floor(Math.random() * SPACES.length)];
alert('Randomly selected space at row=' + spc.row + ', col=' + spc.col);</code></pre>
   
   <p>Once you’ve selected a random space, you’ll need to use its <code>.row</code> and <code>.col</code> values to <strong>calculate a pixel position</strong>, and place your <code>.card</code> at that pixel position using CSS.</p>
   
   
   <?= subhead("The Flipping Effect", array('modified' => true)) ?>
   
   <figure class="example" style="margin-top: -4em;">
      <a href="output/hw4_expected_output_nonmatch_ff15_lion.png">
         <img src="output/hw4_expected_output_nonmatch_ff15_lion.png" alt="Cards in the process of flipping." />
      </a>
      <figcaption>Cards in the process of flipping.</figcaption>
   </figure>
   
   <p>To create the flipping effect, we do the following:</p>
   
   <style type="text/css">
      #already-does:before {
         margin-top: 1em;
      }
   </style>
   
   <ul>
      <li>Position the <code>.front</code> and <code>.back</code> images absolutely, but don’t specify a location. This causes the images to appear in the same place, with one overlapping the other. <ins id="already-does" datetime="Wed, Oct 24, 9:30 PM">(The provided CSS code already does this in a <code>.card img</code> rule.)</ins></li>
      <li>Reflect the <code>.front</code> image (the photo, which we want to be face down initially) 180 degrees on the Y axis. (If you imagine the front of a real card when it’s face down, it’s flipped with respect to the back face.)</li>
      <li>When we turn, we turn the whole <code>.card</code> on the Y axis, and the images inside turn with it. (So the <code>.front</code> turns to become visible, and the <code>.back</code> turns to become hidden, or vice versa.)</li>
   </ul>
   
   <p>In order to cause the front and back faces to be revealed or hidden when flipped, we need to set a property of the images:</p>
   
<pre><code>.card img {
backface-visibility: hidden;
}</code></pre>
   
   <p>Normally when you flip an image, you see the image mirrored. Setting backface visibility to hidden causes the image to become invisible when turned away. This is allows the side that becomes turned toward us to be seen instead.</p>
   
   <p>There’s one more property we need to set for things to come out right:</p>
   
<pre><code>.card {
transform-style: preserve-3d;
}</code></pre>
   
   <p>Without this, the card faces won’t retain their correct orientation in three dimensions.</p>
   
   <p>See the additional slides in the <a href="../../lectures/special-effects/">Lecture 8</a> deck for more information and examples of how <code>backface-visibility</code> and <code>transform-style</code> work.</p>
   
   <div class="note">
      <p><em style="font-family: 'Droid Sans'; color: red; font-style: normal;"><del>You <strong>ARE NOT</strong> required to browser-prefix your CSS3 transitions and transforms for this assignment.</del></em></p>
      <ins datetime="Fri, Oct 26, 11:15 PM"><p>Firefox 16 is apparently the first version of Firefox to not require the <code>-moz-</code> prefix for the CSS3 effects. If you’re using Firefox 15, you’ll need to prefix your CSS3 transitions &amp; transforms. However, you’re not required to include prefixes for other browsers.</p></ins>
   </div>
   
   <?= subhead("Finding a Match", array('modified' => true)) ?>
   
   <p>When the player clicks the first card to reveal it, you will need to keep track of which card they clicked, so that you can compare it to the second card.</p>
   
   <p>The best way to do this is to store the first card in a global variable, then compare its <code>.front</code> face to the <code>.front</code> face of the second card when it is clicked. If the URLs of the two images are the same, then they are the same card and they can be removed; <ins datetime="Fri, Oct 26, 7:30 PM">if not, they’ll need to be flipped back over.</ins></p>
   
   <p>In order to compare the two images, you may find it helpful to make use of the jQuery <code>.children()</code> function:</p>
   
   <pre><code>$('#foo').children('.bar');</code></pre>
   
   <p>This example selects children of <code>#foo</code> having the class of <code>bar</code>.</p>
   
   <p><ins datetime="Fri, Oct 26, 7:45 PM">If you compare the source images <em>immediately</em> when clicked, the second card won’t have time to flip before both of them will be told to flip back again. (This will have the appearance of causing the first card to flip back when the second is clicked.)</ins></p>
   
   <p><ins>So you’ll need to allow the second card time to flip before flipping the cards back or removing them. To do this, you should <strong>delay</strong> any code that flips the cards back (or removes them) until after the second flip has had time to complete. (You may even want to wait a bit after the card has finished flipping, just to let the user see that they have or have not found a match.)</ins></p>
   
   
   <?= subhead("Removing a Card") ?>
   
   <figure class="example" style="margin-top: -3em">
      <a href="output/hw4_expected_output_match_ff15_lion.png">
         <img src="output/hw4_expected_output_match_ff15_lion.png" alt="Cards in the process of being removed." />
      </a>
      <figcaption>Cards in the process of being removed.</figcaption>
   </figure>
   
   <p>When two cards match, their disappearance should be animated using a jQuery or jQuery UI effect of your choice. <em style="font-style: normal; color: red">When this animation is finished, the cards should be removed completely from the DOM.</em></p>
   
   
   <?= subhead("Customizing &amp; Improving the Game (Optional)") ?>
   
   <p>The skeleton JavaScript file contains two global variables for images:</p>
   
   <dl>
      <dt><code>BACK_IMAGE</code></dt>
         <dd>The URL of the image to use for the back texture.</dd>
      <dt><code>FRONT_IMAGES</code></dt>
         <dd>An object containing URLs and alt descriptions of the front-side images.</dd>
   </dl>
   
   <p>These can be customized with your own images. Since there are 18 spaces on the page, you’ll need exactly 9 front images. All images should be <strong>square</strong> so that the tiles are evenly spaced on the page. Please link all images <strong>absolutely</strong>, with the full URL.</p>
   
   <p class="note"><strong>Tip:</strong> Instagram is a great source for square images with contrast and framing that work well for this game; if you have an account, images can be browsed on the web via a third-party service like <a href="http://statigr.am/">Statigram</a>, <a href="http://web.stagram.com/">Webstagram</a>, or <a href="http://extragr.am/">Extragram</a>.</p>
   
   <p>You are also welcome to customize the CSS and behavior of the page as you like. Some examples of possible enhancements:</p>
   
   <ul>
      <li>Change the font and colors on the page to go with your custom back face texture.</li>
      <li>Position cards more sporadically on the page, within the grid but with random “wiggle room” and a slight tilt so they look more like cards placed by a human.</li>
      <li>Currently if you click a tile while others are being removed, the third tile might also be removed. Also, if you click on the same tile twice, it may match itself and be removed. Prevent such buggy behavior.</li>
      <li>
         <p>Make the number of spaces dynamically adjust to the size of the screen, so that when the window is very large there will be more tiles.</p>
         
         <p>Since there will be a variable number of spaces available, if you do this you’ll either need more images in <code>FRONT_IMAGES</code>, or you’ll need to reuse existing images (possibly adding more than one pair). Or both.</p>
      </li>
      <li>
         <p>Make the cards appear on screen in an animated fashion — for example, all originating from the same place and moving to their final destination.</p>
         <p>If you’d like cards to be positioned in sequence (as if being dealt) rather than fanning out all at once, consider using <code>setTimeout</code> or <code>setInterval</code> to iterate through the creation or placement of cards with a short time gap between each placement.</p>
         </li>
   </ul>
</section>

<section><ins datetime="Fri, Oct 26, 7:30 PM">
   <?= head("Development Strategy", array('modified' => true)) ?>
   
   <p>Breaking down this assignment into steps may be difficult. We suggest tackling the problem in this order:</p>
   
   <ol>
      <li>Begin by creating a single card with <strong>the front image only</strong>, and inject it into the page.</li>
      <li>Next, experiment with changing that card’s location. If you know you want to put it in a certain row and column, how do you place it there? (Last week’s <a href="../../minilabs/6/">Mini-lab 6</a> and <a href="../../minilabs/7/">Mini-lab 7</a> did a lot of placing things.)</li>
      <li>Now, get a random space from the <code>SPACES</code> array. Place the card at the location indicated by that space’s <code>.row</code> and <code>.col</code> properties.</li>
      <li>Put your card creation and placement stuff into a loop, so that you create a card for every image in <code>FRONT_IMAGES</code>.</li>
      <li>Now make your loop create two of each card instead of just one. Your board should now be filled.</li>
      <li>At this point you can address animation:
         <ol>
            <li>Start by making the front image be flipped initially, as specified in <a href="#the-flipping-effect">The Flipping Effect</a>. (The images should show up as mirror images of the way they were before.)</li>
            <li>Then make the <em>card</em> (not the image itself) flip when clicked.</li>
            <li>Now add the back image, and the <code>backface-visibility</code> and <code>transform-style</code> properties as specified in <a href="#the-flipping-effect">The Flipping Effect</a>. Your cards should now flip from back to front when clicked.</li>
         </ol>
      </li>
      <li>Finally, make it so that when you click one image, and then click another image, it compares the <code>src</code> attributes of the <code>front</code> images in the two cards clicked. If they match, remove them from the page; if not, flip them back over. (Remember to account for the flipping time, as discussed in <a href="#finding-a-match">Finding a Match</a>.)</li>
      <li>Do a stylistic audit of your code: Add comments, clean up variables, simplify and reorder things, eliminate redundancy, validate, test, and upload.</li>
      <li>Turn it in and go work on your Halloween costume.</li>
   </ol>
</ins></section>


<section>
   <?= head("Stylistic Considerations") ?>
   
   <p>You will be graded in part on certain choices you make in writing the code for your pages. Keep the following in mind:</p>
   
   <ul>
      <li>
         <p><strong>Make good tag choices.</strong> Use the most appropriate HTML tags available to describe each piece of content. Be careful not to choose tags based on the appearance you want the content to have; rather, choose tags based on how well they describe the content or structure of the page. You can always use CSS to alter the appearance if it isn’t right.</p>
      </li>
      
      <li><strong>Reduce redundancy.</strong> Sometimes you may have styles that are shared by multiple elements. Whenever it makes your code more logically-structured, you should combine redundant style declarations into a single rule.</li>
      
      <li><strong>Properly format your code.</strong> Use consistent indentation that makes the structure of your code easy to follow. In general, you should usually indent inside block-level elements in your HTML, and in your CSS code you should indent consistently inside curly braces. Wrap comments to no more than 100 characters on a line. Don’t worry about wrapping long HTML opening tags, but you may want to indent the content inside an element if its opening tag is long — even if it’s an inline element. (<strong>Never</strong> add a line break inside of a URL!)</li>
      
      <li>
         <p><strong>Include proper comments.</strong> All files submitted should begin with an authorship comment with information to identify the work: the course, date, assignment, your name and section, and a brief description to the file are all standard things to include.</p>
         
         <p class="important note">
            <strong>Remember to use the right comment syntax!</strong><br/>
            HTML comments look <code>&lt;!-- like this ---&gt;</code>, CSS comments look <code>/*&nbsp;like&nbsp;this&nbsp;*/</code>, and JavaScript comments can be either <code>/*&nbsp;like&nbsp;this&nbsp;*/</code> or <code>//&nbsp;like&nbsp;this</code>.
         </p>
         
         <p>These should be at the top of <strong>every file</strong>.</p>
         
         <p>You don’t need to comment on sections of your HTML or CSS code — however, in your JavaScript code you are required to comment on function behavior (parameters, return value, purpose) as well as “milestones” at significant passages of your JavaScript code, as you did in CSE 142.</p>
      </li>
      
      <li><strong>Validate your code.</strong> For full credit, your code should pass the W3C validators with no errors. (Yellow warnings can safely be ignored.) Write valid XHTML 1.1 or HTML5 and CSS 2.1 or CSS 3 code.</li>
   </ul>
</section>

<section>
   <?= head("Grading") ?>
   
   <p>The point breakdown for this assignment will be roughly as follows:</p>
   
   <style type="text/css">
      dl.breakdown {
         margin-left: 1em;
      }
      
      dl.breakdown dt {
         float: left;
         clear: left;
         width: 6em;
      }
      
      dl.breakdown dd {
         margin-left: 6em;
         margin-bottom: .5em;
         width: 11em;
      }
      
      dl.breakdown .total {
         border-top: solid 4px black;
         font-weight: bold;
         padding-top: .5em;
      }
   </style>
   
   <dl class="breakdown">
      <dt>~ 8 points</dt>
      <dd>Card placement and game logic</dd>
      <dt>~ 7 points</dt>
      <dd>Special effects</dd>
      <dt>~ 5 points</dt>
      <dd>Stylistic and other considerations</dd>
      <dt class="total">20 points</dt>
      <dd class="total">Total</dd>
   </dl>
   
   <p><small style="font-style: italic; font-family: 'Open Sans'">The exact point value for each category is subject to change ± 2 points.</small></p>
</section>

<section>
   <?= head("Submitting Your Assignment") ?>
   
   <p>When you are finished with your assignment you are required to do <strong>both</strong> of the following:</p>
   
   <ol>
      <li>
         <p><strong>Upload your files to the course web server.</strong> Put them in a folder named <em>exactly</em> <samp>hw4</samp> inside your <samp>public_html</samp> web directory on our web server (<samp>info343.ischool.uw.edu</samp>).</p>
         <p class="important note">The folder you put your homework files in must match this exactly — including capitalization and spacing! You may lose points if your files are not named <em>exactly</em> as specified in this document.</p>
      </li>
      <li><p><strong>Submit your assignment via the drop box</strong> on the course website.</p></li>
   </ol>
   
   <p>You must do <strong>both</strong> of these to get full credit. You may submit your assignment as many times as you like; only the last submission will count. Please remember to upload to the web server <strong>exactly</strong> the same version that you submit to the drop box.</p>
   
   <p>This assignment will not be accepted by any other means of submission without permission by the instructor or a TA.</p>
</section>