diff options
Diffstat (limited to 'K')
-rw-r--r-- | K/Board.jack | 333 | ||||
-rw-r--r-- | K/K.md | 9 | ||||
-rw-r--r-- | K/KGame.jack | 63 | ||||
-rw-r--r-- | K/Main.jack | 16 |
4 files changed, 421 insertions, 0 deletions
diff --git a/K/Board.jack b/K/Board.jack new file mode 100644 index 0000000..d598093 --- /dev/null +++ b/K/Board.jack @@ -0,0 +1,333 @@ +/** +- K: a 2048 clone written in Jack language +- Coursework for Nand2Tetris (http://nand2tetris.org/) +- Author: Yuchen Pei (me@ypei.me) +- This file: the board model for the K game +*/ +class Board { + field Array grid; + field int nTurn, seed, status; // status: 0: begin game; 1: in game; 2: lose; 3: win; + static String boardBar, strLost, strCont, strGameOver, strWon, strTurn; + + constructor Board new() { + var int i; + let grid = Array.new(4); + let i = 0; + while (i < 4) { + let grid[i] = Array.new(4); + let i = i + 1; + } + do initBoard(); + let seed = 0; + return this; + } + + function void init() { + let boardBar = "+----+"; + let strLost = "You lost!"; + let strWon = "You won!"; + let strCont = "Press any key to continue"; + let strGameOver = "Game over!"; + let strTurn = "Turn: "; + return; + } + + method void initBoard() { + var int i, j; + var Array t; + let i = 0; + while (i < 4) { + let j = 0; + let t = grid[i]; + while (j < 4) { + let t[j] = 32; + let j = j + 1; + } + let i = i + 1; + } + let t = grid[0]; + let t[0] = 65; + let nTurn = 0; + let status = 0; + return; + } + + + method void transpose() { + do exch(0, 1); + do exch(0, 2); + do exch(0, 3); + do exch(1, 2); + do exch(1, 3); + do exch(2, 3); + return; + } + + method void exch(int i, int j){ + var int t; + var Array s1, s2; + let s1 = grid[i]; + let s2 = grid[j]; + let t = s1[j]; + let s1[j] = s2[i]; + let s2[i] = t; + return; + } + + method void align(Array xs, boolean left){ + var int i, j; + let i = 0; + let j = 0; + if (left) { + while (i < 4) { + if (xs[i] > 64) { + let xs[j] = xs[i]; + let j = j + 1; + } + let i = i + 1; + } + while (j < 4) { + let xs[j] = 32; + let j = j + 1; + } + } else { + while (i < 4) { + if (xs[3 - i] > 64) { + let xs[3 - j] = xs[3 - i]; + let j = j + 1; + } + let i = i + 1; + } + while (j < 4) { + let xs[3 - j] = 32; + let j = j + 1; + } + } + return; + } + + method void reduce(Array xs, boolean left){ + if ((xs[0] = xs[1]) & (xs[2] = xs[3]) & (xs[0] > 64) & (xs[2] > 64)) { + if (left) { + let xs[0] = xs[0] + 1; + let xs[1] = xs[2] + 1; + let xs[2] = 32; + let xs[3] = 32; + } else { + let xs[3] = xs[3] + 1; + let xs[2] = xs[1] + 1; + let xs[1] = 32; + let xs[0] = 32; + } + return; + } + if ((xs[0] = xs[1]) & (xs[0] > 64)) { + if (left) { + let xs[0] = xs[0] + 1; + let xs[1] = xs[2]; + let xs[2] = xs[3]; + let xs[3] = 32; + } else { + let xs[1] = xs[1] + 1; + let xs[0] = 32; + } + return; + } + if ((xs[2] = xs[3]) & (xs[2] > 64)) { + if (left) { + let xs[2] = xs[2] + 1; + let xs[3] = 32; + } else { + let xs[3] = xs[3] + 1; + let xs[2] = xs[1]; + let xs[1] = xs[0]; + let xs[0] = 32; + } + return; + } + if ((xs[1] = xs[2]) & (xs[1] > 64)) { + if (left) { + let xs[1] = xs[1] + 1; + let xs[2] = xs[3]; + let xs[3] = 32; + } else { + let xs[2] = xs[2] + 1; + let xs[1] = xs[0]; + let xs[0] = 32; + } + return; + } + return; + } + + method void addTile(){ + var Array t; + var int r, c, parity, newTile; + /* + let t = grid[1]; + if (t[1] = 32) { + let t[1] = 65; + } + */ + + if (~(status = 1)) { + return; + } + + let seed = seed * 25173 + 13849; + if (seed < 0) { + let seed = - seed; + } + + if (seed - (seed / 2 * 2) = 0) { + let parity = 1; + } else { + let parity = -1; + } + + let seed = seed - (seed / 16 * 16); + let r = seed / 4; + let c = seed - (4 * r); + let t = grid[r]; + let newTile = 65; + + while (t[c] > 64){ + let seed = seed + parity; + if (seed < 0) { + let seed = 15; + } + let seed = seed - (seed / 16 * 16); + let r = seed / 4; + let c = seed - (4 * r); + let t = grid[r]; + let newTile = 131 - newTile; + } + let t[c] = newTile; + return; + } + + method void transform(char dir){ + var boolean isVertical, left; + var int i; + if ((dir = 0) | (dir = 1)) { + let left = true; + } else { + let left = false; + } + if ((dir = 0) | (dir = 2)) { + let isVertical = false; + } else { + let isVertical = true; + } + if (isVertical) { + do transpose(); + } + let i = 0; + while (i < 4) { + do align(grid[i], left); + do reduce(grid[i], left); + let i = i + 1; + } + if (isVertical) { + do transpose(); + } + return; + } + + method void next(int dir){ + let nTurn = nTurn + 1; + do transform(dir); + do updateStatus(); + return; + } + + method int getStatus(){ + return status; + } + + method void setStatus(int x){ + let status = x; + return; + } + + method void updateStatus(){ + var int i, j; + var Array r; + let i = 0; + while (i < 4) { + let r = grid[i]; + let j = 0; + while (j < 4) { + if (r[j] = 75) { + let status = 3; + return; + } + if (r[j] = 32) { + let status = 1; + return; + } + let j = j + 1; + } + let i = i + 1; + } + let status = 2; + return; + } + + method void draw(){ + var int r, c, i, j; + var Array t; + let r = 9; + let c = 30; + + if (status = 0) { + do Output.moveCursor(r - 1, c - 1); + do Output.printChar(75); + do Output.moveCursor(r + 1, c - 1); + do Output.printString(strCont); + } else { if (status = 2) { + do Output.moveCursor(r - 1, c - 1); + do Output.printString(strGameOver); + do Output.moveCursor(r + 1, c - 1); + do Output.printString(strLost); + do Output.moveCursor(r + 3, c - 1); + do Output.printString(strCont); + } else { if (status = 3) { + do Output.moveCursor(r - 1, c - 1); + do Output.printString(strGameOver); + do Output.moveCursor(r + 1, c - 1); + do Output.printString(strWon); + do Output.moveCursor(r + 3, c - 1); + do Output.printString(strCont); + } else { + do Output.moveCursor(r - 1, c - 1); + do Output.printString(boardBar); + do Output.moveCursor(r + 4, c - 1); + do Output.printString(boardBar); + + let i = 0; + while (i < 4) { + let j = 0; + do Output.moveCursor(r + i, c - 1); + do Output.printChar(124); // 124 is | + let t = grid[i]; + while (j < 4) { + do Output.printChar(t[j]); + let j = j + 1; + } + do Output.printChar(124); + let i = i + 1; + } + + do Output.moveCursor(r + 6, c - 2); + do Output.printString(strTurn); + do Output.printInt(nTurn); + }}} + return; + } + + method void dispose() { + do Memory.deAlloc(this); + return; + } +} @@ -0,0 +1,9 @@ +K is a clone of 2048. Instead of aiming for the 11th power of 2, the goal of this game is to reach the 11th letter in the alphabet, which is 'K'. +Written in Jack, a minimal OOP language created by creators of the [Nand2Tetris course](http://nand2tetris.org). + +Controls: +- Arrow keys to move the letters +- R to restart +- Q to quit + +Caveats. The pseudorandom number generator is far from industrial strength, so you may notice new letters are more likely to spawn in certain locations than others... diff --git a/K/KGame.jack b/K/KGame.jack new file mode 100644 index 0000000..277afaf --- /dev/null +++ b/K/KGame.jack @@ -0,0 +1,63 @@ +/** +- K: a 2048 clone written in Jack language +- Coursework for Nand2Tetris (http://nand2tetris.org/) +- Author: Yuchen Pei (me@ypei.me) +- This file: the game I/O for the K game +*/ +class KGame{ + field Board board; + + constructor KGame new() { + let board = Board.new(); + do board.draw(); + return this; + } + + method void dispose() { + do board.dispose(); + do Memory.deAlloc(this); + return; + } + + method void run() { + var int key, key1, st; + var boolean exit; + let exit = false; + while (~exit) { + let st = board.getStatus(); + let key = 0; + while (key = 0) { + let key = Keyboard.keyPressed(); + } + let key1 = key; + while (~(key1 = 0)) { + let key1 = Keyboard.keyPressed(); + } + if (key = 81) { + let exit = true; + } else { if ((st = 0)) { + do Screen.clearScreen(); + do board.setStatus(1); + do board.draw(); + } else { if ((st = 2) | (st = 3)) { + do Screen.clearScreen(); + do board.setStatus(0); + do board.draw(); + do board.initBoard(); + } else { if (key = 82) { // r for restart + do Screen.clearScreen(); + do board.initBoard(); + do board.draw(); + } else { if ((key > 129) & (key < 134)) { + do Screen.clearScreen(); + do board.next(key - 130); + do board.draw(); + do Sys.wait(300); + do Screen.clearScreen(); + do board.addTile(); + do board.draw(); + }}}}} + } + return; + } +} diff --git a/K/Main.jack b/K/Main.jack new file mode 100644 index 0000000..c1b6a79 --- /dev/null +++ b/K/Main.jack @@ -0,0 +1,16 @@ +/** +- K: a 2048 clone written in Jack language +- Coursework for Nand2Tetris (http://nand2tetris.org/) +- Author: Yuchen Pei (me@ypei.me) +- This file: the main file for the K game +*/ +class Main { + function void main() { + var KGame game; + do Board.init(); + let game = KGame.new(); + do game.run(); + do game.dispose(); + return; + } +} |