Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.

Project 1 (assign1): Swift and Generics

Goals

The primary goal of this project is to to familiarize yourself with the environment and the language. You should be using at least Swift 5.3 and 12.4 as your friendly development environment. Errors resulting from development in older environments still result in loss of points.

Specifically, you will create an application having a model that emulates the logic of the 2048 app here in a SwiftUI app, though we won't actually build a GUI at all. Your app will do nothing when run, but does include the app's model and unit tests with which to test your model.

In the process you will obviously learn quite a bit about the XCode environment, about unit tests in the context of Swift applications, and about defining type generics.

Using git

You will submit your assignment solution through git. Clone your repository from gitlab.cs.umd.edu as follows:

    git clone git@gitlab.cs.umd.edu:cmsc436Fall2021/cmsc436-<dirid>

with your directoryID substituted for "<dirid>" above. This is the ssh version of git clone, which assumes you've uploaded an ssh key for your machine. Otherwise you can use:

    git clone https://gitlab.cs.umd.edu/cmsc436Fall2021/cmsc436-<dirid>

Email me directly (w/ "436" in the subject) if your repository does not seem to exist.

Create the new project assign1 in your repository. Always close the project first before pushing back to gitlab. The first time you create the project, cd into the repository and then push the new project back to gitlab.

For example, clone the repository (w/ my dirid just as an example), like the following:

    git clone git@gitlab.cs.umd.edu:cmsc436Fall2021/cmsc436-keleher

Create the new assign1 project inside cmsc436-keleher, create a new model.swift in the project to define your model, update the unit tests by copying from this link verbatim, and perform the following for your first commit:

    cd cmsc436-keleher
    git add assign1
    git commit -a -m auto
    git push origin master

You should add, commit, and push frequently, so that:

  1. you do not lose work, and
  2. we can help answer your questions by looking at your code.

Building An App

We are going to build an app called Twos in two or three stages. In the first stage, we are just going to design and implement the model, and unit-test it.

As we did in class, you will create a new SwiftUI iOS app:

  • Create a new project in XCode and save in your repository (which you cloned from gitlab earlier).
  • When creating the project:
    • call it assign1
    • check "unit tests", uncheck git, uncheck UI tests (not fatal, but the Test command from the Product menu will fail because it will try to test your GUI, and you don't have one.
  • Create a new file model.swift to implement the Twos class in your app by selecting "New / File" from the File menu, selecting the Swift file icon in the dialog, and then naming it model.swift. model.swift will contain the "model" known from the model-view-controller (MVC) or model-view-viewmodel paradigms.
  • Copy and paste the code in assign1Tests.swift verbatim over the default version.

Your file structure should look like the following: xcode.png

App Logic

Our game action will be similar to the app 2048 on the apple and android app stores. Game-play should be as on the website.

Your Tasks

Your task is to implement the model of the game. Specifically, you will implement all the code in model.swift (which you first create), including the "collapse", which given a swipe in a direction collapses each row or column parallel to the swipe by:

  • eliminating any blanks, and
  • performing a single pass over each row/col in the reverse of the swipe and combining consecutive individual values into a single value twice as large Note that a "swipe" can also be performed in a variety of other ways, for now we will do it using on-screen buttons.

See more specifics below.

The Twos Class

In the file model.swift you will define a new class Twos to implement the gameplay model and implements the methods discussed below. Twos will need the following definitions:

    struct Tile {
        var val : Int
        var lastRow = 0, lastCol = 0
        init(v: Int) {
            val = v
        }
    }

    enum Direction {
       case left
       case right
       case up
       case down
	}
    var board: [[Tile]]                                // must be init'd, but contents overwritten

and functions:

    // primitive functions
    public func rotate2DInts(input: [[Int]]) ->[[Int]] // rotate a square 2D Int array clockwise
    public func rotate2D<T>(input: [[T]]) ->[[T]]      // generic version of the above

	// high-level functions
    func shiftLeft()                                   // collapse to the left
    func rightRotate()                                 // define using only rotate2D
    func collapse(dir: Direction)                      // collapse in direction "dir" using only
                                                       // shiftLeft() and rightRotate()

Tile, Direction, rotate2DInts, and rotate2D<T> must all be defined outside your Twos class, not inside.

The above must all be created exactly as specified or the unit tests will fail. DO NOT change even a single character of the unit tests files, just copy it verbatim.

Note that methods merely modify the board property. We are not taking any actions based on the board, or doing any GUI work at all.

A Tile is a simple structure containing a val (the value of the tile) and additional Int fields lastRow and lastCol. You will need to ensure that Tile conforms to the Equatable protocol.

You must define and use the generic function rotate2D() to get any credit, do not define a Tile-specific version of rotate or use rotate2DInts at all in the collapse() function.

The rotation functions work as follows: rotate2

Testing

The provided copy of assign1Tests.swift should have been copied unaltered into your project. Test your project by running this set of tests by clicking "Test" in the "Products" menu, or clicking in the margin next to class assign1Tests: XCTestCase, or in the margin next to the individual tests.

Submit, and Grading

Submit by pushing your project to your repository. Check this by visiting your repository in a web browser at https://gitlab.cs.umd.edu/cmsc436fall2021/<dirid>

Alternatively: Test that your project create and push to the repository is correct by cloning it to a separate, throwaway location. Open this throwaway version and verify that it works the same way as your primary copy. If it doesn't, you probably did not add all the files in your project. Do this manually and try again.

Each of the eight tests is worth 1 point. There is no partial credit. You will not get credit if you:

  • modify assign1Tests.swift in any way
  • do not define rightRotate() and collapse() as specified above
  • define a Tile-specific version of rotate.

Notes

  • Remember, frequently save your work on gitlab. You can push your work as many times as you wish. We will download your repository from gitlab directly after the deadline.