<p>This will be mostly just caveats and things to think about. </p>

<p>One problem you will have is that the original code and some other versions are all online as open source. It will be hard to keep your students "in the dark" so that they can grow themselves (mushroom principle of education, I guess). </p>

<p>Second, for a 4 by 4 square array, the standard array operations (scanning, collecting, ...) using loops are a bit inefficient. For example, your rotate method for an array can be done with about 20 assignments, just keeping track of subscripts. That might be a very valuable exercise in itself, of course. But loop overhead in such a small array starts to overwhelm the operations. </p>

<p>Third, I haven't thought in detail about this yet, but you might want to consider a program that uses more space than the minimum, keeping, for example, two versions of the matrix simultaneously, with one rotated 90 degrees from the other. This will achieve adjacency of both rows (in one copy) and columns (in the other). </p>

<p>An object based version might also be possible, so that the "cells" of the matrix can be simultaneously row and column adjacent. This might move some of the logic into those cell objects as well. </p>

CC BY-SA 4.0
2018-10-17T19:01:15.297Z
Thanks Buffy, The rotation solution is particularly inefficient. However, in this case the problem size is small and is a don't care because it need only be fast enough for the human player not to be kept waiting. . Premature optimization is rarely a good thing. - Fritz
Fritz Sieker
CC BY-SA 4.0
2018-10-17T21:01:08.090Z
I actually encourage students to look on line for help and/or solutions. I  ask only that they cite the link where they found the code. And, in doing so, that they  assume responsibility for the code. Tough luck if it doesn't work. I also tend to introduce some structure not found in the online solutions so that students must, at least, adapt what they find to the requirements.
Fritz Sieker
CC BY-SA 4.0
2018-10-17T22:44:43.500Z
Actually, I wasn't optimizing. I just think that brute force assignment is the _simplest_ solution here.
Buffy
CC BY-SA 4.0
2018-10-17T00:06:57.243Z
2018-10-17T00:06:57.243Z
Buffy
<p>First of all, it seems like rather nice bones of a 2-dimensional array lab. It does not strike me as being too many things at all.</p>

<ol>
<li><p>The interface is cleaner with <code>move(direction)</code>, but the internal logic is cleaner divided into methods.  Why not the best of both words?  Provide them with starter code that will utilize private methods:</p>

<pre><code>public void move(direction){
  switch(direction){
    case UP:
       slideUp();
    case DOWN:
       slideDown();
   case LEFT:
       slideLeft();
   case RIGHT:
       slideRight();
  }
}
</code></pre></li>
<li><p>That is another way, also valid.</p></li>
<li><p>It seems excessively finicky to require implementation details down to this level.</p></li>
<li><p>Once again, I would provide the interface, but not these sorts of implementation details.  You can provide both ways as suggestions, but leave it up to them.  They may also choose a third option that you have not mentioned.</p></li>
<li><p>This fits very nicely if you are providing some sort of GUI starter code, which would justify an implementation detail like this one.</p></li>
</ol>

CC BY-SA 4.0
2018-10-24T01:53:31.540Z
I think having 4 public `move` methods is cleaner than using a single one with a string parameter. At least use an `Enum`!
Solomon Ucko
CC BY-SA 4.0
2018-10-24T12:45:12.387Z
@SolomonUcko I don't agree about the cleanliness in the public facing methods, though I am referencing private methods, so we're not far off there. I absolutely agree about the Enum. Thanks for pointing that out! Fixed that, and I also noticed when I went in that my code wasn't formatting.  Apparently we now need 8 spaces to start a code block??  In any case, that's fixed now, too.
Ben I.
CC BY-SA 4.0
2018-10-24T13:26:30.357Z
I'd say that using an `Enum` parameter is better than using multiple methods, which is better than using a `String`. Sorry for the tone of my previous comment, I was in a bit of a hurry.
Solomon Ucko
CC BY-SA 4.0
2018-10-16T17:07:37.117Z
2018-10-24T12:44:18.857Z
2018-10-24T12:44:18.857Z
Ben I.
<p>I'm thinking about an assignment based around the game 2048. This would be towards the end of a <em>first</em> programming course at the <em>university</em> level and assumes the students have been introduced to at least two dimensional arrays, loops, conditionals and methods. The purpose is to have the students practice these skills.</p>

<p>I would represent the <code>board</code> as a two dimensional array of <code>int</code>.</p>

