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; +    } +} | 
