From 47d2bc9d639289fa6a5cc573246305a57c1028e1 Mon Sep 17 00:00:00 2001
From: "Peter J. Keleher" <keleher@cs.umd.edu>
Date: Tue, 10 Mar 2020 14:05:27 -0400
Subject: [PATCH] auto

---
 assign3.md | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 262 insertions(+)
 create mode 100644 assign3.md

diff --git a/assign3.md b/assign3.md
new file mode 100644
index 0000000..668295a
--- /dev/null
+++ b/assign3.md
@@ -0,0 +1,262 @@
+# Assignment 3: Fancy Triples
+**Due: Mar 29, 2020, 11:59:59 pm, v1**
+
+
+## Goals
+Learn to use:
+- property animation
+- custom views
+- drawing
+- gestures
+- tab bar view controllers
+- user defaults
+- dynamic animations
+
+![](https://sedna.cs.umd.edu/436clips/assign3.mp4)
+
+This is the project where we end up with a real game we can give out
+to friends and family. We are not significantly changing core
+functionality, but we are adding many of the extras that make apps usable.
+
+## Before you begin
+
+This project is based on the last one, but copying Xcode projects is a
+dicy, multiple-step project, easy to mess up.
+
+Instead, I suggest you create a new project `assign3` in your repository, no need for either unit or UI tests. Create
+a new `model.swift`, and then copy and paste
+whichever portions of your model and `ViewController` code you want to keep (probably a lot
+of it).
+
+**Note:** create your new project **assign2** directly in your repository, so the resulting directory
+structure should look like this:
+```
+                        repository
+            /                        \
+          /              |             \
+        /                |               \
+      /                  |                 \
+  assign1            assign2                 assign3
+  /    \            /       \                 /      \
+               assign2/   assign2.x...    assign3/   assign3.xcodeproj/
+             /       \                       /                 \
+        model.swift  ...
+```
+
+Run this version to ensure everything is working correctly, quit out of Xcode, `git add
+assign3`, and then push to your repository. Note that if you create more files, you need
+to manually add them as well. Easiest to just do a `git add *` in any affected
+subdirectories. 
+
+We realize that `git` is sometimes a challenging, non-intuitive tool, especially as we are
+not using Xcode's GUI interface, but understanding git will serve you well in almost any
+facet of the tech world going forward.
+
+## Task 1: Change your storyboard.
+Throw away your statically defined "tile" Buttons. You are going to
+programmatically create
+"tiles" on the fly to match your game model.
+
+The storyboard will have the following elements:
+- a `view` to use as your square board (add a constraint to ensure that it stays square)
+- a stack of controls, including:
+  - left, right, up, down buttons
+  - newgame
+  - segmented random/determ control
+  - score label
+
+Put the view and the control stack into another stack (the top-level stack), add constraints as I
+did in class to:
+- pull the top-level stack's leading and trailing edges to 10 points off safe
+  area, center it vertically
+- ensure that the square board is as large as possible (pin leading and
+  trailing edges to it's superview
+
+### Adapt to Orientation changes
+Introduce two variations to allow your storyboard to adapt smoothly to
+landscape mode and back again:
+- Introduce a *horizontal* variant to the top-level stack for *compact height*
+- Put the storyboard in horizontal mode, click on "Vary for Traits", and get
+  rid of some constraints that no longer apply in horizontal mode (don't need
+  to pin leading and trailing edges of top-level stack to edges, etc.), and
+  add new ones (pin top and bottom of top-level stack to edges, etc.)
+- Click done varying, go back to vertical mode, and click "Done Varying".
+
+You cannot run at this point because your `IBOutlet`s refer to non-existent views.
+
+
+## Task 2: Change the model
+
+Your model is conceptually unchanged. However, the view controller is
+now going to animate tile movement, and therefore needs to recognize
+specific tiles in order to identify tile movements.
+
+We are therefore going to change our board's base type from `Int` to a
+new struct `Tile`.
+`Tile`s will have a unique *id*, and  therefore be identifiable even
+as their value (the number) changes. Define `Tile` as follows:
+```
+     struct Tile {
+         var val : Int
+         var id : Int
+         var row: Int    // recommended
+         var col: Int    // recommended
+     }
+```
+
+Your model's `board` will change from `[[Int]]` to  `[[Tile?]]`. Note the
+optional base type; each cell of your board will consist of either a `Tile`
+or a `nil`.
+
+You might want to include `row` and `col` properties to make drawing on the
+board a bit easier. Be sure to update these properties before returning to the
+view controller after a collapse, spawn, or newgame.
+
+**Hint:** If a row has the following tiles and we are collapsing left:
+```
+   (val: 1, id: 13), (val:2, id:14), nil, nil
+```
+you probably want to have tile 13 disappear, while tile 14 moves to the
+left. This makes animation more straightforward.
+
+
+## Implement TileButtons programmatically
+Your `updateViewForGame` (substitute whatever name you use) needs to ensure
+that there are buttons on top of the *board* (`viewOutlet` you've attached to
+the square view you put on the storyboard) for each current tile. This
+involves:
+- create buttons for each newly-seen tile and adding as a *subview* to the
+  `board` at the correct location
+- moving the `frame` for each tile that we've already seen
+- removing buttons for any tiles that we had seen before but are no longer in
+  the model
+
+Before you get started, you should create a new subclass `ButtonTile`:
+```
+class ButtonTile: UIButton {
+    var tile = Tile(val: 0, id: 0, row: 0, col: 0)
+
+    convenience init(t: Tile) {
+        self.init()
+        tile = t
+    }
+```
+where you have defined `Tile` in your new model. You can use a `ButtonTile`
+just like a `UIButton`, but it has the `Tile` information readily at hand
+(crucial for implementing animation via a custom view later).
+
+Your code will be able to recognize tiles from previous steps in the
+application because each tile will have a unique `ID`.
+
+At the end of this step you should have a fully functional game again. It
+should adapt well to the orientation changes *except* that existing TileButtons
+might have the wrong size and position until a subsequent swipe.
+
+**Hint:** You should create a method `func buttonFrame(row: Int, col: Int,
+view: UIView) -> CGRect` 
+that will compute the frame for a `ButtonTile`, based on `view` and the fact
+that your game board will always have four rows of four possible positions.
+
+**Hint:** adding a button to `board` can be done w/ the following code:
+```
+                let button = ButtonTile(t: tileMap[id]!)
+                board.addSubview(button)
+```
+Later on it can be removed via `tileButton.removeFromSuperView()`
+
+**Save early and often by pushing to your repository.**
+
+## Task 3: Custom View
+At this point we want to build a custom view for our board, and have
+`ButtonTile` operate independently of the view controller.
+
+- Subclass `UIView` with a custom `BoardView` by create a new Cocoa Touch
+  file.
+- Move `buttonFrame` your new `BoardView` class.
+- `override func draw(_ rect: CGRect)` to draw the board lines any way you
+  wish, though you must use `UIBezierPath`.
+- `override func layoutSubviews()` to get lay out your buttons in the correct
+  location.
+  
+`draw` is called by iOS whenever a previously unseen portion of the board gets
+seen. Use this just to draw the board's background lines.
+
+`layoutSubviews` is the majority of this task. It is called whenever iOS think
+there might have been a change in layout (at app startup, orientation changes,
+and other seemingly random times).
+
+Your job is to make put each button in it's proper place, set the titles,
+colors, etc. Views should not access view controllers' data directly. Instead make this
+routine entirely standalone, deriving all information by querying its own
+`subviews` property. 
+
+`subviews` is an array of all child view, which in this case is only those
+buttons that the view controller has put on the board. But how to figure out
+where to situate the buttons, and how to figure out color and text of each?
+
+Luckily, these "buttons" are actually `ButtonTile`s. Cast each `UIView` to a
+`ButtonTile` and you now have access to the complete `Tile` associated with
+each button.
+
+The view controller's `updateViewFromGame()` method is now quite short. It has
+to:
+- add `ButtonTile`s to the board if the model has a previously-unseen `Tile`.
+- remove `ButtonTile`s from the board if a previously-unseen `Tile` no longer
+  exists. 
+- ensure that all remaining `ButtonTile`s have accurate row/col information.
+- update the score
+- ensure that the board's layout / draw methods are called by calling `board.setNeedsDisplay()`
+
+## Task 4: Animation
+Implement tile animation entirely in your `BoardView` class:
+- animate new tiles but starting them w/ opacity of 0 and animating to opacity
+  1.0
+- animate movement of existing tiles to new locations
+- use opacity again to animate disappearence of previously-seen tiles
+
+**Hint:** Animating tile disappearence in `BoardView` will not work if the
+view controller removes the `ButtonTile` from the board.
+
+## Task 5: Gestures
+Add gestures to the board. The gesture recognizer use your
+game's view controller as a target (first parameter to the
+`UISwipeGestureRecognizer` initializer), but you can attach this either to
+view controller's view, or to the game board. Either works.
+
+## Task 6: TabBarController
+This task is simple: draw out a `TabBarController` in the storyboard, attach
+the game controller (your original `ViewController`), and ensure that the `TabBarController` is the initial
+controller by moving the arrow.
+
+Everything else should continue working the same.
+
+## Task 7: Implement the *HighController* Scene
+You should:
+- subclass the `UIViewController` to a new `HighController` class. 
+- use interface builder to add a `UITableView`.
+- implement routines for the view controller to call providing a new high
+  score
+- use `UserDefaults` to store and retrieve high scores
+- the the tableview to show at least ten of the top scores with rank / score /
+  date-and-date, as shown in the video.
+- your game should jump to the high-scores screen at the end of a game when
+  calling `isDone()` returns true, but not whe
+
+
+## Task 8: Implement the *About* Scene
+It doesn't have to be like mine, and it doesn't have use gestures, but it
+should be fancy. Use `UIBezierPath` to draw something a diagram, make a little
+mini-game using dynamic gestures, be creative!
+
+
+
+## Grading
+ Note that the above tasks are for sequencing your work. They do not match up exactly with this grading rubric:
+- 30: change storyboard and buttons to be dynamic, adapting to orientation/device changes
+- 30: animation, both movement and spawns
+- 10: gestures
+- 10: tabbarcontroller (just with labels saying "High Score" and "by AwesomeWhoever")
+- 10: High scores using a tableview and `UserDefaults`
+- 10: Fancy About scene using dynamic animation. 
+  
+  
-- 
GitLab