<p>I would require a method (e.g. <code>merge(int[] row)</code>) which does the work on an individual row of the puzzle when the move is to slide left. The idea is to encapsulate the work of a slide in a single, testable method. <em>This also emphasizes that a two dimensional array is an array of array, and that one can work on a single row at a time.</em></p>

<p>What are your opinions on the following ideas:</p>

<ol>
<li><p>Should a single move in the game be implemented as (<code>move(direction)</code>) or as individual methods (<code>up() down() left() right()</code>)?</p></li>
<li><p>One idea for completing the game involves rotating the board by multiples of 90 degrees. Then a move can be implemented as a three step process:</p>

<ol>
<li>Rotate board to one orientation</li>
<li>Slide all rows left (<code>merge(board[row])</code> for each <code>row</code></li>
<li>Rotate board back to original orientation</li>
</ol></li>
<li><p>Another idea is to show them that move right can be implemented by the process</p>

<ol>
<li>reverse a row</li>
<li>slide it left (<code>merge(board[row]</code>)</li>
<li>reverse the row again</li>
<li>For columns, copy the values from a column into a one dimensional temp array, then perform the <code>merge(temp)</code> and then copy back to the board. This may also require reverses, depending on the up/down selection.</li>
</ol></li>
<li><p>Require a method to produce a list of empty cells for use in picking the location of the next "insertion". This could be a list of <code>int</code> to demonstrate how a single index can map to a row/col using <code>div</code> and <code>mod</code> operations. Alternatively, it could be a list of <code>pairs</code> of row/column.</p></li>
<li><p>The last wrinkle is to decide what to actually stored in each board location. The simple answer is just the value. However, an interesting variation might be to store the <code>log2</code> of the value. By doing this, you get an index that can be used to select, for example, the background color of each square of the board. This changes the logic of <code>merge()</code>, so that
combining adjacent cells ups the value by 1, rather than adding two values together.</p></li>
</ol>

<p>Am I trying to put too many different concepts into this assignment? Your opinions and suggestions are appreciated.</p>

<p>Thanks</p>

CC BY-SA 4.0
2018-10-18T01:05:27.400Z
About #5: $0{\text{ }}log_{2} = \infty$, while $0=1{\text{ }}log_{2}$, so there ends up being some kind of special test for the empty square value or the stored value of zero. The conditionals around that problem makes it likely that choosing color based on cell value would be just as fast, and less error-prone.
Gypsy Spellweaver
CC BY-SA 4.0
2018-10-18T18:45:47.903Z
Yes your are correct, the empty cell being 0 is a special case, but as an index works very nicely.  I would hope that the students would see that `array[cellValue]` is cleaner than a `switch` on the the `cellValue` with all the possible cases (`2 4 8 15 ...`). Perhaps you are correct that the students would be more comfortable with the `switch` approach. I had thought of this an a way to demonstrate allocating an `arrray` of constant values.
Fritz Sieker
<java><undergraduate><project><algorithms><data-structure>
Project based on game 2048
# Project based on game 2048

(Asked by: username_0 on 2018-10-15)

I'm thinking about an assignment based around the game 2048. This would be towards the end of a *first* programming course at the *university* level and assumes the students have been introduced to at least two dimensional arrays, loops, conditionals and methods. The purpose is to have the students practice these skills.

I would represent the `board` as a two dimensional array of `int`.

I would require a method (e.g. `merge(int[] row)`) which does the work on an individual row of the puzzle when the move is to slide left. The idea is to encapsulate the work of a slide in a single, testable method. *This also emphasizes that a two dimensional array is an array of array, and that one can work on a single row at a time.*

What are your opinions on the following ideas:

1. Should a single move in the game be implemented as (`move(direction)`) or as individual methods (`up() down() left() right()`)?
2. One idea for completing the game involves rotating the board by multiples of 90 degrees. Then a move can be implemented as a three step process:

   1. Rotate board to one orientation
   2. Slide all rows left (`merge(board[row])` for each `row`
   3. Rotate board back to original orientation
3. Another idea is to show them that move right can be implemented by the process

   1. reverse a row
   2. slide it left (`merge(board[row]`)
   3. reverse the row again
   4. For columns, copy the values from a column into a one dimensional temp array, then perform the `merge(temp)` and then copy back to the board. This may also require reverses, depending on the up/down selection.
4. Require a method to produce a list of empty cells for use in picking the location of the next "insertion". This could be a list of `int` to demonstrate how a single index can map to a row/col using `div` and `mod` operations. Alternatively, it could be a list of `pairs` of row/column.
5. The last wrinkle is to decide what to actually stored in each board location. The simple answer is just the value. However, an interesting variation might be to store the `log2` of the value. By doing this, you get an index that can be used to select, for example, the background color of each square of the board. This changes the logic of `merge()`, so that
   combining adjacent cells ups the value by 1, rather than adding two values together.

Am I trying to put too many different concepts into this assignment? Your opinions and suggestions are appreciated.

Thanks

**Tags:** java, undergraduate, project, algorithms, data-structure

> **Comments:**
> **username_1**: About #5: $0{\text{ }}log_{2} = \infty$, while $0=1{\text{ }}log_{2}$, so there ends up being some kind of special test for the empty square value or the stored value of zero. The conditionals around that problem makes it likely that choosing color based on cell value would be just as fast, and less error-prone.  
> **username_0**: Yes your are correct, the empty cell being 0 is a special case, but as an index works very nicely.  I would hope that the students would see that `array[cellValue]` is cleaner than a `switch` on the the `cellValue` with all the possible cases (`2 4 8 15 ...`). Perhaps you are correct that the students would be more comfortable with the `switch` approach. I had thought of this an a way to demonstrate allocating an `arrray` of constant values.  

---

## 2 answers

### Answer by username_3 on 2018-10-16. Score: 1

First of all, it seems like rather nice bones of a 2-dimensional array lab. It does not strike me as being too many things at all.

The interface is cleaner with move(direction), but the internal logic is cleaner divided into methods.  Why not the best of both words?  Provide them with starter code that will utilize private methods:
public void move(direction){
  switch(direction){
    case UP:
       slideUp();
    case DOWN:
       slideDown();
   case LEFT:
       slideLeft();
   case RIGHT:
       slideRight();
  }
}

That is another way, also valid.
It seems excessively finicky to require implementation details down to this level.
Once again, I would provide the interface, but not these sorts of implementation details.  You can provide both ways as suggestions, but leave it up to them.  They may also choose a third option that you have not mentioned.
This fits very nicely if you are providing some sort of GUI starter code, which would justify an implementation detail like this one.

> **Comments:**
> **username_4**: I think having 4 public `move` methods is cleaner than using a single one with a string parameter. At least use an `Enum`!  
> **username_3**: @SolomonUcko I don't agree about the cleanliness in the public facing methods, though I am referencing private methods, so we're not far off there. I absolutely agree about the Enum. Thanks for pointing that out! Fixed that, and I also noticed when I went in that my code wasn't formatting.  Apparently we now need 8 spaces to start a code block??  In any case, that's fixed now, too.  
> **username_4**: I'd say that using an `Enum` parameter is better than using multiple methods, which is better than using a `String`. Sorry for the tone of my previous comment, I was in a bit of a hurry.  

---

### Answer by username_2 on 2018-10-17. Score: 0

This will be mostly just caveats and things to think about.

One problem you will have is that the original code and some other versions are all online as open source. It will be hard to keep your students "in the dark" so that they can grow themselves (mushroom principle of education, I guess).

Second, for a 4 by 4 square array, the standard array operations (scanning, collecting, ...) using loops are a bit inefficient. For example, your rotate method for an array can be done with about 20 assignments, just keeping track of subscripts. That might be a very valuable exercise in itself, of course. But loop overhead in such a small array starts to overwhelm the operations.

Third, I haven't thought in detail about this yet, but you might want to consider a program that uses more space than the minimum, keeping, for example, two versions of the matrix simultaneously, with one rotated 90 degrees from the other. This will achieve adjacency of both rows (in one copy) and columns (in the other).

An object based version might also be possible, so that the "cells" of the matrix can be simultaneously row and column adjacent. This might move some of the logic into those cell objects as well.

> **Comments:**
> **username_0**: Thanks username_2, The rotation solution is particularly inefficient. However, in this case the problem size is small and is a don't care because it need only be fast enough for the human player not to be kept waiting. . Premature optimization is rarely a good thing. - Fritz  
> **username_0**: I actually encourage students to look on line for help and/or solutions. I  ask only that they cite the link where they found the code. And, in doing so, that they  assume responsibility for the code. Tough luck if it doesn't work. I also tend to introduce some structure not found in the online solutions so that students must, at least, adapt what they find to the requirements.  
> **username_2**: Actually, I wasn't optimizing. I just think that brute force assignment is the _simplest_ solution here.  

---

