aboutsummaryrefslogtreecommitdiff
path: root/projects/11
diff options
context:
space:
mode:
Diffstat (limited to 'projects/11')
-rw-r--r--projects/11/Average/Main.jack29
-rw-r--r--projects/11/ComplexArrays/Main.jack70
-rw-r--r--projects/11/ConvertToBin/Main.jack82
-rw-r--r--projects/11/Pong/Ball.jack203
-rw-r--r--projects/11/Pong/Bat.jack103
-rw-r--r--projects/11/Pong/Main.jack20
-rw-r--r--projects/11/Pong/PongGame.jack137
-rw-r--r--projects/11/Seven/Main.jack17
-rw-r--r--projects/11/Square/Main.jack17
-rw-r--r--projects/11/Square/Square.jack110
-rw-r--r--projects/11/Square/SquareGame.jack81
11 files changed, 869 insertions, 0 deletions
diff --git a/projects/11/Average/Main.jack b/projects/11/Average/Main.jack
new file mode 100644
index 0000000..d560bf1
--- /dev/null
+++ b/projects/11/Average/Main.jack
@@ -0,0 +1,29 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Average/Main.jack
+
+// (Same as projects/09/Average/Main.jack)
+
+// Inputs some numbers and computes their average
+class Main {
+ function void main() {
+ var Array a;
+ var int length;
+ var int i, sum;
+
+ let length = Keyboard.readInt("How many numbers? ");
+ let a = Array.new(length); // constructs the array
+
+ let i = 0;
+ while (i < length) {
+ let a[i] = Keyboard.readInt("Enter a number: ");
+ let sum = sum + a[i];
+ let i = i + 1;
+ }
+
+ do Output.printString("The average is ");
+ do Output.printInt(sum / length);
+ return;
+ }
+}
diff --git a/projects/11/ComplexArrays/Main.jack b/projects/11/ComplexArrays/Main.jack
new file mode 100644
index 0000000..fe51c20
--- /dev/null
+++ b/projects/11/ComplexArrays/Main.jack
@@ -0,0 +1,70 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/ComplexArrays/Main.jack
+
+/**
+ * Performs several complex array processing tests.
+ * For each test, the expected result is printed, along with the
+ * actual result. In each test, the two results should be equal.
+ */
+class Main {
+
+ function void main() {
+ var Array a, b, c;
+
+ let a = Array.new(10);
+ let b = Array.new(5);
+ let c = Array.new(1);
+
+ let a[3] = 2;
+ let a[4] = 8;
+ let a[5] = 4;
+ let b[a[3]] = a[3] + 3; // b[2] = 5
+ let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1]; // a[5] = 8 * 5 = 40
+ let c[0] = null;
+ let c = c[0];
+
+ do Output.printString("Test 1: expected result: 5; actual result: ");
+ do Output.printInt(b[2]);
+ do Output.println();
+ do Output.printString("Test 2: expected result: 40; actual result: ");
+ do Output.printInt(a[5]);
+ do Output.println();
+ do Output.printString("Test 3: expected result: 0; actual result: ");
+ do Output.printInt(c);
+ do Output.println();
+
+ let c = null;
+
+ if (c = null) {
+ do Main.fill(a, 10);
+ let c = a[3];
+ let c[1] = 33;
+ let c = a[7];
+ let c[1] = 77;
+ let b = a[3];
+ let b[1] = b[1] + c[1]; // b[1] = 33 + 77 = 110;
+ }
+
+ do Output.printString("Test 4: expected result: 77; actual result: ");
+ do Output.printInt(c[1]);
+ do Output.println();
+ do Output.printString("Test 5: expected result: 110; actual result: ");
+ do Output.printInt(b[1]);
+ do Output.println();
+ return;
+ }
+
+ function int double(int a) {
+ return a * 2;
+ }
+
+ function void fill(Array a, int size) {
+ while (size > 0) {
+ let size = size - 1;
+ let a[size] = Array.new(3);
+ }
+ return;
+ }
+}
diff --git a/projects/11/ConvertToBin/Main.jack b/projects/11/ConvertToBin/Main.jack
new file mode 100644
index 0000000..e627486
--- /dev/null
+++ b/projects/11/ConvertToBin/Main.jack
@@ -0,0 +1,82 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/ConvertToBin/Main.jack
+
+/**
+ * Unpacks a 16-bit number into its binary representation:
+ * Takes the 16-bit number stored in RAM[8000] and stores its individual
+ * bits in RAM[8001..8016] (each location will contain 0 or 1).
+ * Before the conversion, RAM[8001]..RAM[8016] are initialized to -1.
+ *
+ * The program should be tested as follows:
+ * 1) Load the program into the supplied VM emulator
+ * 2) Put some value in RAM[8000]
+ * 3) Switch to "no animation"
+ * 4) Run the program (give it enough time to run)
+ * 5) Stop the program
+ * 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and
+ * that none of these memory locations contains -1.
+ */
+class Main {
+
+ /**
+ * Initializes RAM[8001]..RAM[8016] to -1,
+ * and converts the value in RAM[8000] to binary.
+ */
+ function void main() {
+ var int value;
+ do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1
+ let value = Memory.peek(8000); // reads a value from RAM[8000]
+ do Main.convert(value); // performs the conversion
+ return;
+ }
+
+ /** Converts the given decimal value to binary, and puts
+ * the resulting bits in RAM[8001]..RAM[8016]. */
+ function void convert(int value) {
+ var int mask, position;
+ var boolean loop;
+
+ let loop = true;
+ while (loop) {
+ let position = position + 1;
+ let mask = Main.nextMask(mask);
+
+ if (~(position > 16)) {
+
+ if (~((value & mask) = 0)) {
+ do Memory.poke(8000 + position, 1);
+ }
+ else {
+ do Memory.poke(8000 + position, 0);
+ }
+ }
+ else {
+ let loop = false;
+ }
+ }
+ return;
+ }
+
+ /** Returns the next mask (the mask that should follow the given mask). */
+ function int nextMask(int mask) {
+ if (mask = 0) {
+ return 1;
+ }
+ else {
+ return mask * 2;
+ }
+ }
+
+ /** Fills 'length' consecutive memory locations with 'value',
+ * starting at 'startAddress'. */
+ function void fillMemory(int startAddress, int length, int value) {
+ while (length > 0) {
+ do Memory.poke(startAddress, value);
+ let length = length - 1;
+ let startAddress = startAddress + 1;
+ }
+ return;
+ }
+}
diff --git a/projects/11/Pong/Ball.jack b/projects/11/Pong/Ball.jack
new file mode 100644
index 0000000..02e47f9
--- /dev/null
+++ b/projects/11/Pong/Ball.jack
@@ -0,0 +1,203 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Pong/Ball.jack
+
+/**
+ * A graphical ball. Characterized by a screen location and distance of
+ * last destination. Has methods for drawing, erasing and moving on the screen.
+ * The ball is displayed as a filled, 6-by-6 pixles rectangle.
+ */
+class Ball {
+
+ field int x, y; // the ball's screen location (in pixels)
+ field int lengthx, lengthy; // distance of last destination (in pixels)
+
+ field int d, straightD, diagonalD; // used for straight line movement computation
+ field boolean invert, positivex, positivey; // (same)
+
+ field int leftWall, rightWall, topWall, bottomWall; // wall locations
+
+ field int wall; // last wall that the ball was bounced off of
+
+ /** Constructs a new ball with the given initial location and wall locations. */
+ constructor Ball new(int Ax, int Ay,
+ int AleftWall, int ArightWall, int AtopWall, int AbottomWall) {
+ let x = Ax;
+ let y = Ay;
+ let leftWall = AleftWall;
+ let rightWall = ArightWall - 6; // -6 for ball size
+ let topWall = AtopWall;
+ let bottomWall = AbottomWall - 6; // -6 for ball size
+ let wall = 0;
+ do show();
+ return this;
+ }
+
+ /** Deallocates the Ball's memory. */
+ method void dispose() {
+ do Memory.deAlloc(this);
+ return;
+ }
+
+ /** Shows the ball. */
+ method void show() {
+ do Screen.setColor(true);
+ do draw();
+ return;
+ }
+
+ /** Hides the ball. */
+ method void hide() {
+ do Screen.setColor(false);
+ do draw();
+ return;
+ }
+
+ /** Draws the ball. */
+ method void draw() {
+ do Screen.drawRectangle(x, y, x + 5, y + 5);
+ return;
+ }
+
+ /** Returns the ball's left edge. */
+ method int getLeft() {
+ return x;
+ }
+
+ /** Returns the ball's right edge. */
+ method int getRight() {
+ return x + 5;
+ }
+
+ /** Computes and sets the ball's destination. */
+ method void setDestination(int destx, int desty) {
+ var int dx, dy, temp;
+ let lengthx = destx - x;
+ let lengthy = desty - y;
+ let dx = Math.abs(lengthx);
+ let dy = Math.abs(lengthy);
+ let invert = (dx < dy);
+
+ if (invert) {
+ let temp = dx; // swap dx, dy
+ let dx = dy;
+ let dy = temp;
+ let positivex = (y < desty);
+ let positivey = (x < destx);
+ }
+ else {
+ let positivex = (x < destx);
+ let positivey = (y < desty);
+ }
+
+ let d = (2 * dy) - dx;
+ let straightD = 2 * dy;
+ let diagonalD = 2 * (dy - dx);
+
+ return;
+ }
+
+ /**
+ * Moves the ball one unit towards its destination.
+ * If the ball has reached a wall, returns 0.
+ * Else, returns a value according to the wall:
+ * 1 (left wall), 2 (right wall), 3 (top wall), 4 (bottom wall).
+ */
+ method int move() {
+
+ do hide();
+
+ if (d < 0) { let d = d + straightD; }
+ else {
+ let d = d + diagonalD;
+
+ if (positivey) {
+ if (invert) { let x = x + 4; }
+ else { let y = y + 4; }
+ }
+ else {
+ if (invert) { let x = x - 4; }
+ else { let y = y - 4; }
+ }
+ }
+
+ if (positivex) {
+ if (invert) { let y = y + 4; }
+ else { let x = x + 4; }
+ }
+ else {
+ if (invert) { let y = y - 4; }
+ else { let x = x - 4; }
+ }
+
+ if (~(x > leftWall)) {
+ let wall = 1;
+ let x = leftWall;
+ }
+ if (~(x < rightWall)) {
+ let wall = 2;
+ let x = rightWall;
+ }
+ if (~(y > topWall)) {
+ let wall = 3;
+ let y = topWall;
+ }
+ if (~(y < bottomWall)) {
+ let wall = 4;
+ let y = bottomWall;
+ }
+
+ do show();
+
+ return wall;
+ }
+
+ /**
+ * Bounces off the current wall: sets the new destination
+ * of the ball according to the ball's angle and the given
+ * bouncing direction (-1/0/1=left/center/right or up/center/down).
+ */
+ method void bounce(int bouncingDirection) {
+ var int newx, newy, divLengthx, divLengthy, factor;
+
+ // dividing by 10 first since results are too big
+ let divLengthx = lengthx / 10;
+ let divLengthy = lengthy / 10;
+ if (bouncingDirection = 0) { let factor = 10; }
+ else {
+ if (((~(lengthx < 0)) & (bouncingDirection = 1)) | ((lengthx < 0) & (bouncingDirection = (-1)))) {
+ let factor = 20; // bounce direction is in ball direction
+ }
+ else { let factor = 5; } // bounce direction is against ball direction
+ }
+
+ if (wall = 1) {
+ let newx = 506;
+ let newy = (divLengthy * (-50)) / divLengthx;
+ let newy = y + (newy * factor);
+ }
+ else {
+ if (wall = 2) {
+ let newx = 0;
+ let newy = (divLengthy * 50) / divLengthx;
+ let newy = y + (newy * factor);
+ }
+ else {
+ if (wall = 3) {
+ let newy = 250;
+ let newx = (divLengthx * (-25)) / divLengthy;
+ let newx = x + (newx * factor);
+ }
+ else { // assumes wall = 4
+ let newy = 0;
+ let newx = (divLengthx * 25) / divLengthy;
+ let newx = x + (newx * factor);
+ }
+ }
+ }
+
+ do setDestination(newx, newy);
+ return;
+ }
+}
diff --git a/projects/11/Pong/Bat.jack b/projects/11/Pong/Bat.jack
new file mode 100644
index 0000000..340760f
--- /dev/null
+++ b/projects/11/Pong/Bat.jack
@@ -0,0 +1,103 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Pong/Bat.jack
+
+/**
+ * A graphical Pong bat.
+ * Displayed as a filled horizontal rectangle that has
+ * a screen location, a width and a height.
+ * Has methods for drawing, erasing, moving left and right,
+ * and changing its width (to make the hitting action more challenging).
+ * This class should have been called "paddle", following the
+ * standard Pong terminology. But, unaware of this terminology,
+ * we called it "bat", and then decided to stick to it.
+ */
+class Bat {
+
+ field int x, y; // the bat's screen location
+ field int width, height; // the bat's width and height
+ field int direction; // direction of the bat's movement (1 = left, 2 = right)
+
+ /** Constructs a new bat with the given location and width. */
+ constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) {
+ let x = Ax;
+ let y = Ay;
+ let width = Awidth;
+ let height = Aheight;
+ let direction = 2;
+ do show();
+ return this;
+ }
+
+ /** Deallocates the object's memory. */
+ method void dispose() {
+ do Memory.deAlloc(this);
+ return;
+ }
+
+ /** Shows the bat. */
+ method void show() {
+ do Screen.setColor(true);
+ do draw();
+ return;
+ }
+
+ /** Hides the bat. */
+ method void hide() {
+ do Screen.setColor(false);
+ do draw();
+ return;
+ }
+
+ /** Draws the bat. */
+ method void draw() {
+ do Screen.drawRectangle(x, y, x + width, y + height);
+ return;
+ }
+
+ /** Sets the bat's direction (0=stop, 1=left, 2=right). */
+ method void setDirection(int Adirection) {
+ let direction = Adirection;
+ return;
+ }
+
+ /** Returns the bat's left edge. */
+ method int getLeft() {
+ return x;
+ }
+
+ /** Returns the bat's right edge. */
+ method int getRight() {
+ return x + width;
+ }
+
+ /** Sets the bat's width. */
+ method void setWidth(int Awidth) {
+ do hide();
+ let width = Awidth;
+ do show();
+ return;
+ }
+
+ /** Moves the bat one step in the bat's direction. */
+ method void move() {
+ if (direction = 1) {
+ let x = x - 4;
+ if (x < 0) { let x = 0; }
+ do Screen.setColor(false);
+ do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height);
+ do Screen.setColor(true);
+ do Screen.drawRectangle(x, y, x + 3, y + height);
+ }
+ else {
+ let x = x + 4;
+ if ((x + width) > 511) { let x = 511 - width; }
+ do Screen.setColor(false);
+ do Screen.drawRectangle(x - 4, y, x - 1, y + height);
+ do Screen.setColor(true);
+ do Screen.drawRectangle((x + width) - 3, y, x + width, y + height);
+ }
+ return;
+ }
+}
diff --git a/projects/11/Pong/Main.jack b/projects/11/Pong/Main.jack
new file mode 100644
index 0000000..45e2dd2
--- /dev/null
+++ b/projects/11/Pong/Main.jack
@@ -0,0 +1,20 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Pong/Main.jack
+
+/**
+ * The main class of the Pong game.
+ */
+class Main {
+
+ /** Initializes a Pong game and starts running it. */
+ function void main() {
+ var PongGame game;
+ do PongGame.newInstance();
+ let game = PongGame.getInstance();
+ do game.run();
+ do game.dispose();
+ return;
+ }
+}
diff --git a/projects/11/Pong/PongGame.jack b/projects/11/Pong/PongGame.jack
new file mode 100644
index 0000000..7e1ae4c
--- /dev/null
+++ b/projects/11/Pong/PongGame.jack
@@ -0,0 +1,137 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Pong/PongGame.jack
+
+/**
+ * Represents a Pong game.
+ */
+class PongGame {
+
+ static PongGame instance; // the singelton, a Pong game instance
+ field Bat bat; // the bat
+ field Ball ball; // the ball
+ field int wall; // the current wall that the ball is bouncing off of.
+ field boolean exit; // true when the game is over
+ field int score; // the current score.
+ field int lastWall; // the last wall that the ball bounced off of.
+
+ // The current width of the bat
+ field int batWidth;
+
+ /** Constructs a new Pong game. */
+ constructor PongGame new() {
+ do Screen.clearScreen();
+ let batWidth = 50; // initial bat size
+ let bat = Bat.new(230, 229, batWidth, 7);
+ let ball = Ball.new(253, 222, 0, 511, 0, 229);
+ do ball.setDestination(400,0);
+ do Screen.drawRectangle(0, 238, 511, 240);
+ do Output.moveCursor(22,0);
+ do Output.printString("Score: 0");
+
+ let exit = false;
+ let score = 0;
+ let wall = 0;
+ let lastWall = 0;
+
+ return this;
+ }
+
+ /** Deallocates the object's memory. */
+ method void dispose() {
+ do bat.dispose();
+ do ball.dispose();
+ do Memory.deAlloc(this);
+ return;
+ }
+
+ /** Creates an instance of Pong game, and stores it. */
+ function void newInstance() {
+ let instance = PongGame.new();
+ return;
+ }
+
+ /** Returns the single instance of this Pong game. */
+ function PongGame getInstance() {
+ return instance;
+ }
+
+ /** Starts the game, and andles inputs from the user that control
+ * the bat's movement direction. */
+ method void run() {
+ var char key;
+
+ while (~exit) {
+ // waits for a key to be pressed.
+ while ((key = 0) & (~exit)) {
+ let key = Keyboard.keyPressed();
+ do bat.move();
+ do moveBall();
+ do Sys.wait(50);
+ }
+
+ if (key = 130) { do bat.setDirection(1); }
+ else {
+ if (key = 132) { do bat.setDirection(2); }
+ else {
+ if (key = 140) { let exit = true; }
+ }
+ }
+
+ // Waits for the key to be released.
+ while ((~(key = 0)) & (~exit)) {
+ let key = Keyboard.keyPressed();
+ do bat.move();
+ do moveBall();
+ do Sys.wait(50);
+ }
+ }
+
+ if (exit) {
+ do Output.moveCursor(10,27);
+ do Output.printString("Game Over");
+ }
+
+ return;
+ }
+
+ /**
+ * Handles ball movement, including bouncing.
+ * If the ball bounces off a wall, finds its new direction.
+ * If the ball bounces off the bat, increases the score by one
+ * and shrinks the bat's size, to make the game more challenging.
+ */
+ method void moveBall() {
+ var int bouncingDirection, batLeft, batRight, ballLeft, ballRight;
+
+ let wall = ball.move();
+
+ if ((wall > 0) & (~(wall = lastWall))) {
+ let lastWall = wall;
+ let bouncingDirection = 0;
+ let batLeft = bat.getLeft();
+ let batRight = bat.getRight();
+ let ballLeft = ball.getLeft();
+ let ballRight = ball.getRight();
+
+ if (wall = 4) {
+ let exit = (batLeft > ballRight) | (batRight < ballLeft);
+ if (~exit) {
+ if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; }
+ else {
+ if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; }
+ }
+
+ let batWidth = batWidth - 2;
+ do bat.setWidth(batWidth);
+ let score = score + 1;
+ do Output.moveCursor(22,7);
+ do Output.printInt(score);
+ }
+ }
+ do ball.bounce(bouncingDirection);
+ }
+ return;
+ }
+} \ No newline at end of file
diff --git a/projects/11/Seven/Main.jack b/projects/11/Seven/Main.jack
new file mode 100644
index 0000000..067402e
--- /dev/null
+++ b/projects/11/Seven/Main.jack
@@ -0,0 +1,17 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Seven/Main.jack
+
+/**
+ * Computes the value of 1 + (2 * 3) and prints the result
+ * at the top-left of the screen.
+ */
+class Main {
+
+ function void main() {
+ do Output.printInt(1 + (2 * 3));
+ return;
+ }
+
+}
diff --git a/projects/11/Square/Main.jack b/projects/11/Square/Main.jack
new file mode 100644
index 0000000..0753893
--- /dev/null
+++ b/projects/11/Square/Main.jack
@@ -0,0 +1,17 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Square/Main.jack
+
+// (same as projects/09/Square/Main.jack)
+
+/** Initializes a new Square Dance game and starts running it. */
+class Main {
+ function void main() {
+ var SquareGame game;
+ let game = SquareGame.new();
+ do game.run();
+ do game.dispose();
+ return;
+ }
+}
diff --git a/projects/11/Square/Square.jack b/projects/11/Square/Square.jack
new file mode 100644
index 0000000..5a92838
--- /dev/null
+++ b/projects/11/Square/Square.jack
@@ -0,0 +1,110 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Square/Square.jack
+
+// (same as projects/09/Square/Square.jack)
+
+/** Implements a graphical square. */
+class Square {
+
+ field int x, y; // screen location of the square's top-left corner
+ field int size; // length of this square, in pixels
+
+ /** Constructs a new square with a given location and size. */
+ constructor Square new(int Ax, int Ay, int Asize) {
+ let x = Ax;
+ let y = Ay;
+ let size = Asize;
+ do draw();
+ return this;
+ }
+
+ /** Disposes this square. */
+ method void dispose() {
+ do Memory.deAlloc(this);
+ return;
+ }
+
+ /** Draws the square on the screen. */
+ method void draw() {
+ do Screen.setColor(true);
+ do Screen.drawRectangle(x, y, x + size, y + size);
+ return;
+ }
+
+ /** Erases the square from the screen. */
+ method void erase() {
+ do Screen.setColor(false);
+ do Screen.drawRectangle(x, y, x + size, y + size);
+ return;
+ }
+
+ /** Increments the square size by 2 pixels. */
+ method void incSize() {
+ if (((y + size) < 254) & ((x + size) < 510)) {
+ do erase();
+ let size = size + 2;
+ do draw();
+ }
+ return;
+ }
+
+ /** Decrements the square size by 2 pixels. */
+ method void decSize() {
+ if (size > 2) {
+ do erase();
+ let size = size - 2;
+ do draw();
+ }
+ return;
+ }
+
+ /** Moves the square up by 2 pixels. */
+ method void moveUp() {
+ if (y > 1) {
+ do Screen.setColor(false);
+ do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
+ let y = y - 2;
+ do Screen.setColor(true);
+ do Screen.drawRectangle(x, y, x + size, y + 1);
+ }
+ return;
+ }
+
+ /** Moves the square down by 2 pixels. */
+ method void moveDown() {
+ if ((y + size) < 254) {
+ do Screen.setColor(false);
+ do Screen.drawRectangle(x, y, x + size, y + 1);
+ let y = y + 2;
+ do Screen.setColor(true);
+ do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
+ }
+ return;
+ }
+
+ /** Moves the square left by 2 pixels. */
+ method void moveLeft() {
+ if (x > 1) {
+ do Screen.setColor(false);
+ do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
+ let x = x - 2;
+ do Screen.setColor(true);
+ do Screen.drawRectangle(x, y, x + 1, y + size);
+ }
+ return;
+ }
+
+ /** Moves the square right by 2 pixels. */
+ method void moveRight() {
+ if ((x + size) < 510) {
+ do Screen.setColor(false);
+ do Screen.drawRectangle(x, y, x + 1, y + size);
+ let x = x + 2;
+ do Screen.setColor(true);
+ do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
+ }
+ return;
+ }
+}
diff --git a/projects/11/Square/SquareGame.jack b/projects/11/Square/SquareGame.jack
new file mode 100644
index 0000000..4fe7e39
--- /dev/null
+++ b/projects/11/Square/SquareGame.jack
@@ -0,0 +1,81 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/11/Square/SquareGame.jack
+
+// (same as projects/09/Square/SquareGame.jack)
+
+/**
+ * Implements the Square Dance game.
+ * This simple game allows the user to move a black square around
+ * the screen, and change the square's size during the movement.
+ * When the game starts, a square of 30 by 30 pixels is shown at the
+ * top-left corner of the screen. The user controls the square as follows.
+ * The 4 arrow keys are used to move the square up, down, left, and right.
+ * The 'z' and 'x' keys are used, respectively, to decrement and increment
+ * the square's size. The 'q' key is used to quit the game.
+ */
+
+class SquareGame {
+ field Square square; // the square of this game
+ field int direction; // the square's current direction:
+ // 0=none, 1=up, 2=down, 3=left, 4=right
+
+ /** Constructs a new Square Game. */
+ constructor SquareGame new() {
+ // Creates a 30 by 30 pixels square and positions it at the top-left
+ // of the screen.
+ let square = Square.new(0, 0, 30);
+ let direction = 0; // initial state is no movement
+ return this;
+ }
+
+ /** Disposes this game. */
+ method void dispose() {
+ do square.dispose();
+ do Memory.deAlloc(this);
+ return;
+ }
+
+ /** Moves the square in the current direction. */
+ method void moveSquare() {
+ if (direction = 1) { do square.moveUp(); }
+ if (direction = 2) { do square.moveDown(); }
+ if (direction = 3) { do square.moveLeft(); }
+ if (direction = 4) { do square.moveRight(); }
+ do Sys.wait(5); // delays the next movement
+ return;
+ }
+
+ /** Runs the game: handles the user's inputs and moves the square accordingly */
+ method void run() {
+ var char key; // the key currently pressed by the user
+ var boolean exit;
+ let exit = false;
+
+ while (~exit) {
+ // waits for a key to be pressed
+ while (key = 0) {
+ let key = Keyboard.keyPressed();
+ do moveSquare();
+ }
+ if (key = 81) { let exit = true; } // q key
+ if (key = 90) { do square.decSize(); } // z key
+ if (key = 88) { do square.incSize(); } // x key
+ if (key = 131) { let direction = 1; } // up arrow
+ if (key = 133) { let direction = 2; } // down arrow
+ if (key = 130) { let direction = 3; } // left arrow
+ if (key = 132) { let direction = 4; } // right arrow
+
+ // waits for the key to be released
+ while (~(key = 0)) {
+ let key = Keyboard.keyPressed();
+ do moveSquare();
+ }
+ } // while
+ return;
+ }
+}
+
+
+