Last active
February 13, 2018 10:39
-
-
Save dz0/f83b046ed75e3e11c9d6b503b80dd017 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Game of Life v1.0 | |
| * https://en.wikipedia.org/wiki/Conway's_Game_of_Life | |
| * | |
| * Author: Chionsas | |
| * Licence: PUBLIC DOMAIN, https://unlicense.org/UNLICENSE | |
| */ | |
| /* | |
| * Užduotis: pabaigti funkcijas getAliveNeighbourCount ir (panaudojant ją) generateNextTick (pagal išvardintas taisykles). | |
| * Kaip elgtis su programa?: Su pele paspaudinėt pradinę situaciją ir paskui paspaust "Space", procesui paleisti. | |
| */ | |
| // Konstantos | |
| final int rows = 10; // eilučių skaičius = aukštis | |
| final int columns = 20; // stulpelių skaičius = plotis | |
| final int target_world_width = 1400; // norimas lentos plotis pixeliais | |
| final int target_world_height = 700; // norimas lentos aukštis pixeliais | |
| final int cell_border = 1; // langelio krašto storis pixeliais | |
| final int cell_width = (target_world_width / columns) - cell_border; // vidinis langelio plotis pixeliais | |
| final int cell_height = (target_world_height / rows) - cell_border; // vidinis langelio aukštis pixeliais | |
| final int world_width = columns * (cell_width + cell_border) - cell_border; // lentos plotis | |
| final int world_height = rows * (cell_height + cell_border) - cell_border; // lentos aukštis | |
| final int window_width = floor(world_width*1.00); // lango plotis pixeliais | |
| final int window_height = floor(world_height*1.00); // lango aukštis pixeliais | |
| final int world_x = (window_width - world_width) / 2; // lentos pozicija x - centruota | |
| final int world_y = (window_height - world_height) / 2; // lentos pozicija y - centruota | |
| // Tango palette, https://en.wikipedia.org/wiki/Tango_Desktop_Project#Palette | |
| final color color_background = #eeeeec; | |
| final color color_cell_normal = color_background; | |
| final color color_cell_hover = color(255, 255, 255, 200); | |
| final color color_border = #d3d7cf; | |
| final color[] color_debug = { #a40000, #5c3566 }; | |
| final color[] color_value = { color_background, #d3d7cf, #75507b }; | |
| // Galimos langelių reikšmės | |
| final int VALUE_EMPTY = 0; | |
| final int VALUE_DEAD = 1; | |
| final int VALUE_ALIVE = 2; | |
| // Globalūs kintamieji | |
| // logging | |
| final int TRACE_DRAW = 70; // rodyti informaciją ir apie piešiamus objektus | |
| final int TRACE = 60; // detaliausias log'inimo lygis (konsolė ir grafinis rodymas) | |
| final int TRACE_GRAPHICAL = 55; // detaliai, grafiškai vaizduojami veiksmai su langeliais | |
| final int DEBUG = 50; // keičiant duomenis, veiksmai aprašomi konsolėje | |
| final int INFO = 40; // tik informacija apie svarbesnius pokyčius | |
| final int OFF = 0; // išjungta | |
| int trace_graphical_delay = 100; // programos sulėtinimo indeksas TRACE_GRAPHICAL režimui | |
| // logLevel gali būti keičiamas klaviatūra, programos eigoje: | |
| // r = TRACE_DRAW | |
| // t = TRACE | |
| // g = TRACE_GRAPHICAL | |
| // d = DEBUG | |
| // i = INFO | |
| // o = OFF | |
| int logLevel = INFO; | |
| int fps = 24; // frames per second; gali būti keičiamas rodyklėmis aukštyn/žemyn | |
| boolean isRunning = false; // kai true, programa | |
| boolean isMouseInputDisabled = false; // kai true, programa nereaguoja į pelę | |
| boolean wrap = true; // ar kirtus kraštą pereinama į priešingą pusę | |
| int[][] world = new int[rows][columns]; // dvimatis masyvas žaidimo būklei saugoti | |
| int mouseColumn = -1; // mouseColumn keičiamas judinant pelę pagal mouseX | |
| int mouseRow = -1; // mouseRow keičiamas judinant pelę pagal mouseY | |
| // debug'inamas langelis būna apibrėžtas spalvotai, kai įjungtas TRACE_GRAPHICAL logLevel'is | |
| int debugRow = -1; // debug'inamo langelio eilutė | |
| int debugColumn = -1; // debug'inamo langelio stulpelis | |
| color debugColor; // debug'inamo langelio spalva | |
| // ------------------------------------------------------------------------------------------- | |
| // Pagrindiniai nustatymai | |
| void settings() { | |
| size(window_width, window_height); // Nustato lango dydį | |
| } | |
| // Nustatymai | |
| void setup() { | |
| frameRate(fps); | |
| noLoop(); | |
| noStroke(); | |
| background(color_background); | |
| } | |
| // Piešimo funkcija, iškviečiama per redraw() | |
| // arba nuolat kviečiama paleidus loop() | |
| void draw() { | |
| if (isRunning) { | |
| tick(); | |
| } | |
| drawWorld(); | |
| } | |
| // Piešia pasaulį ir susijusius elementus | |
| void drawWorld() { | |
| log(TRACE_DRAW, "Drawing world at " + world_x + "," + world_y); | |
| // Lentos fonas, bus matomas tarp langelių kaip kraštinės | |
| fill(color_border); | |
| rect(world_x, world_y, world_width, world_height); | |
| for (int row = 0; row < rows; row++) { | |
| for (int column = 0; column < columns; column++) { | |
| int x = world_x + translateColumnToX(column); | |
| int y = world_y + translateRowToY(row); | |
| color color_cell = getCellColor(row, column); | |
| if (color_cell != color_border) { // praleidžiam, jei sutampa spalva | |
| fill(color_cell); | |
| rect(x, y, cell_width, cell_height); | |
| } | |
| if (!isRunning && isCellHovered(row, column)) { | |
| log(TRACE, "Cell " + row + "," + column + " is hovered"); | |
| fill(color_cell_hover); | |
| rect(x, y, cell_width, cell_height); | |
| } | |
| // Jei įjungtas grafinis trace'inimas, piešiam papildomus elementus | |
| if (isLogLevel(TRACE_GRAPHICAL)) { | |
| if (row == debugRow && column == debugColumn) { | |
| drawCellDebug(world_x, world_y, debugRow, debugColumn, debugColor); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // Piešia nurodytos spalvos rėmelį aplink nurodytą langelį | |
| void drawCellDebug(int x, int y, int row, int column, color strokeColor) { | |
| log(TRACE_DRAW, "Drawing debug stroke for " + row + "," + column + " at " + x + "," + y); | |
| pushStyle(); | |
| stroke(strokeColor); | |
| strokeWeight(cell_border*2); | |
| noFill(); | |
| rect(x, y, cell_width, cell_height); | |
| noStroke(); | |
| popStyle(); | |
| } | |
| // Pakeičia esamą pasaulį nauju | |
| void tick() { | |
| world = generateNextTick(); | |
| } | |
| // Generuoja naują pasaulį iš esamo | |
| int[][] generateNextTick() { | |
| int[][] world_new = cloneTwoDimensionalArray(world); | |
| for (int row=0; row < rows; row++) { | |
| for (int column=0; column < columns; column++) { | |
| // RULES: | |
| // Any live cell with fewer than two live neighbours dies, as if caused by underpopulation. | |
| // Any live cell with two or three live neighbours lives on to the next generation. | |
| // Any live cell with more than three live neighbours dies, as if by overpopulation. | |
| // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. | |
| int neighbours_alive = getAliveNeighbourCount(row, column); | |
| } | |
| } | |
| return world_new; | |
| } | |
| // Grąžina gyvų kaimynų kiekį | |
| int getAliveNeighbourCount(int row, int column) { | |
| /* Reliatyvios kaimynų koordinatės: | |
| {-1, -1}, {-1, 0}, {-1, 1}, | |
| { 0, -1}, { 0, 1}, | |
| { 1, -1}, { 1, 0}, { 1, 1} | |
| */ | |
| int neighbours_alive = 0; | |
| //if (isCellAlive(neighbour_row, neighbour_column)) { | |
| // neighbours_alive++; | |
| //} | |
| return neighbours_alive; | |
| } | |
| // Grąžina duotojo dvimačio masyvo kopiją | |
| int[][] cloneTwoDimensionalArray(int[][] source) { | |
| int[][] copy = new int[source.length][]; | |
| for (int i = 0; i < source.length; i++) { | |
| copy[i] = source[i].clone(); | |
| } | |
| return copy; | |
| } | |
| // Iškviečiamas kaskart pajudėjus pelei. | |
| // Nustato mouseRow ir mouseColumn kintamuosius ir iškviečia perpiešimą, jei jie pasikeitė | |
| void mouseMoved() { | |
| if (isMouseInputDisabled) { return; } | |
| int newMouseRow = translateYToRow(mouseY - world_y); | |
| int newMouseColumn = translateXToColumn(mouseX - world_x); | |
| if (isOutOfBounds(newMouseRow, newMouseColumn)) { return; } | |
| if (newMouseRow != mouseRow || newMouseColumn != mouseColumn) { | |
| mouseRow = newMouseRow; | |
| mouseColumn = newMouseColumn; | |
| if (mousePressed) { | |
| log(TRACE, "Toggling value of " + mouseRow + "," + mouseColumn); | |
| toggleCellValue(mouseRow, mouseColumn); | |
| } | |
| log(TRACE, "MouseColumn=" + mouseColumn + ", mouseRow=" + mouseRow); | |
| log(TRACE, "Redrawing.."); | |
| redraw(); | |
| } | |
| } | |
| void mousePressed() { | |
| if (isMouseInputDisabled) { return; } | |
| if (!isOutOfBounds(mouseRow, mouseColumn)) { | |
| log(TRACE, "Toggling value of " + mouseRow + "," + mouseColumn); | |
| toggleCellValue(mouseRow, mouseColumn); | |
| redraw(); | |
| } | |
| } | |
| void mouseDragged() { | |
| mouseMoved(); | |
| } | |
| // Pradeda žaidimą | |
| void startWorld() { | |
| if (isLogLevel(TRACE_GRAPHICAL)) { | |
| // įjungtas TRACE/TRACE_GRAPHICAL loglevel'os | |
| frameRate(120); | |
| redraw(); | |
| log(TRACE_GRAPHICAL, "Tracing a single tick.."); | |
| thread("tick"); // tick() paleidžiamas atskiram procese, kad galėtume piešti debugCell | |
| } else if (isLogLevel(DEBUG)) { | |
| // įjungtas DEBUG LogLevel'is | |
| log(DEBUG, "Drawing a single tick.."); | |
| tick(); | |
| redraw(); | |
| } else { | |
| // normalus programos paleidimas | |
| log(INFO, "Starting.."); | |
| isMouseInputDisabled = true; | |
| mouseColumn = -1; | |
| mouseRow = -1; | |
| frameRate(fps); | |
| isRunning = true; | |
| loop(); | |
| } | |
| } | |
| // Stabdo žaidimą | |
| void stopWorld() { | |
| log(INFO, "Stopping."); | |
| noLoop(); | |
| isMouseInputDisabled = false; | |
| isRunning = false; | |
| } | |
| void clearWorld() { | |
| log(INFO, "Resetting world.."); | |
| world = cloneTwoDimensionalArray(new int[rows][columns]); | |
| redraw(); | |
| } | |
| // Iškviečiamas paspaudus klaviatūros mygtuką | |
| // Pakeičia logLevel: | |
| // r = TRACE_DRAW | |
| // t = TRACE | |
| // g = TRACE_GRAPHICAL | |
| // d = DEBUG | |
| // i = INFO | |
| // o = OFF | |
| // | |
| // c = išvalo pasaulį | |
| // w = keičia kraštų sujungimą | |
| // + / - = padidina/sumažina trace_graphical_delay | |
| // ↑ / ↓ = padidina/sumažina kadrų per sekundę skaičių | |
| // <space> = paleidžia/stabdo žaidimą | |
| void keyPressed() { | |
| log(TRACE, "Key pressed: " + key); | |
| switch(key) { | |
| case 'r': | |
| logLevel = TRACE_DRAW; | |
| debugCell(-1, -1, 0); | |
| log(INFO, "Log level: TRACE_DRAW"); | |
| break; | |
| case 't': | |
| logLevel = TRACE; | |
| debugCell(-1, -1, 0); | |
| log(INFO, "Log level: TRACE"); | |
| break; | |
| case 'g': | |
| logLevel = TRACE_GRAPHICAL; | |
| debugCell(-1, -1, 0); | |
| log(INFO, "Log level: TRACE_GRAPHICAL"); | |
| break; | |
| case 'd': | |
| logLevel = DEBUG; | |
| log(INFO, "Log level: DEBUG"); | |
| break; | |
| case 'i': | |
| logLevel = INFO; | |
| log(INFO, "Log level: INFO"); | |
| break; | |
| case 'o': | |
| log(INFO, "Logging is off"); | |
| logLevel = OFF; | |
| break; | |
| case '+': | |
| trace_graphical_delay += 10; | |
| log(INFO, "Graphical trace delay: " + trace_graphical_delay); | |
| break; | |
| case '-': | |
| if (trace_graphical_delay > 10) { | |
| trace_graphical_delay -= 10; | |
| } | |
| log(INFO, "Graphical trace delay: " + trace_graphical_delay); | |
| break; | |
| case 'w': | |
| wrap = !wrap; | |
| log(INFO, "Wrap edges: " + (wrap ? "ON" : "OFF")); | |
| break; | |
| case 'c': // išvalo pasaulį | |
| if (isRunning) { | |
| stopWorld(); | |
| } | |
| clearWorld(); | |
| break; | |
| case ' ': // pradeda/stabdo programą | |
| if (isRunning) { | |
| stopWorld(); | |
| } else { | |
| startWorld(); | |
| } | |
| break; | |
| case CODED: | |
| if (keyCode == UP && fps < 120) { // didina kadrų per sekundę skaičių | |
| fps += 4; | |
| } else if (keyCode == DOWN && fps > 4) { // mažina kadrų per sekundę skaičių | |
| fps -= 4; | |
| } | |
| frameRate(fps); | |
| log(INFO, "Framerate=" + fps + " (actual: " + frameRate + ")"); | |
| break; | |
| } | |
| log(TRACE, "Redrawing.."); | |
| redraw(); | |
| } | |
| // Grąžina true, jei duotas langelio adresas yra už lentos ribų | |
| // (t.y. neigiamos arba per didelės koordinatės) | |
| boolean isOutOfBounds(int row, int column) { | |
| return row < 0 || row >= rows || column < 0 || column >= columns; | |
| } | |
| // Grąžina true, jei duotasis langelis turi virš savęs pelę | |
| boolean isCellHovered(int row, int column) { | |
| return mouseRow == row && mouseColumn == column; | |
| } | |
| // Grąžina true, jei langelis neturi reikšmės | |
| boolean isCellAlive(int row, int column) { | |
| return getCellValue(row, column) == VALUE_ALIVE; | |
| } | |
| void toggleCellValue(int row, int column) { | |
| if (isCellAlive(row, column)) { | |
| log(TRACE, row + "," + column + " is now DEAD"); | |
| setCellValue(row, column, VALUE_DEAD); | |
| } else { | |
| log(TRACE, row + "," + column + " is now ALIVE"); | |
| setCellValue(row, column, VALUE_ALIVE); | |
| } | |
| } | |
| // Grąžina langelio reikšmę | |
| int getCellValue(int row, int column) { | |
| return world[row][column]; | |
| } | |
| // Nustato langelio reikšmę | |
| void setCellValue(int row, int column, int[][] twoDimensionalArray, int value) { | |
| twoDimensionalArray[row][column] = value; | |
| log(DEBUG, "Setting " + row + "," + column + " to " + value); | |
| if (isLogLevel(TRACE_GRAPHICAL)) { | |
| debugCell(row, column, 1); | |
| } | |
| } | |
| void setCellValue(int row, int column, int value) { | |
| setCellValue(row, column, world, value); | |
| } | |
| // Nustto langelį kaip pažymėtą (neigiamą reikšmę) | |
| void setCellAlive(int row, int column) { | |
| log(DEBUG, "Setting " + row + "," + column + " as alive"); | |
| setCellAlive(row, column, world); | |
| } | |
| void setCellAlive(int row, int column, int[][] twoDimensionalArray) { | |
| setCellValue(row, column, twoDimensionalArray, VALUE_ALIVE); | |
| } | |
| void setCellDead(int row, int column) { | |
| log(DEBUG, "Setting " + row + "," + column + " as dead"); | |
| setCellValue(row, column, world, VALUE_DEAD); | |
| } | |
| // Nustato langelį kaip nepažymėtą (teigiamą reikšmę) | |
| void setCellDead(int row, int column, int[][] twoDimensionalArray) { | |
| setCellValue(row, column, twoDimensionalArray, VALUE_DEAD); | |
| } | |
| // Grąžina duotojo langelio ženklo spalvą | |
| color getCellColor(int row, int column) { | |
| return translateValueToColor(getCellValue(row, column)); | |
| } | |
| color translateValueToColor(int value) { | |
| return color_value[value]; | |
| } | |
| // Paverčia stulpelio indeksą į x koordinatę lentoje | |
| int translateColumnToX(int column) { | |
| return column * (cell_width + cell_border); | |
| } | |
| // Paverčia eilutės indeksą į y koordinatę lentoje | |
| int translateRowToY(int row) { | |
| return row * (cell_height + cell_border); | |
| } | |
| // Paverčia x koordinatę lentoje į stulpelio indeksą | |
| int translateXToColumn(int x) { | |
| return x / (cell_width + cell_border); | |
| } | |
| // Paverčia y koordinatę lentoje į eilutės indeksą | |
| int translateYToRow(int y) { | |
| return y / (cell_height + cell_border); | |
| } | |
| // Grąžina true, jei esamas logLevel yra detalesnis arba lygus duotajam argumentui | |
| boolean isLogLevel(int level) { | |
| return level <= logLevel; | |
| } | |
| // Spausdina message, jei esamas logLevel atitinka duotąjį level (yra detalesnis arba lygus) | |
| void log(int level, String message) { | |
| if (isLogLevel(level)) { | |
| println(message); | |
| } | |
| } | |
| // Sustabdo programą nurodydam laikui, jei esamas logLevel atitinka duotąjį level | |
| void debugDelay(int level, int milliseconds) { | |
| if (isLogLevel(level)) { | |
| delay(milliseconds); | |
| } | |
| } | |
| // Nustato debug'inamą langelį ir perpiešia ekraną | |
| void debugCell(int row, int column, int debugColorIndex) { | |
| if (!isLogLevel(TRACE_GRAPHICAL)) { return; } | |
| debugRow = row; | |
| debugColumn = column; | |
| debugColor = color_debug[debugColorIndex]; | |
| redraw(); | |
| debugDelay(TRACE_GRAPHICAL, trace_graphical_delay); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment