# My projects library #4! Gallery Megathread

**URL:** https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103
**Category:** Gallery
**Created:** [July 7, 2021, 11:46am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103 "2021-07-07T11:46:48Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 7, 2021, 11:46am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/1 "2021-07-07T11:46:48Z")

</div>

Here are some of my projects! I hope you get some ideas/inspiration from it : P

There are 3 previous megathreads with 40 projects in total!

- [library #1](https://discourse.processing.org/t/my-projects-library-codemasterxs-gallery-megathread/26301)
- [library #2](https://discourse.processing.org/t/my-projects-library-2-codemasterxs-gallery-megathread/27161)
- [library #3](https://discourse.processing.org/t/my-projects-library-3-gallery-megathread/29696)

If you have any questions regarding the projects, use the #[project number] while referencing them!  
Any suggestions/ideas are very welcome! Enjoy!

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 7, 2021, 11:51am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/2 "2021-07-07T11:51:51Z")

</div>

**#41 - Quasi console V0**  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/c/c88d60cbaea509c12f62d1b275a28f2c4deac833.png)

> **Code**
>
> ```auto
> import javax.swing.JOptionPane;
> String pLines = "Welcome to quasi console!\n ";
> void setup() {
> surface.setLocation(-width*2,-height*2);
> surface.setVisible(false);
> String strInp = JOptionPane.showInputDialog(null,pLines );
> pLines+="\n"+strInp;
> }
> void draw() {
> String strInp = JOptionPane.showInputDialog(null,pLines );
> pLines+="\n"+strInp;
> if(strInp.equals("stopConsole")) exit();
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 8, 2021, 12:35pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/3 "2021-07-08T12:35:33Z")

</div>

**#42 - Quasi console V01**  
Changelog:

- commands require “!” as first letter
- commands are no longer case sensitive
- added more commands
- renamed command “stopConsole” to “!stop”
- prevented crashing from null entries
- added a confirmation after !stop
- can exit program by pressing the “cancel” button or the “x” button

> **Code**
>
> ```auto
> import javax.swing.JOptionPane;
> String pLines = "Welcome to quasi console!\n ";
> int dialogButton = JOptionPane.YES_NO_OPTION;
> void setup() {
> surface.setLocation(-width*2, -height*2);
> surface.setVisible(false);
> }
> void draw() {
> String strInp = getInput(0, pLines);
> if (strInp!=null) {
> println("User Input: "+strInp);
> pLines+=((pLines.length()==0)? "" : "\n")+strInp;
> if (strInp.charAt(0)=='!') executeCommand(strInp);
> } else exit();
> }
> String getInput(int windowType, String text) {
> if (windowType==0) {
> return JOptionPane.showInputDialog(null, text );
> }
> return "";
> }
> void executeCommand(String text) {
> println("identifying the command: " + text);
> String segments[] = split(text, " ");
> if (eic(text, "!stop")) if (JOptionPane.showConfirmDialog (null, "Do you want to exit Quasi Console?", "Warning", dialogButton)==dialogButton) exit();
> if (eic(text, "!clearConsole")) pLines="";
> //###################COMMANDS RELATED TO TIME
> if (eic(text, "!time")) pLines+="\nCONSOLE: current time is: " + nf(hour(), 2)+":"+nf(minute(), 2)+":"+nf(second(), 2);
> if (eic(text, "!date")) pLines+="\nCONSOLE: (D/M/Y) current date is: " + day()+". "+month()+". "+year();
> //###################COMMANDS RELATED TO CANVAS
> if (segments.length>2) if (eic(segments[0], "!window")) {
> if (eic(segments[1], "show")) { //######COMMANDS RELATED TO DISPLAYING CANVAS
> if (eic(segments[2], "true")) {
> surface.setVisible(true); 
> surface.setLocation(0, 0);
> } else if (eic(segments[2], "false")) {
> surface.setVisible(false); 
> surface.setLocation(-width*2, -height*2);
> }// else if(eic(segments[2], "check")) pLines+="\nCONSOLE: window visible: " + "unknown";
> }
> }
> }
> boolean eic(String s1, String s2) {
> return(s1.equalsIgnoreCase(s2));
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 9, 2021, 12:13pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/4 "2021-07-09T12:13:25Z")

</div>

**#42 Circular pattern**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b5edaf52ca749ec688c0051e66775eee31711338.png)

> **Code**
>
> ```auto
> //This code is hideous, it is just a mess of trigenometry : P
> int n = 40;
> void setup() {
> size(600, 600);
> }
> void draw() {
> background(0);
> stroke(255, 100);
> float sqrt2 = sqrt(2), r = width*0.4;
> for (int i = 0; i < 4; i++) {
> displaySquare( i, 20, 300, 300, r);
> displaySquare( i-2, 20, 300+cos(HALF_PI*(i+0.5))*r*sqrt2, 300+sin(HALF_PI*(i+0.5))*r*sqrt2, r);
> displaySquare( i+2, 20, 300+cos(HALF_PI*i)*r, 300+sin(HALF_PI*i)*r, r);
> displaySquare( i+1, 20, 300+cos(HALF_PI*i)*r, 300+sin(HALF_PI*i)*r, r);
> }
> }
> void displaySquare(float d, int n, float cx, float cy, float r) {
> float r2 = r*sqrt(2);
> translate(cx, cy);
> PVector p1 = new PVector(cos((d+1)*HALF_PI)*r, sin((d+1)*HALF_PI)*r);
> PVector p0 = new PVector(cos((d+0.5)*HALF_PI)*r2, sin((d+0.5)*HALF_PI)*r2);
> PVector p2 = new PVector(cos((d)*HALF_PI)*r, sin((d)*HALF_PI)*r);
> line(p1.x, p1.y, p0.x, p0.y);
> line(p2.x, p2.y, p0.x, p0.y);
> for (float i = 0; i < n; i++) {
> float lp = i/n;
> line( lerp(p0.x, p1.x, lp), lerp(p0.y, p1.y, lp), lerp(p0.x, p2.x, 1-lp), lerp(p0.y, p2.y, 1-lp));
> }
> translate(-cx, -cy);
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 12, 2021, 9:48pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/5 "2021-07-12T21:48:45Z")

</div>

**#43 Sudoku UI V0**

Solved

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f4c83da3db00f9b2c6c712ab25bbbb063520a7c5.png)  
(Mid game)  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/e/e7cb60a8d0faacadf34d433748ea73dda8143ea2.png)

> **Code**
>
> ```auto
> //sudoku | dictionary - grid - 9x9 | cell - 3x3 | slot - 1x1
> int grid[][] = new int[9][9];
> boolean locked[][] = new boolean[9][9];
> boolean editing = false, editLocked=false, showMoves=false, showCovered=true;
> int num = 9, moves = 0, sel =1;
> float scl=64;
> float scl2=128, p2x = 646, p2y = 115;
> float scl3=96, p3x = 646, p3y = 19;
> float scl4X=96,scl4Y=24, p4x=934,p4y=499;
> String loadString = "873410900065028070020703000540000210208007490690080000480000500700031609010009807";
> void setup() {
> size(1100, 576);
> textAlign(3, 3);
> textSize(scl*0.6);
> if(loadString.length()==81) loadBlueprint(loadString);
>   
> }
> void draw() {
> background(0);
> if(showCovered) for(int i = 0; i < num; i++) for(int j = 0; j < num; j++) if(grid[i][j]==sel && sel!=0) showCovered(i,j);
> noFill(); 
> //stroke(255, 20);
> noStroke();
> textSize(scl*0.6);
> for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) { //drawing the main grid
> fill(0,0,255,50);
> if(locked[i][j]) square(i*scl,j*scl,scl);
> fill( ((grid[i][j]==sel)? color(255,0,55) : color(255) ) ); //all slots that match the selected number will be red-ish
> if (grid[i][j]!=0)text(grid[i][j], (i+0.5)*scl, (j+0.5)*scl);
> }
> stroke(255,40);
> for (int i = 1; i < 9; i++) line( i*scl, 0, i*scl, height); //drawing the stronger 3 lines
> for (int i = 1; i < 9; i++) line( 0, i*scl, height, i*scl);
> stroke(255);
> for (int i = 1; i < 4; i++) line( 3*i*scl, 0, 3*i*scl, height); //drawing the stronger 3 lines
> for (int i = 1; i < 3; i++) line( 0, 3*i*scl, height, 3*i*scl);
> //fill(255);
> textSize(scl2*0.6);
> noFill();
> for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { //drawing the select button area
> square(p2x+scl2*i, p2y+scl2*j, scl2);
> fill( ((sel==i+j*3+1)? color(255) : color(255, 150)));
> text(i+j*3+1, p2x+scl2*(i+0.5), p2y+scl2*(j+0.5));
> noFill();
> }
> textSize(scl3*0.65); 
> for (int i = 0; i < 4; i+=((i==1)? 2 : 1)) { //displaying the 3 upper, smaller buttons
> noFill();
> square(p3x+i*scl3, p3y, scl3);
> fill( ( (i==0 && sel==0)? color(255) : ((i==1)? color(255, 150) : (i==3 && editing)? color(255) : color(255, 150))));
> text( ( (i==0)? "x" : ((i==1)? "○" : "LK") ), p3x+(i+0.5)*scl3, p3y+scl3*0.4);
> }
> if(editing) { //displaying the SHOW MOVES/EDIT LOCKED/SHOW COVERED buttons
> textSize(scl4Y*0.5);
> for(int i = 0; i < 3; i++) {
> noFill();
> rect(p4x,p4y+i*scl4Y,scl4X,scl4Y);
> fill( (( i==0&&editLocked || i==1&&showMoves || i==2&&showCovered )? color(255) : color(255,150) ) );
> text( ((i==0)? "EDIT LOCKED" : ((i==1)? "SHOW MOVES" : "SHOW COVERED")),p4x+0.5*scl4X,p4y+(i+0.5)*scl4Y);
> }
> }
>   
> fill(255);
> textSize(scl*0.6);
> if(showMoves==true) text("MOVES: "+moves, 838, 530);
> }
> 
> void showCovered(int x, int y) {
> fill(0,200,40,20);
> noStroke();
> rect(0,y*scl,scl*num,scl);
> rect(x*scl,0,scl,scl*num);
> square( floor(x/3)*3*scl, floor(y/3)*3*scl, scl*3);
> }
> 
> void mousePressed() {
> 
> if (mouseButton==LEFT) {
> if (mouseX>p2x&&mouseY>p2y&&mouseX<p2x+3*scl2&&mouseY<p2y+3*scl2) { //number selection menu
> float mmx = mouseX-p2x, mmy = mouseY-p2y;
> sel = (int)(mmx/scl2+1)+ (int)(mmy/scl2)*3;
> }
> if (mouseX<scl*num) {//main grid - getting the mouse position and filling the slot
> int mx = constrain(floor(mouseX/scl),0,9), my = constrain(floor(mouseY/scl),0,9);
> if ((setSlot(mx, my, sel)==0)) grid[mx][my] = 0; //if the slot already has the number you selected, it will clear the slot
> if(locked[mx][my]==true && grid[mx][my] != 0) sel = grid[mx][my]; //if user clicks on a locked slot, selection will shift
> }
> if (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+4*scl3&&mouseY<p3y+scl3) { //The top 4 buttons (id = 3)
> int mx = floor((mouseX-p3x)/scl3);
> if (mx==0) sel = 0;
> if (mx==1) for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) if (grid[i][j]!=0&&locked[i][j]==false) grid[i][j]=0;
> if (mx==3) editing = !editing;
> }
> if(mouseX>p4x&&mouseY>p4y&&mouseX<p4x+scl4X&&mouseY<p4y+scl4Y*3) {
> int my = floor((mouseY-p4y)/scl4Y);
> if(my==0) editLocked = !editLocked;
> if(my==1) showMoves = !showMoves;
> if(my==2) showCovered = !showCovered;
> }
> } else if(mouseButton==RIGHT) {
> if (mouseX<scl*num && editing == true && editLocked) {//main grid - edit locked slots
> int mx = floor(mouseX/scl), my = floor(mouseY/scl);
> locked[mx][my] = !locked[mx][my];
> }
> }
> }
> void keyPressed() {
> if (keyCode>47&&keyCode<58) { //numbers 0-9
> int mx = floor(mouseX/scl), my = floor(mouseY/scl), nnum = keyCode-48;
> if(sel==nnum) if ((setSlot(mx, my, sel)==0)) grid[mx][my] = 0; //first time pressing the number will set the number as sel, second will input it
> sel=keyCode-48;
> }
> }
> int setSlot(int x, int y, int value) { //0 - slot matches the selection - will empty | 1 - success | 2 - slot is locked
> if (grid[x][y]==value) {
> println("slot is already filled with the same number!");
> return 0;
> }
> if (locked[x][y]==false||editing==true) {
> println("changing the slot!");
> moves++;
> grid[x][y] = value;
> } else { 
> println("FAILED-the slot is locked");
> return 2;
> }
> return 1;
> }
> void loadBlueprint(String blueprint) {
> if(blueprint.length()==81) {
> for(int i = 0; i < 81; i++) {
> int x = i%num, y = floor(i/num), number = int(blueprint.charAt(i)-48);
> grid[x][y]=number;
> locked[x][y]=(number!=0);
> }
> }
> }
> /* TODO: 
> add a feature to save up to 3 numbers per slot, so you can have help while saving it
> add a feature that shows the quantity of certain numbers next to number selector
> */
> 
> ```

This is my 10th attempt at this. There were a lot of issues beforehand. I had to actually start playing sudoku myself for a week (both online and irl) to find out what neat features I should add. I am extremely proud of the result!

Features:

- sudoku program
- can edit board mid-game
- can edit locked slots (enable while in LK mode and click EDIT LOCKED)
- can show moves (can toggle in the LK menu)
- can use green-guide feature - guide on placing numbers (look image 2 where there is a black slot in bottom left corner, that is the place to put number 2)
- can load a board (format is selfexplanitory)
- all of the numbers that are selected will become red-ish
- locked slots cannot be edited without LK mode
- locked slots are colored blue
- can use mouse/keyboard as input/number selection
- can clear the slot by pressing on it again with the same number selected
- can press x button to enable clear-mode (clear slots instead of placing them with mouse)
- can press O button to clear all non-locked slots
- can press LK button to toggle LK mode (LK - Lock)
- while in LK mode, a toggle menu will appear
- while in LK mode press right-mouse-button to toggle locked slots

Issues:

- there is a bug where you can delete a locked slot, not 100% sure about how to avoid it

Futurue versions will have:

- several random boards of varying difficulty
- can save up to 3 numbers per slot, to keep track of potential numbers
- a feature that tells you the quantity of each number (so you know if they are full)
- roboto (google) font
- window to input a blueprint string
- window to show you current blueprint
- a way to check for errors on completion

If you find any other issues, or have any suggestions for future versions, do tell. Any and all opinions are welcome here. I know that the color pallette isn’t the most good looking, but I am no artist.

Enjoy!

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 13, 2021, 3:17pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/6 "2021-07-13T15:17:32Z")

</div>

**#44 Sudoku V1**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/e/e51590b8b6c16dd0d7929654085965cc8c4909c3.png)

> **Code**
>
> ```auto
> //sudoku | dictionary - grid - 9x9 | cell - 3x3 | slot - 1x1
> import javax.swing.JOptionPane;
> int grid[][] = new int[9][9];
> int saved[][][] = new int[9][9][3];
> boolean locked[][] = new boolean[9][9];
> boolean editing = false, editLocked=false, showMoves=false, showCovered=true, showNotes=true;
> int num = 9, moves = 0, sel =1;
> float scl=64;
> float scl2=128, p2x = 646, p2y = 115;
> float scl3=96, p3x = 646, p3y = 19;
> float scl4X=96, scl4Y=18, p4x=934, p4y=499;
> float scl5X=21.333, scl5Y=16;
> float p6x = 934-3*scl4X, p6y=499, scl6X=96, scl6Y=24;
> PFont roboto;
> String loadString = "873410900065028070020703000540000210208007490690080000480000500700031609010009807";
> //EASY: 873410900065028070020703000540000210208007490690080000480000500700031609010009807
> //MEDIUM: 730095000600030709200000300068704190000000860000000004900108400051900270000050080
> //HARD: 080200009000300006960070001000000000090700200040001008070400500004030800306000000
> void setup() {
> roboto = createFont("Roboto-Light.ttf", 70);
> textFont(roboto);
> size(1100, 576);
> textAlign(3, 3);
> textSize(scl*0.6);
> if (loadString.length()==81) loadBlueprint(loadString);
> //for (int i = 0; i < 100; i++) saved[(int)random(9)][(int)random(9)][(int)random(3)]= (int)random(9);
> }
> void draw() {
> background(0);
> if (showCovered) for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) if (grid[i][j]==sel && sel!=0) showCovered(i, j);
> noFill(); 
> //stroke(255, 20);
> noStroke();
> for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) { //drawing the main grid
> textSize(scl*0.6);
> fill(0, 0, 255, 50);
> if (locked[i][j]) square(i*scl, j*scl, scl);
> fill( ((grid[i][j]==sel)? color(255, 0, 55) : color(255) ) ); //all slots that match the selected number will be red-ish
> if (grid[i][j]!=0)text(grid[i][j], (i+0.5)*scl, (j+0.5)*scl);
> textSize(scl5Y*0.9);
> if (showNotes&&locked[i][j] == false) for (int k = 0; k < 3; k++) {
> fill( ((saved[i][j][k]==sel)? color(255, 0, 55) : color(255) ));
> if (saved[i][j][k]!=0) text( saved[i][j][k], i*scl+(k+0.5)*scl5X, j*scl+0.5*scl5Y );
> }
> }
> stroke(255, 40);
> for (int i = 1; i < 9; i++) line( i*scl, 0, i*scl, height); //drawing the stronger 3 lines
> for (int i = 1; i < 9; i++) line( 0, i*scl, height, i*scl);
> stroke(255);
> for (int i = 1; i < 4; i++) line( 3*i*scl, 0, 3*i*scl, height); //drawing the stronger 3 lines
> for (int i = 1; i < 3; i++) line( 0, 3*i*scl, height, 3*i*scl);
> //fill(255);
> textSize(scl2*0.6);
> noFill();
> for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { //drawing the select button area
> square(p2x+scl2*i, p2y+scl2*j, scl2);
> fill( ((sel==i+j*3+1)? color(255) : color(255, 150)));
> text(i+j*3+1, p2x+scl2*(i+0.5), p2y+scl2*(j+0.5));
> noFill();
> }
> textSize(scl3*0.65); 
> for (int i = 0; i < 4; i+=((i==1)? 2 : 1)) { //displaying the 3 upper, smaller buttons
> noFill();
> square(p3x+i*scl3, p3y, scl3);
> fill( ( (i==0 && sel==0)? color(255) : ((i==1)? color(255, 150) : (i==3 && editing)? color(255) : color(255, 150))));
> text( ( (i==0)? "Ж" : ((i==1)? "Ф" : "LK") ), p3x+(i+0.5)*scl3, p3y+scl3*0.4);
> }
> if (editing) { //displaying the SHOW MOVES/EDIT LOCKED/SHOW COVERED buttons
> textSize(scl4Y*0.65);
> for (int i = 0; i < 4; i++) { //CHANGED TO 4
> noFill();
> rect(p4x, p4y+i*scl4Y, scl4X, scl4Y);
> fill( (( i==0&&editLocked || i==1&&showMoves || i==2&&showCovered || i==3&&showNotes)? color(255) : color(255, 150) ) );
> text( ((i==0)? "EDIT LOCKED" : ((i==1)? "SHOW MOVES" : ((i==2)?"SHOW COVERED":"SHOW NOTES"))), p4x+0.5*scl4X, p4y+(i+0.5)*scl4Y);
> }
> //LOAD/SAVE BUTTONS
> noFill();
> textSize(scl6Y*0.5);
> for (int i = 0; i < 2; i++) {
> rect(p6x, p6y+scl6Y*i, scl6X, scl6Y);
> text( ((i==0)? "LOAD BLUEPRINT" : "SAVE BLUEPRINT" ), p6x+scl6X*0.5, p6y+scl6Y*(i+0.5));
> }
> }
> 
> fill(255);
> textSize(scl*0.6);
> if (showMoves==true && !editing) text("MOVES: "+moves, 838, 530);
> }
> 
> void showCovered(int x, int y) {
> fill(0, 200, 40, 20);
> noStroke();
> rect(0, y*scl, scl*num, scl);
> rect(x*scl, 0, scl, scl*num);
> square( floor(x/3)*3*scl, floor(y/3)*3*scl, scl*3);
> }
> 
> void mousePressed() {
> if (mouseButton==LEFT) {
> if (mouseX>p2x&&mouseY>p2y&&mouseX<p2x+3*scl2&&mouseY<p2y+3*scl2) { //number selection menu
> float mmx = mouseX-p2x, mmy = mouseY-p2y;
> sel = (int)(mmx/scl2+1)+ (int)(mmy/scl2)*3;
> }
> if (mouseX<scl*num) {//main grid - getting the mouse position and filling the slot
> int mx = constrain(floor(mouseX/scl), 0, 9), my = constrain(floor(mouseY/scl), 0, 9);
> if ((setSlot(mx, my, sel)==0)) grid[mx][my] = 0; //if the slot already has the number you selected, it will clear the slot
> if (locked[mx][my]==true && grid[mx][my] != 0) sel = grid[mx][my]; //if user clicks on a locked slot, selection will shift
> }
> if (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+4*scl3&&mouseY<p3y+scl3) { //The top 4 buttons (id = 3)
> int mx = floor((mouseX-p3x)/scl3);
> if (mx==0) sel = 0;
> if (mx==1 && JOptionPane.showConfirmDialog (null, "Do you want to clear the board?", "Confirm", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_NO_OPTION) {
> for (int i = 0; i < num; i++) for (int j = 0; j < num; j++) {
> if (grid[i][j]!=0&&locked[i][j]==false) grid[i][j]=0;
> for (int k = 0; k < 3; k++) saved[i][j][k]=0;
> }
> moves=0;
> }
> if (mx==3) editing = !editing;
> }
> if (mouseX>p4x&&mouseY>p4y&&mouseX<p4x+scl4X&&mouseY<p4y+scl4Y*4) {
> int my = floor((mouseY-p4y)/scl4Y);
> if (my==0) editLocked = !editLocked;
> if (my==1) showMoves = !showMoves;
> if (my==2) showCovered = !showCovered;
> if (my==3) showNotes=!showNotes;
> }
>     
> if(mouseX>p6x&&mouseY>p6y&&mouseX<p6x+scl6X&&mouseY<p6y+scl6Y*2) {
> int my = floor((mouseY-p6y)/scl6Y);
> if(my==0) loadBlueprint( JOptionPane.showInputDialog(null, "ENTER BLUEPRINT" ) );
> if(my==1) saveBlueprint();
> }
>     
> } else if (mouseButton==RIGHT) {
> if (mouseX<scl*num && editing == true && editLocked) {//main grid - edit locked slots
> int mx = floor(mouseX/scl), my = floor(mouseY/scl);
> locked[mx][my] = !locked[mx][my];
> }
> if (mouseX<scl*num) {
> int mx = constrain(floor(mouseX/scl), 0, 9), my = constrain(floor(mouseY/scl), 0, 9);
> if (showNotes==true) {
> int mx2 = floor(map(mouseX-mx*scl, 0, scl, 0, 3));
> saved[mx][my][mx2] = ((saved[mx][my][mx2]==sel)? 0 : sel);
> }
> }
> }
> }
> void keyPressed() {
> if (keyCode>47&&keyCode<58) { //numbers 0-9
> int mx = floor(mouseX/scl), my = floor(mouseY/scl), nnum = keyCode-48;
> if (sel==nnum) if ((setSlot(mx, my, sel)==0)) grid[mx][my] = 0; //first time pressing the number will set the number as sel, second will input it
> sel=keyCode-48;
> }
> }
> int setSlot(int x, int y, int value) { //0 - slot matches the selection - will empty | 1 - success | 2 - slot is locked
> if (grid[x][y]==value && (!locked[x][y]||editing)) {
> println("slot is already filled with the same number!");
> return 0;
> }
> if (locked[x][y]==false||editing==true) {
> println("changing the slot!");
> moves++;
> grid[x][y] = value;
> } else { 
> println("FAILED-the slot is locked");
> return 2;
> }
> return 1;
> }
> void loadBlueprint(String blueprint) {
> if (blueprint.length()==81) {
> for (int i = 0; i < 81; i++) {
> int x = i%num, y = floor(i/num), number = int(blueprint.charAt(i)-48);
> grid[x][y]=number;
> locked[x][y]=(number!=0);
> for(int k = 0; k < 3; k++) saved[x][y][k]=0;
> }
> }
> }
> String saveBlueprint() {
> String output="";
> for (int j = 0; j < num; j++) for (int i = 0; i < num; i++) output+=grid[i][j];
> println("Blueprint:"+output);
> JOptionPane.showMessageDialog(frame, "Current blueprint: [Available in console]\n"+output);
> return output;
> }
> void mouseWheel(MouseEvent event) {
> int e = event.getCount();
> sel= (sel-e)%(num+1);
> if(sel<0) sel = num;
> println(e,sel);
> }
> /* TODO: 
> the error checker will store the quantity of numbers instead of just if they are there.
> Add a LOAD/SAVE | Will be replaced with the BLUEPRINT button. It will make a popup, where it will ask you what you want
> so 1) SAVE 2) LOAD -> next menu, choose difficulty (1:easy,2:medium,3:hard)-> there are x blueprints of [difficulty], choose a number, -1 for random
>  
> load/save prompt should show up if clicked  
> NEW CONTENT:
> - can save up to 3 numbers per slot with right click
> - roboto light font
> - confirmation before board erasure
> - can save/load blueprints mid game
> - scroll mouse wheel to change selection
> */
> 
> ```

FEATURES:

- can save up to 3 numbers per slot with right click
- font changed to roboto light (if you have it in the data folder, I can’t share it with code)
- popup window appears before you can erase the board
- can save/load blueprints mid game
- can use mouse wheel to change selection
- moves are not shown while in LK mode
- erasing the board now resets moves counter
- retextured ERASER and CLEAR buttons

BUGFIXES:

- BUG#0001 - double clicking on a locked slot will clear it even while not in LK mode

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 17, 2021, 1:10pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/7 "2021-07-17T13:10:52Z")

</div>

**#45 Mastermind puzzle game**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/bb834d973ae42f8052e55d6a461515274c1b80c6.png)

> **Code**
>
> ```auto
> int tries = 12, len = 4, clrs = 6, attempts = 0, sel = 1;
> int grid[][] = new int[tries][len]; //[x][] - vertical | [][x] - horizontal
> float scl = 48;
> color colors[] = new color[clrs+1]; //0 - transparent, 1-6 (default) are colored
> String result[] = new String[tries]; //shows O or X or ////
> float p2x = 352, p2y=0, p2W = scl, p2maxH = tries*scl; //color picker
> float p3x = 328, p3y = 0, p3W = 24, p3H=p2maxH; //confirm vertical bar (only useful if line is full)
> boolean showPassword=false; //show password at the start of the game (testing)
> boolean ended = false;
> int password[] = new int[len]; //password
> void setup() {
> size(400, 640);
> textAlign(LEFT, CENTER);
> textSize(scl*0.6);
> colorMode(HSB);
> colors[0] = color(0);
> for (int i = 1; i < colors.length; i++) colors[i] = color(map(i, 1, colors.length, 0, 255), 255, 255); //saving bright color values
> password = generateUniquePassword(len, clrs); //generate a code, where there is max 1 of each number, (4423 is not vaild)
> }
> void draw() {
> background(0);
> for (int j = 0; j < tries; j++) { //draw the grid
> if (attempts==j) { //highlight the active row
> noStroke();
> fill(255, 50);
> rect(0, j*scl, len*scl+2, scl);
> }
> for (int i = 0; i < len; i++) {
> stroke(255, 60);
> noFill();
> square((i)*scl, (j)*scl, scl);
> fill( colors[grid[j][i]]);
> if (j<=attempts && grid[j][i] != 0) circle( (i+0.5)*scl, (j+0.5)*scl, scl*0.8); //display circles into squares
> }
> if (result[j] != null) displayText(result[j]+"", (len+0.1)*scl, (j+0.5)*scl, color(255)); //display XOXX
> }
> stroke(255);
> for (int i = 0; i < len; i++) { //display the bottom line with solution
> noFill();
> square(i*scl, height-scl-1, scl);
> fill( colors[password[i]] );
> if (showPassword || ended) circle( (i+0.5)*scl, height-scl*0.5-1, scl*0.8); //show solution if game ended/showPassword==true
> } //(next line) show number of attempts used
> displayText(((!ended)?"ATTEMPTS:"+attempts:((attempts<tries)?"WON!!! A: "+attempts : "LOST")),(len+0.1)*scl,height-scl*0.5,color(255));
> stroke(0);//displaying color picker
> for (int i = 1; i <= clrs; i++) {
> fill(colors[i], ((i==sel)? 255 : 50));
> rect(p2x, p2y+p2maxH/clrs*(i-1), p2W, p2maxH/clrs);
> }
> //displaying the confirm bar | (next line) change colors based on user action, blank/hover/hover&mousePressed
> fill(255, (( (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+p3W&&mouseY<p3y+p3H)? ((mousePressed)? 255 : 150) : 50 )) );
> rect(p3x, p3y, p3W, p3H);
>   
> if(ended) noLoop();
> }
> void displayText(String txt, float x, float y, color clr) {
> fill(clr);
> text(txt, x, y);
> }
> void mousePressed() {
> if (mouseX>p2x && mouseX<p2x+p2W && mouseY>p2y && mouseY<p2y+p2maxH) { //color picker
> float my = mouseY-p2y;
> int myy = (int)(my/(p2maxH/clrs));
> sel = myy+1;
> }
> if (mouseX>0&&mouseX<len*scl&&mouseY>0+attempts*scl&&mouseY<0+(attempts+1)*scl) { //active input (highlighted line)
> int mmx = mouseX-0;
> int mx = (int)(mmx/scl);
> println(mx);
> grid[attempts][mx]=sel;
> }
> if (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+p3W&&mouseY<p3x+p3H) { //confirm bar hitbox
> boolean filled = true;
> for (int i = 0; i < len; i++) if (grid[attempts][i]==0) filled=false;
> if (filled) { //checks if all slots have been filled
> if (check(grid[attempts], password)) { //checks for perfect match
> println("YOU WIN!");
> ended = true;
> } else attempts++;
> if (attempts>=tries) { //out of tries
> println("YOU LOSE");
> ended = true;
> }
> }
> }
> }
> boolean check(int input[], int pass[]) {
> int res[] = new int[len]; //result, basically stores the things from password that are already used
> int correct = 0, halfCorrect=0;
> for (int i = 0; i < len; i++) if (input[i] == pass[i]) {
> res[i] = 2; //correct - 2 | HALFcorrect - 1
> correct ++;
> }
> for (int i = 0; i < len; i++) for (int j = 0; j < len||j==-1; j++) { //i is from guess, j is from password
> if (res[j]==0 && i!=j) { //searching for HALFcorrect numbers
> if (input[i]==pass[j]) {
> halfCorrect++;
> res[j]=1;
> j=-1;
> }
> }
> }
> result[attempts]=modifyFormat(correct, halfCorrect);
> return(correct==len);
> }
> String modifyFormat(int cor, int hCor) { //modifying format of outut to n*O+m*X OR ////
> String output = "";
> for (int i = 0; i < cor; i++) output+="O";
> for (int i = 0; i < hCor; i++) output+="X";
> if (cor==0 && hCor == 0) output = "////";
> return output;
> }
> int[] generateUniquePassword(int len, int cs) { //length of the password & colors in password
> int newPass[] = new int[len];
> ArrayList<Integer> available = new ArrayList<Integer>();
> for (int i = 1; i <= cs; i++) available.add(i); 
> for (int i = 0; i < len; i++) {
> int rndNum = (int)random(available.size());
> newPass[i]=available.get(rndNum);
> available.remove(rndNum);
> }
> return newPass;
> }
> 
> ```

> **Version 2**
>
> ```auto
> int tries = 12, len = 4, clrs = 6, attempts = 0, sel = 1;
> int grid[][] = new int[tries][len]; //[x][] - vertical | [][x] - horizontal
> float scl = 48;
> color colors[] = new color[clrs+1]; //0 - transparent, 1-6 (default) are colored
> String result[] = new String[tries]; //shows O or X or ////
> float p2x = 352, p2y=0, p2W = scl, p2maxH = tries*scl; //color picker
> float p3x = 328, p3y = 0, p3W = 24, p3H=p2maxH; //confirm vertical bar (only useful if line is full)
> boolean showPassword=false; //show password at the start of the game (testing)
> boolean ended = false;
> int password[] = new int[len]; //password
> void setup() {
> size(400, 640);
> textAlign(LEFT, CENTER);
> textSize(scl*0.6);
> colorMode(HSB);
> colors[0] = color(0);
> for (int i = 1; i < colors.length; i++) colors[i] = color(map(i, 1, colors.length, 0, 255), 255, 255); //saving bright color values
> password = generateUniquePassword(len, clrs); //generate a code, where there is max 1 of each number, (4423 is not vaild)
> }
> void draw() {
> background(0);
> for (int j = 0; j < tries; j++) { //draw the grid
> if (attempts==j) { //highlight the active row
> noStroke();
> fill(255, 50);
> rect(0, j*scl, len*scl+2, scl);
> }
> for (int i = 0; i < len; i++) {
> stroke(255, 60);
> noFill();
> square((i)*scl, (j)*scl, scl);
> fill( colors[grid[j][i]]);
> if (j<=attempts && grid[j][i] != 0) circle( (i+0.5)*scl, (j+0.5)*scl, scl*0.8); //display circles into squares
> }
> if (result[j] != null) displayText(result[j]+"", (len+0.1)*scl, (j+0.5)*scl, color(255)); //display XOXX
> }
> stroke(255);
> for (int i = 0; i < len; i++) { //display the bottom line with solution
> noFill();
> square(i*scl, height-scl-1, scl);
> fill( colors[password[i]] );
> if (showPassword || ended) circle( (i+0.5)*scl, height-scl*0.5-1, scl*0.8); //show solution if game ended/showPassword==true
> } //(next line) show number of attempts used
> displayText(((!ended)?"ATTEMPTS:"+attempts:((attempts<tries)?"WON!!! A:"+attempts : "LOST")),(len+0.1)*scl,height-scl*0.5,color(255));
> stroke(0);//displaying color picker
> for (int i = 1; i <= clrs; i++) {
> fill(colors[i], ((i==sel)? 255 : 50));
> rect(p2x, p2y+p2maxH/clrs*(i-1), p2W, p2maxH/clrs);
> }
> //displaying the confirm bar | (next line) change colors based on user action, blank/hover/hover&mousePressed
> fill(255, (( (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+p3W&&mouseY<p3y+p3H)? ((mousePressed)? 255 : 150) : 50 )) );
> rect(p3x, p3y, p3W, p3H);
>   
> if(ended) noLoop();
> }
> void displayText(String txt, float x, float y, color clr) {
> fill(clr);
> text(txt, x, y);
> }
> void mousePressed() {
> if (mouseX>p2x && mouseX<p2x+p2W && mouseY>p2y && mouseY<p2y+p2maxH) { //color picker
> float my = mouseY-p2y;
> int myy = (int)(my/(p2maxH/clrs));
> sel = myy+1;
> }
> if (mouseX>0&&mouseX<len*scl&&mouseY>0+attempts*scl&&mouseY<0+(attempts+1)*scl) { //active input (highlighted line)
> int mmx = mouseX-0;
> int mx = (int)(mmx/scl);
> println(mx);
> grid[attempts][mx]=sel;
> }
> if (mouseX>p3x&&mouseY>p3y&&mouseX<p3x+p3W&&mouseY<p3x+p3H) { //confirm bar hitbox
> boolean filled = true;
> for (int i = 0; i < len; i++) if (grid[attempts][i]==0) filled=false;
> if (filled) { //checks if all slots have been filled
> if (check(grid[attempts], password)) { //checks for perfect match
> println("YOU WIN!");
> ended = true;
> } else attempts++;
> if (attempts>=tries) { //out of tries
> println("YOU LOSE");
> ended = true;
> }
> }
> }
> }
> boolean check(int input[], int pass[]) {
> int res[] = new int[len]; //result, basically stores the things from password that are already used
> int correct = 0, halfCorrect=0;
> for (int i = 0; i < len; i++) if (input[i] == pass[i]) {
> res[i] = 2; //correct - 2 | HALFcorrect - 1
> correct ++;
> }
> for (int i = 0; i < len; i++) for (int j = 0; j < len||j==-1; j++) { //i is from guess, j is from password
> if (res[j]==0 && i!=j) { //searching for HALFcorrect numbers
> if (input[i]==pass[j]) {
> halfCorrect++;
> res[j]=1;
> j=-1;
> }
> }
> }
> result[attempts]=modifyFormat(correct, halfCorrect);
> return(correct==len);
> }
> String modifyFormat(int cor, int hCor) { //modifying format of outut to n*O+m*X OR ////
> String output = "";
> for (int i = 0; i < cor; i++) output+="O";
> for (int i = 0; i < hCor; i++) output+="X";
> if (cor==0 && hCor == 0) output = "////";
> return output;
> }
> int[] generateUniquePassword(int len, int cs) { //length of the password & colors in password
> int newPass[] = new int[len];
> ArrayList<Integer> available = new ArrayList<Integer>();
> for (int i = 1; i <= cs; i++) available.add(i); 
> for (int i = 0; i < len; i++) {
> int rndNum = (int)random(available.size());
> newPass[i]=available.get(rndNum);
> available.remove(rndNum);
> }
> return newPass;
> }
> void keyPressed() {
> if (keyCode>47&&keyCode<49+clrs) {
> sel = constrain(1,keyCode-48,clrs-1);
> }
> }
> void mouseWheel(MouseEvent event) {
> int e = -event.getCount();
> sel= (sel-e)%(clrs);
> if(sel<1) sel = clrs;
> println(e,sel);
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 30, 2021, 1:14pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/8 "2021-07-30T13:14:51Z")

</div>

**#46 Simple Mine-Sweeper**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/85ab21f4ba3f15db18487de885f258e23534dcf9.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/172ef68ab1b141fe6ee1dc554e33940ad4df6be0.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/d471fbcabe2ffc0427fd673312ffee6ec4114784.png)  
(Won, Playing, Lost)

> **Code**
>
> ```auto
> int a = 10; //width and height of grid
> int grid[][] = new int[a][a];
> int scl = 600/a, m = 10;
> boolean show[][] = new boolean[a][a];
> boolean flagged[][] = new boolean[a][a];
> int RESULT = 0; //-1: lost 0: undecided 1: won
> void setup() {
> size(600, 600);
> grid = newGrid(a, m);
> textAlign(3, 3);
> textSize(scl*0.6);
> }
> void draw() {
> background(0);
> stroke(255, 50);
> for (int i = 1; i < a; i++) {
> line( i*scl, 0, i*scl, height);
> line( 0, i*scl, width, i*scl);
> }
> for (int i = 0; i < a; i++) for (int j = 0; j < a; j++) {
> if (show[i][j]||RESULT==1) {
> fill(100);
> square(i*scl, j*scl, scl);
> fill(255);
> if (grid[i][j] > 0) text(grid[i][j], (i+0.5)*scl, (j+0.5)*scl);
> else if(grid[i][j]==-1) drawMine(i,j);
> } else {
> if (mouseX>i*scl&&mouseY>j*scl&&mouseX<(i+1)*scl&&mouseY<(j+1)*scl) {
> fill(200);
> } else fill(0);
> square(i*scl, j*scl, scl);
> if (flagged[i][j]) {
> fill(0, 0, 255, 50);
> square(i*scl, j*scl, scl);
> }
> }
> if(RESULT==-1 && grid[i][j]==-1) drawMine(i,j);
> }
> if(RESULT!=0) {
> textSize(100+sin(frameCount*0.05)*scl*0.25);
> if(RESULT==1) {
> //sin -1 1
> //+1= 0 2
> // *0.5 = 0 1
> fill(20,255,20,map( sin(frameCount*0.05), -1,1, 100,255));
> text("YOU WIN!!",width*0.5,height*0.5);
> } else if(RESULT==-1) {
> fill(255,20,20,map( sin(frameCount*0.05), -1,1, 100,255));
> text("YOU LOSE!!",width*0.5,height*0.5);
> }
> textSize(scl*0.6);
> }
> }
> void drawMine(int x, int y) {
> fill(255,0,0,150);
> circle((x+0.5)*scl,(y+0.5)*scl,scl*0.5);
> }
> 
> void mousePressed() {
> int mx = mouseX/scl, my = mouseY/scl;
> if (mouseButton==LEFT) {
> if (flagged[mx][my]==false) checkSlot(mx, my);
> } else if (mouseButton==RIGHT && RESULT==0) flagged[mx][my] = !flagged[mx][my];
> }
> void keyPressed() {
> if(key==' ') println(checkWin());
> }
> void checkSlot(int x, int y) {
> if (grid[x][y]==-1) {
> println("GAME OVER");
> RESULT=-1;
> } else if (RESULT==0) {
> show[x][y]=true;
> while (spreadVisible(x, y)>0);
> if (checkWin()) {
> RESULT=1;
> println("YOU WIN!");
> }
> }
> }
> int spreadVisible(int x, int y) {
> int num = 0;
> for (int i = 0; i < a; i++) for (int j = 0; j < a; j++) {
> if (grid[i][j]==0||i==x&&j==y) {
> for (int k = -1; k < 2; k++) for (int l = -1; l < 2; l++) if (inBounds(i, j, k, l, a)) {
> if (grid[i+k][j+l]!=-1) show[i+k][j+l]=true;
> }
> }
> }
> return num;
> }
> int[][] newGrid (int na, int nm) {
> int ngrid[][] = new int[na][na];
> if (nm>=na*na) nm = na*na-1; //to prevent infinite loops, the higher the mine:area ratio the longer it takes
> for (int i = 0, rx = (int)random(na), ry = (int)random(na); i < nm; i++, rx = (int)random(na), ry =(int)random(na)) {
> while (!canPlace(ngrid, rx, ry, 0)) {
> rx = (int)random(na); 
> ry = (int)random(na);
> }
> ngrid[rx][ry]=-1;
> }
> for (int i = 0; i < na; i++) for (int j = 0; j < na; j++) if (ngrid[i][j]!=-1) {
> int num = 0;
> for (int k = -1; k < 2; k++) for (int l = -1; l < 2; l++) if (!(k==0&&l==0) && inBounds(i, j, k, l, a)) {
> if (ngrid[i+k][j+l]==-1) num ++;
> }
> ngrid[i][j] = num;
> }
> a = na;
> m = nm;
> return ngrid;
> }
> boolean inBounds(int x, int y, int px, int py, int w) {
> return(x+px<w&&y+py<w&&x+px>=0&&y+py>=0);
> }
> boolean canPlace(int mgrid[][], int x, int y, int desired) {
> return(mgrid[x][y]==desired);
> }
> boolean checkWin() {
> boolean won = true; //first set it to true
> for (int i = 0; i < a; i++) for (int j = 0; j < a; j++) {
> if (!(show[i][j]==true&&grid[i][j]>=0 || show[i][j]==false&&grid[i][j]==-1)) won = false;
> }
> return won;
> }
> 
> ```

Notable features:

- flexible grid size and amount of mines
- flag slots to mark potential mines (cannot uncover unless you unflag)

A game I completed with 20x20 grid & 40 mines.

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b188c57d487e758506f2d6575ae4ceafaebe3ff1.png)

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [July 31, 2021, 12:54pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/9 "2021-07-31T12:54:29Z")

</div>

**#47 3n+1 sequence**  
Outputs it format: [sum] [highest number] [sequence…] […] […] [1]

> **Code**
>
> ```auto
> void setup() {
> printArray(path(1001));
> exit();
> }
> long[] path(long start) { //0 - sum 1 - max
> ArrayList<Long> values = new ArrayList<Long>();
> long num = start, sum = 0, maxNum=0;
> while(num!=1) {
> if(num%2==0) num*=0.5;
> else num=num*3+1;
> values.add(num);
> sum+=num;
> if(num>maxNum) maxNum=num;
> }
> long output[] = {sum,maxNum};
> output = expand(output,values.size()+2);
> for(int i = 0; i < values.size(); i++) output[i+2]=values.get(i);
> return output;
> }
> 
> ```

EDIT: there are 3 issues:  
1st: the entered number will not show up , so with path(1) you will get the output [0] [0] instead of [1] [1] [1]  
2nd: if you enter 0 you will never get the result out  
3rd: negative numbers enter an infinite loop. To stop this, just add in the while condition:

EDIT 2:  
Version without the above issues (But it is slightly slower)

> **Version 2**
>
> ```auto
> void setup() {
> printArray(path(16));
> exit();
> }
> long[] path(long start) { //0 - sum 1 - max
> ArrayList<Long> values = new ArrayList<Long>();
> long num = start, sum = 0, maxNum=0;
> values.add(num);
> while(num!=1&&!values.contains(num)) {
> if(num%2==0) num*=0.5;
> else num=num*3+1;
> values.add(num);
> sum+=num;
> if(num>maxNum) maxNum=num;
> println(num);
> }
> long output[] = {sum,maxNum};
> output = expand(output,values.size()+2);
> for(int i = 0; i < values.size(); i++) output[i+2]=values.get(i);
> return output;
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [August 1, 2021, 2:55pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/10 "2021-08-01T14:55:15Z")

</div>

nice work keep on 😉 😉 😉

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 4, 2021, 9:49am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/11 "2021-08-04T09:49:20Z")

</div>

**#48 String sum**  
Description: can add two integers (in string form) allowing you to have far larger range. Negative numbers are not supported.

The code contains a fibonacci example and limits allowing you to get the 1000 digit number (4781th value in sequence).

> **Code**
>
> ```auto
> String stringSum(String n1, String n2) {
> String output="";
> while(n1.length()!=n2.length()) {
> if(n1.length()>n2.length()) {
> n2 = "0"+n2;
> } else if(n2.length()>n1.length()) {
> n1 = "0"+n1;
> }
> }
> int rem = 0;
> for(int i = n1.length()-1; i >= 0; i--) {
> int sum = n1.charAt(i)+n2.charAt(i)-96+rem;
> rem=0;
> String abc = sum+"";
> output = abc.charAt(abc.length()-1)+output;
> if(abc.length()==2) rem = int(abc.charAt( abc.length()-2 ))-48;
> }
> if(rem>0)output = rem + output;
> return output;
> }
> void setup() {
> String a = "0";
> String b = "1";
> String c = "1";
> for(int i = 0; i < 4783; i++) {
> c = stringSum(a,b);
> a = b;
> b = c;
> println("["+i+"] L:",a.length(),"NEXT:\n"+a); //using a instead of c so it is aligned with the challenge
> }
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 11, 2021, 8:53pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/12 "2021-08-11T20:53:37Z")

</div>

**#49 Wolfram cellular automata**  
Edges - looped

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/4c6f8bf6249c02827182e162f3b64a71585c6f7a.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/bb4f78c3c917a48611e89bd44c1bfb1942eec3a5.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/e/ea0dc852abac6328b57672b29fc83ac5a1ffe0f2.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/a/a3aa339fb9ef7454e03b9219e94aaff335b0804a.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/777cbd79b36b5be5b7bc1e254a68e6cb62c7f79f.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/8e0cf0a75b228b5040b4db399a779875b2c54fa5.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/5/5709aa08f41bce5eae89c50b13c8de0d876d90e0.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/47427da86ac7fe4b49db8c386b86ae8c1e35cc0f.png)

> **Code**
>
> ```auto
> //wolfram - by timbebender
> ArrayList<int[]> grid = new ArrayList<int[]>();
> int w = 330, h = 1000, scl = 660/w;
> boolean rules[] = new boolean[8];
> void setup() {
> size(660, 600);
> genRule();
> }
> void mousePressed() { 
> genRule();
> }
> void genRule() {
> grid.clear();
> int startW[] = new int[w];
> startW[floor(w*0.5)] = 1;
> 
> for (int i = 0; i < rules.length; i++) rules[i] = (random(1)>0.5);
> int v = 0;
> for (int i = 0, m = 128; i < 8; i++, m*=0.5) v+=m*((rules[i])? 1 : 0);
> println(v);
> 
> grid.add(startW);
> }
> 
> void draw() {
> background(0); 
> noStroke();
> for (int j = 0; j < grid.size(); j++) {
> for (int i = 0; i < grid.get(j).length; i++) {
> fill( ((grid.get(j)[i]!=0)? color(255) : color(0) ) );
> square(i*scl, j*scl, scl);
> }
> }
> if (grid.size()*scl<height) {
> grid.add(generate(grid.get(grid.size()-1), rules));
> }
> }
> int[] generate(int[] prev, boolean[] ruls) {
> int next[] = new int[prev.length];
> next[0] = checkrule(prev[prev.length-1], prev[0], prev[1], ruls);
> next[next.length-1] = checkrule(prev[prev.length-2], prev[prev.length-1], prev[0], ruls); //ENDGES WRAP ARROUND
> for (int i = 1; i < next.length-1; i++) {
> next[i] = checkrule(prev[i-1], prev[i], prev[i+1], ruls);
> }
> return next;
> }
> int checkrule(int l, int c, int r, boolean[] ruls) {
> int combine = l*4+c*2+r;
> return 1*((ruls[combine])? 1 : 0);
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 12, 2021, 11:43am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/13 "2021-08-12T11:43:57Z")

</div>

**#50 Mutated Wolfram cellular automata**  
(Mutated or modified, whichever : P)  
The difference is that it doesn’t have rules for: [left cell, this cell, right cell] but also the 3 cells above them, so it generates the next row based on the previous two. It has 64 different rules (2^6), resulting in 2^64 different combination.

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/73544a00a3fc45787c3c036768e9927145a4800f.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b22abdb1161c1d4d70e8da67bebdf2bcb488b629.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/4a38e4f56e11cb304083ff6ec94ca108f123946b.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/8180bafb29cac3a6605a611806513dc0ad4afacf.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/0e253ca4d20ac0c66a9cbf6d8b2c9307913347a4.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/1ad71b90c5d69ec0796e00fd3f7b6a446642f1f4.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/6/6af327e6631f659758cd3e64e9fe9e8cbb1db4e0.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/88416fbaa6af1112bb801cdc80bd756330e013cd.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/0ecbd8324ca82eec05c7c3f0a7f62bd17bb8b2c8.png) ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/dba3962695831f89374d278fa1a5a955f319600b.png)

> **Code**
>
> ```auto
> int w = 600, h=600, gens=1;
> int grid[][] = new int[h][w];
> int rules[] = new int[64]; //2^6 = 64
> boolean loop = true;
> void setup() {
> size(600, 600);
> genBoard();
> }
> void draw() {
> background(0);
> loadPixels();
> for (int j = 0; j < gens; j++) for (int i = 0; i < w; i++) {
> int index = i+j*width;
> color clr = ((grid[j][i]==1)? color(255) : color(0) );
> pixels[index] = clr;
> }
> updatePixels();
> if (gens<h-1) {
> grid[gens] = generate(grid[gens-1], grid[gens], rules);
> gens++;
> }
> }
> void genBoard() {
> grid = new int[h][w];
> for (int i = 0; i < rules.length; i++) rules[i] = round(random(1));
> grid[0] = new int[w];
> grid[1] = new int[w];
> grid[1][300] = 1;
> gens=1;
> }
> int[] generate(int[] pp, int[] p, int[] rls) {
> int next[] = new int[w];
> if(!loop) for (int i = 1; i < w-1; i++) next[i] = checkRule(pp[i-1], pp[i], pp[i+1], p[i-1], p[i], p[i+1], rls);
> if(loop) for(int i = 0; i < w; i++) next[i] = checkRule(pp[((i-1>0)? i-1 : w-1)], pp[i], pp[(i+1)%w], p[((i-1>0)? i-1 : w-1)], p[i], p[(i+1)%w], rls);
> return next;
> }
> int checkRule(int pl, int pc, int pr, int cl, int cc, int cr, int[] rls) {
> int v = pl+pc*2+pr*4+cl*8+cc*16+cr*32;
> return rls[v];
> }
> void mousePressed() {
> genBoard();
> }
> 
> ```

Looping around the edges can be disabled.  
If you press the mouse, another pattern will be generated

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 13, 2021, 2:06pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/14 "2021-08-13T14:06:48Z")

</div>

**#51 Simple pong game**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b5d2afdb8d267d8ad04dcc2e10b6da207aa33271.png)

> **Code**
>
> ```auto
> int w = 400, h = 400;
> int scoreA = 0, scoreB = 0; //LEFT - A, RIGHT - B
> float speed=5, barSpeed=3, ballS = 20, ballX = w, ballY = h*0.5, xS = ((random(1)>=0.5)? 1 : -1), yS = ((random(1)>=0.5)? 1 : -1) * random(1,0.7);
> float barX=0.1, barH = 32, barA = h*0.5, barB = h*0.5;
> int mA = 0, mB = 0;
> void keyPressed() {
> if (keyCode==UP) mB=-1;
> if (keyCode==DOWN) mB=1;
> if (key=='w') mA=-1;
> else if (key=='s') mA=1;
> }
> void keyReleased() {
> if (mB==-1 && keyCode==UP ||mB==1 && keyCode==DOWN) mB=0;
> if (mA==-1 && key=='w' ||mA==1 && key=='s') mA=0;
> }
> 
> void setup() {
> size(800, 400);
> textSize(50);
> }
> void draw() {
> background(0);
> stroke(255);
> fill(255);
> line(w, 0, w, height);
> float sw1 = textWidth(scoreA+"");
> text(scoreA, w-sw1-5, textAscent());
> text(scoreB, w+5, textAscent());
> 
> //bar movements
> barA=constrain(barA+mA*barSpeed, barH, h-barH);
> barB=constrain(barB+mB*barSpeed, barH, h-barH);
> line( w*barX, barA-barH, w*barX, barA+barH);
> line( w*(2-barX), barB-barH, w*(2-barX), barB+barH);
> 
> //puck movement
> ballX+=speed*xS;
> ballY+=speed*yS;
> if (ballY>h-ballS*0.5||ballY<ballS*0.5) { //puck bounce of walls
> ballY = ((ballY>h*0.5)? h-ballS*0.5 : ballS*0.5 );
> yS*=-1;
> }
> //puck deflection
> if (ballX>(2-barX)*w-ballS*0.5&&ballX<(2-barX)*w+ballS*0.5 && ballY>barB-barH-ballS*0.5&&ballY<barB+barH+ballS*0.5) {
> ballX=(2-barX)*w-ballS*0.5;
> xS*=-1;
> }
> if (ballX>barX*w-ballS*0.5&&ballX<(barX)*w+ballS*0.5) {
> ballX=(barX)*w+ballS*0.5;
> xS*=-1;
> }
> 
> //drawing the puck
> square(ballX-ballS*0.5, ballY-ballS*0.5, ballS);
> //scoring system
> if (ballX>w*2) scoreA++;
> if (ballX<0) scoreB++;
> else if (ballX<-ballS) scoreB++;
> if (ballX>w*2||ballX<0) {
> ballX=w;
> ballY=h*0.5;
> xS=((random(1)>=0.5)? 1 : -1);
> }
> }
> 
> ```

There is a bug where the puck bounces off empty air. Not sure what’s wrong but yeah. Besides that, I didn’t implement ignore-case-controlls, so playing with capslock is impossible. Good luck playing!

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 13, 2021, 2:54pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/15 "2021-08-13T14:54:30Z")

</div>

**#52 SnakePVP**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/c/ca28eedda70614160d43d1981784da7e5337c306.png)

> **Code**
>
> ```auto
> int w = 20, h = 20, scl=30;
> int grid[][] = new int[w][h];
> color clr1 = color(255, 0, 0), clr2 = color(0, 0, 255);
> color trail1 = color(50, 0, 0), trail2 = color(0, 0, 50);
> int x1=5, y1=5, x2=15, y2=15;
> float d1 = 0, d2 = 2;
> int RESULT = 0;
> void setup() {
> size(660, 660);
> textAlign(3, 3);
> }
> void keyPressed() {
> d1 = ((keyCode==RIGHT)? 0 : ((keyCode==DOWN)? 1 : ((keyCode==LEFT)? 2 : ((keyCode==UP)? 3 : d1)))); 
> char pressed = ((key+"").toLowerCase()).charAt(0);
> d2 = ((pressed=='d')? 0 : ((pressed=='s')? 1 : ((pressed=='a')? 2 : ((pressed=='w')? 3 : d2))));
> }
> 
> void draw() {
> background(50, 255, 50);
> fill(0); 
> noStroke();
> square(scl, scl, scl*w);  
> int cx1 = round(cos(d1*HALF_PI)), cy1 = round(sin(d1*HALF_PI)), cx2 = round(cos(d2*HALF_PI)), cy2 = round(sin(d2*HALF_PI));
> if (grid[x1][y1]==0) grid[x1][y1] = 1;
> else RESULT = 2; //P1 LOSES
> if (grid[x2][y2]==0) grid[x2][y2] = 2;
> else RESULT = 1; //P2 LOSES
> if (RESULT==0) {
> x1+= cx1;
> y1+= cy1;
> x2+= cx2;
> y2+= cy2;
> }
> if(x1>=w||x1<0||y1>=h||y1<0) RESULT = 2;
> if(x2>=w||x2<0||y2>=h||y2<0) RESULT = 1;
> for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) if (grid[i][j]!=0) {
> fill( ((grid[i][j]==1)? trail1 : trail2) );
> square((i+1)*scl, (j+1)*scl, scl);
> }
> 
> fill(clr1);
> square((x1+1)*scl, (y1+1)*scl, scl);
> fill(clr2);
> square((x2+1)*scl, (y2+1)*scl, scl);
> if (RESULT!=0) {
> textSize(50);
> if (RESULT==1) {
> println("Player 1 wins!");
> fill(clr1, 150);
> text("PLAYER 1 WINS", width*0.5, height*0.5);
> } else if (RESULT == 2) {
> println("Player 2 wins!");
> fill(clr2, 150);
> text("PLAYER 2 WINS", width*0.5, height*0.5);
> }
> noLoop();
> }
> delay(300);
> }
> 
> ```

A PVP game for two players

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 19, 2021, 9:45pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/16 "2021-08-19T21:45:58Z")

</div>

**#53 Artistic Connect-n (4)**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/4bb9a130c836f6a60ab3bdfdddab01fc71960cf4.png)  
A program that allows you to play connect-n in a w \* h size grid. It allows you to resize the grid and the win requirement. There is no win message.

> **Code**
>
> ```auto
> int w = 7, h = 6, inRow = 4, turn = 1, mx=0;
> int grid[][] = new int[w][h];
> float scl = 70, rm = 0.85;
> color clr[] = {#FF001C, #75A2BF, #FFFF00};
> int bottomBuffer=5, x=floor(700*0.5-w*scl*0.5), y=600-bottomBuffer-int(h*scl), sideW=25;
> float coinX = y+scl*w/2, coinY = y - scl*0.6;
> int RESULT = 0;
> int wx1, wy1, wx2=4, wy2=4;
> void setup() {
> size(700, 600);
> }
> void draw() {
> mx = (int)constrain(map(mouseX, x, x+w*scl, 0, w), 0, w-1);
> noStroke();
> strokeWeight(1);
> noFill();
> background(0);
> displayBoard();
> if (RESULT!=0) { 
> displayWin(wx1, wy1, wx2, wy2);
> }
> }
> int checkWin() { //0-none, -1: yellow 1: red 2: out of space
> //checking for outofspace
> boolean outOfSpace=true;
> for (int i = 0; i < w && outOfSpace==true; i++)for (int j = 0; j < h && outOfSpace==true; j++) if (grid[i][j]==0) outOfSpace=false;
> if (outOfSpace) return 2;
> //check for horizontal win
> for (int j = 0; j < h; j++) for (int i = 0; i < w; i++) if (grid[i][j] != 0) for (int k = 0; k < 4; k++) {
> //HOR, VER, RDIG, LDIG
> int cx = ((k==0 || k == 2)? 1 : ((k==1)? 0 : -1)), cy = ((k==0)? 0 : 1);
> boolean win=true;
> int nx = i, ny = j, target = grid[i][j], row = 0;
> while (inBounds(nx, ny) && grid[nx][ny] == target) {
> row++;
> nx+=cx;
> ny+=cy;
> }
> if (row>=inRow) {
> wx1 = i;
> wy1 = j;
> wx2 = nx-cx;
> wy2 = ny-cy;
> return target;
> }
> }
> 
> return 0;
> }
> boolean inBounds(int x, int y) {
> return(x>=0&&x<w&&y>=0&&y<h);
> }
> void displayWin(int x1, int y1, int x2, int y2) {
> stroke(0, 255, 0); 
> strokeWeight(3);
> boolean t = true, f = false;
> float nx1 = x+(x1+0.5)*scl, ny1 = y+(y1+0.5)*scl, nx2 = x+(x2+0.5)*scl, ny2 = y+(y2+0.5)*scl;
> float dir = atan2(y2-y1, x2-x1);
> float cx = move(0, dir+HALF_PI, scl*0.5, t), cy = move(0, dir+HALF_PI, scl*0.5, f);
> line(nx1-cx, ny1-cy, nx2-cx, ny2-cy);
> line(nx1+cx, ny1+cy, nx2+cx, ny2+cy);
> noFill();
> arc(nx1, ny1, scl, scl, dir+HALF_PI, dir+3*HALF_PI);
> arc(nx2, ny2, scl, scl, dir-HALF_PI, dir+HALF_PI);
> }
> float move(float p, float dir, float dist, boolean x_) {
> if (x_) return p+cos(dir)*dist;
> else return p+sin(dir)*dist;
> }
> void displayBoard() {
> fill(#001540);
> rect(x-sideW, y, w*scl+2*sideW, h*scl+bottomBuffer, sideW, sideW, 0, 0);
> 
> fill(#003366);
> rect(x, y, w*scl, h*scl);
> for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
> fill( clr[grid[i][j]+1]);
> circle((i+0.5)*scl+x, (j+0.5)*scl+y, scl*rm);
> }
> fill(#001540);
> rect(x, y, w*scl, scl*(1-rm)*0.25);
> 
> fill(255, 20);
> rect(x+mx*scl, y, scl, scl*h);
> if(RESULT==0) coinX = constrain(lerp(coinX, x+(mx+0.5)*scl, 0.05), x+scl*0.5, x+(w-0.5)*scl);
> 
> fill(clr[turn+1]);
> circle(coinX, coinY, scl*(0.5+rm*0.5));
> }
> void mousePressed() {
> if (RESULT==0) {
> int y = h-1;
> while (grid[mx][constrain(y, 0, h)]!=0 && y>=0) y--;
> if (y>=0) { 
> grid[mx][y] = turn;
> turn*=-1;
> RESULT = checkWin();
> }
> }
> }
> 
> ```

set inRow to \>3, since everything less is not interesting. To resize the grid change w and h.

---

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [August 19, 2021, 10:07pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/17 "2021-08-19T22:07:23Z")

</div>

Nice and good working keep on that

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 20, 2021, 9:08am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/18 "2021-08-20T09:08:00Z")

</div>

**#53-2 Artistic Connect-n V2**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f9f0c2eb5345ae24619f49f5009ed516ead8e3bd.png)  
Changes:

- added win message
- more than one win can be displayed (look at picture)
- minor changes

> **Code**
>
> ```auto
> int w = 7, h = 6, inRow =4, turn = 1, mx=0, wUsed = 0; //wUsed - wins used
> int grid[][] = new int[w][h];
> float scl = 70, rm = 0.85; //rm - radius multiplier
> color clr[] = {#FF001C, #75A2BF, #FFFF00}; //red-empty-yellow
> int bottomBuffer=5, x=floor(700*0.5-w*scl*0.5), y=600-bottomBuffer-int(h*scl), sideW=25, RESULT = 0;
> float coinX = y+scl*w/2, coinY = y - scl*0.6;
> PVector w1[] = new PVector[4], w2[] = new PVector[4];
> void setup() {
> size(700, 600);
> textAlign(3,3);
> }
> void draw() {
> mx = (int)constrain(map(mouseX, x, x+w*scl, 0, w), 0, w-1);
> noStroke();
> strokeWeight(1);
> noFill();
> background(0);
> displayBoard();
> if (RESULT!=0) for(int i = 0; i < wUsed; i++) displayWin((int)w1[i].x,(int)w1[i].y,(int)w2[i].x,(int)w2[i].y);
> if (RESULT==2) displayWin(100,100,100,100);
> }
> int checkWin() { //0-none, -1: yellow 1: red 2: out of space
> boolean outOfSpace=true; //checking for outofspace
> int output = 0;
> for (int i = 0; i < w && outOfSpace==true; i++)for (int j = 0; j < h && outOfSpace==true; j++) if (grid[i][j]==0) outOfSpace=false;
> if (outOfSpace) return 2;
> //check connecting
> for (int j = 0; j < h; j++) for (int i = 0; i < w; i++) if (grid[i][j] != 0) for (int k = 0; k < 4; k++) {
> //HOR, VER, RDIG, LDIG
> int cx = ((k==0 || k == 2)? 1 : ((k==1)? 0 : -1)), cy = ((k==0)? 0 : 1);
> int nx = i, ny = j, target = grid[i][j], row = 0;
> while (inBounds(nx, ny) && grid[nx][ny] == target) {
> row++;
> nx+=cx;
> ny+=cy;
> }
> if (row>=inRow) {
> w1[wUsed] = new PVector(i,j);
> w2[wUsed] = new PVector(nx-cx,ny-cy);
> wUsed++;
> output = target;
> }
> }
> 
> return output;
> }
> boolean inBounds(int x, int y) {
> return(x>=0&&x<w&&y>=0&&y<h);
> }
> void displayWin(int x1, int y1, int x2, int y2) {
> stroke(0, 255, 0); 
> strokeWeight(3);
> boolean t = true, f = false;
> float nx1 = x+(x1+0.5)*scl, ny1 = y+(y1+0.5)*scl, nx2 = x+(x2+0.5)*scl, ny2 = y+(y2+0.5)*scl;
> float dir = atan2(y2-y1, x2-x1);
> float cx = move(0, dir+HALF_PI, scl*0.5, t), cy = move(0, dir+HALF_PI, scl*0.5, f);
> line(nx1-cx, ny1-cy, nx2-cx, ny2-cy);
> line(nx1+cx, ny1+cy, nx2+cx, ny2+cy);
> noFill();
> arc(nx1, ny1, scl, scl, dir+HALF_PI, dir+3*HALF_PI);
> arc(nx2, ny2, scl, scl, dir-HALF_PI, dir+HALF_PI);
> textSize(scl);
> if(RESULT==-1||RESULT==1) {
> fill(clr[RESULT+1]);
> text( ((RESULT==1)? "YELLOW" : "RED") + " WINS!", x+w*scl*0.5, y-scl);
> }
> if(RESULT==2) {
> fill(0,200,0);
> text( "OUT OF SPACE", x+w*scl*0.5, y-scl);
> }
> }
> float move(float p, float dir, float dist, boolean x_) {
> if (x_) return p+cos(dir)*dist;
> else return p+sin(dir)*dist;
> }
> void displayBoard() {
> fill(#001540);
> rect(x-sideW, y, w*scl+2*sideW, h*scl+bottomBuffer, sideW, sideW, 0, 0);
> 
> fill(#003366);
> rect(x, y, w*scl, h*scl);
> for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
> fill( clr[grid[i][j]+1]);
> circle((i+0.5)*scl+x, (j+0.5)*scl+y, scl*rm);
> }
> fill(#001540);
> rect(x, y, w*scl, scl*(1-rm)*0.25);
> 
> fill(255, 20);
> rect(x+mx*scl, y, scl, scl*h);
> if(RESULT==0) coinX = constrain(lerp(coinX, x+(mx+0.5)*scl, 0.05), x+scl*0.5, x+(w-0.5)*scl);
> 
> fill(clr[turn+1]);
> circle(coinX, coinY, scl*(0.5+rm*0.5));
> }
> void mousePressed() {
> if (RESULT==0) {
> int y = h-1;
> while (grid[mx][constrain(y, 0, h)]!=0 && y>=0) y--;
> if (y>=0) { 
> grid[mx][y] = turn;
> turn*=-1;
> RESULT = checkWin();
> }
> }
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 27, 2021, 10:00am UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/19 "2021-08-27T10:00:24Z")

</div>

**#54 2D simple collisions demo 1**

This is a simple demo for a 2D collision detection with rectangles. The only square that can move is the player. If you find any bugs, do tell!

> **Code**
>
> ```auto
> int px = 10, py = 10, a = 20;
> int cx = 0, cy = 0, speed = 1;
> obstacle o = new obstacle(275, 275, 50, 50);
> void setup() {
> size(600, 600);
> }
> void draw() {
> background(0);
> movePlayer();
> fill(255);
> square(px, py, a);
> o.display();
> }
> void movePlayer() {
> for (int i = 0; i < speed; i++) {
> int nx = px+cx, ny = py+cy;
> if(collision(nx,py,a,a, o.x,o.y,o.s,o.s2) == false) px = nx;
> if(collision(px,ny,a,a, o.x,o.y,o.s,o.s2) == false) py = ny;
> }
> }
> void keyPressed() {
> char ky = (key+"").toLowerCase().charAt(0);
> if (ky == 'a') cx = -1;
> if (ky == 'd') cx = 1;
> if (ky == 'w') cy = -1;
> if (ky == 's') cy = 1;
> }
> void keyReleased() {
> char ky = (key+"").toLowerCase().charAt(0);
> if (ky == 'a' && cx == -1) cx = 0;
> if (ky == 'd' && cx == 1) cx = 0;
> if (ky == 'w' && cy == -1) cy = 0;
> if (ky == 's' && cy == 1) cy = 0;
> }
> boolean collision(int x1, int y1, int s1, int s12, int x2, int y2, int s2, int s22) {
> if (x1>x2-s1&&y1>y2-s12&& x1<x2+s2 && y1<y2+s22) return true; //x2-s1, y2-s12, x2+s2, y2+s22
> return false;
> }
> class obstacle {
> int x, y, s, s2;
> obstacle(int x_, int y_, int s_, int s2_) {
> x = x_;
> y = y_;
> s = s_;
> s2 = s2_;
> }
> void display() {
> fill(0, 0, 255);
> rect(x, y, s, s2);
> }
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [August 30, 2021, 3:30pm UTC](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103/20 "2021-08-30T15:30:00Z")

</div>

**#55 Simple posterization filter**

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b08cc4d3793af09f3213d98df982bd77ab02e812.jpeg)

Posterization filter sets the maximum amount of colors used. All colors on the screen get converted into those. [explanation by josephh](https://discourse.processing.org/t/posterization-filter-explained/32001/3)

> **Code**
>
> ```auto
> int clrs = 3; //end has clrs^3 colors, (1-1, 2-8, 3-27, 4-64, 5-125, 6-216,...)
> color clr[];
> PImage img;
> void setup() {
> size(640,642);
> clr = generateColors(clrs);
> img = loadImage("house2.jpg");
> println(img.width,img.height);
> }
> void draw() {
> image(img,0,0); noLoop();
> loadPixels();
> for(int i = 0; i < width; i++) for(int j = 0; j < height*0.5; j++) {
> int in = i+j*width, off = floor(width*height*0.5);
> color base = pixels[in], chan = closest(base);
> pixels[in+off] = chan;
> }
> updatePixels();
> }
> color closest(color input) {
> int id=0;
> float d = -1;
> for(int i = 0; i < clr.length; i++) {
> float dis = dist(red(input),green(input),blue(input),red(clr[i]),green(clr[i]),blue(clr[i]));
> if(dis < d || d == -1) {
> id = i;
> d = dis;
> }
> }
> return clr[id];
> }
> 
> color[] generateColors(int c) {
> float a = 255/c;
> color nclr[] = new color[c*c*c];
> for(int i = 0; i < c; i++) for(int j = 0; j < c; j++) for(int k = 0; k < c; k++) {
> nclr[i+j*c+k*c*c] = color(i*a, j*a, k*a);
> }
> return nclr;
> }
> 
> ```

It is a simple project (if you are using the simple color cube solution). It can be upgraded at any time by changing the generateColors() function.

[Next page](https://discourse.processing.org/t/my-projects-library-4-gallery-megathread/31103.md?page=2)
