Using for loop to print grid in JavaScript - javascript

I am trying to create a small grid for connect four game using a four loop. I have printed circles for X and Y axis but I have only been able to print 1 row successfully, I am trying to print this seven times across the canvas but the for loop I have created does not seem to work.
var x = 30;
var y = 30;
function setup(){
createCanvas(300,300);
background(0);
for(i=0; i<=6; i++){
for(i=0; i<=6; i++){
x+=30;
circle(x, y, 20);
for(i=0; i<=6; i++){
y+=30;
circle(x, y, 20);
}
}
}
}
setup();
I am trying to achieve this:

Change your loop structure - iterate 7 times and increase y at the end of each iteration, and iterate within this loop where you render the circle, and increase x:
for (let i = 0; i < 6; i++) {
x = 30;
for (let j = 0; j < 7; j++) {
circle(x, y, 20);
x += 30;
}
y += 30;
}

You do have three loops that use i, and actually all loops will work on the same number, therefore the inner loop will loop 6times, than all three loops end. As your aim is to loop over x and y, just use them:
for(let x = 1; x < 6; x++) { // always declare variables with let!
for(let y = 1; y < 6; y++) {
circle(x * 30, y * 30, 20); // just keep as many varoables as necessary, the position can easily be derived from the index
}
}

Maybe this is what you need:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let cw = (canvas.width = 300),
cx = cw / 2;
let ch = (canvas.height = 300),
cy = ch / 2;
//the circles radius
let ar = 30;
//the red and yellow clees index
let red = [10, 23, 30, 31, 37, 40];
let gold = [16, 17, 24, 32, 38, 39];
let n = 0;// a counter
let cellw = cw / 7;// the width of a cell
//the loop:
for (let y = cellw / 2; y < ch; y += cellw) {
for (let x = cellw / 2; x < cw; x += cellw) {
ctx.beginPath();
ctx.arc(x, y, ar / 2, 0, 2 * Math.PI);
//set the color of the circles
for (let i = 0; i < red.length; i++) {
if (n == red[i]) {
ctx.fillStyle = "red";
break;
} else if (n == gold[i]) {
ctx.fillStyle = "gold";
break;
} else {
ctx.fillStyle = "white";
}
}
ctx.fill();
n++;
}
}
body {
background-color: #222;
overflow: hidden;
}
canvas {
background-color: #000;
display: block;
position:absolute;
margin: auto;
top:0;bottom:0;left:0;right:0
}
<canvas id="canvas"></canvas>

Yep, there's a problem in the for loop.
You just need to 2 loops for that.
for (let row = 0; row <= 6; row++) {
for (let column = 0; column <= 6; column++) {
circle(row * 30, column * 30, 20)
}
}

Related

Program integrated into html that creates a 4x4 grid and draws like Armin Hoffman

So far, I've done research into the design by Armin Hoffman (rubber band design). The objective is to create a grid of circles which can be selected to change from white to black and connect these circles in a natural fluid shape that avoids white circles but never traps them. I've been using Codecademy to learn the basics while copying and studying examples on the p5.js website and additionally following The Coding Train on Youtube (specifically: 7.4 mouse interaction and 7.6 clicking on objects).
Check #MauriceMeilleur on Twitter between Feb 2021 and Aug 2021
Also: https://discourse.processing.org/t/shape-generator-help-armin-hofmanns-rubber-band-shape-generator/33190
Every time I try to make a matrix or array of x and y values stored and to be used in the for loop within the draw/setup functions, it becomes invalid and it doesn't show the shapes I would like.
I know I'm missing info.
This is my latest trial:
class boundingBox {
createBox() {
stroke(0);
strokeWeight(3);
fill(255, 255, 255, 255);
rect(100, 100, 700, 700);
}
}
function Bubble(x, y, x1, y1, x2, y2, x3, y3) {
// creating a distinction from x/y private and x/y public
this.x = x;
this.y = y;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
//this.x = x = [225,350,475,600];
//this.y = y = [225,350,475,600];
// creating color public for later use
this.col = color(255);
// this expression works to make a public function within a private function
this.display = function() {
stroke(0);
fill(this.col);
// creating the ability to display the circles within the parameters set
//ellipse(this.x, this.y, 48,48);
// in theory this should loop through the x array position values against all the y values in it's array creating multiple circles
for (i = 0; i < 4; i++) {
ellipse(this.x /*[i]*/ , this.y, 100, 100);
ellipse(this.x1, this.y1, 100, 100);
ellipse(this.x2, this.y2, 100, 100);
ellipse(this.x3, this.y3, 100, 100);
}
}
//this.move = function() {
// //making the circles change position and act like they are moving within air
// this.x = this.x + random(-0.5, 0.5);
// this.y = this.y + random(-0.5, 0.5);
// this.x1 = this.x1 + random(-0.5, 0.5);
// this.y1 = this.y1 + random(-0.5, 0.5);
// //this.x = this.x + random(1, 0.5);
// //this.y = this.y + random(1, 0.5);
//}
// again expression to make function but this time implementing a clicking function
this.clicked = function() {
// calculating the distance from the circle center to help fill it with color and nothing else
var d = dist(mouseX, mouseY, this.x, this.y)
// diameter of the circle
if (d < 50) {
this.col = color(0, 0, 0)
}
}
//joinBubbles(bubbles); {
// bubbles.forEach(element => {
// let dis = dist(this.x, this.y, element.x, element.y);
// stroke(200, 200, 200, 127);
// line(this.x, this.y, element.x, element.y);
// });
//}
//}
//class lines {
// constructor(){
// this.x4 = x4;
// this.y4 = y4;
// this.x5 = x5;
// this.y5 = y5;
// }
// this.displayLine = function(){
// stroke(0)
// }
}
let bubbles = [];
let boxii = [];
function setup() {
createCanvas(1536, 1250);
for (let i = 0; i < 1; i++) {
boxii.push(new boundingBox());
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x = 200;
var y = i;
bubbles.push(new Bubble(x, y /*x1,y1*/ ));
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x1 = 375;
var y1 = i;
bubbles.push(new Bubble(x1, y1 /*x1,y1*/ ));
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x2 = 550;
var y2 = i;
bubbles.push(new Bubble(x2, y2 /*x1,y1*/ ));
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x3 = 700;
var y3 = i;
bubbles.push(new Bubble(x3, y3 /*x1,y1*/ ));
}
//for (let i = 0; i < 1; i++) {
//var x1 = 400;
//var y1 = 200;
//bubbles.push(new Bubble(x1,y1));
//}
//for (let i = 200; i < 1000; i+=200){
//var x2 = 200;
//var y2 = i;
//bubbles.push(new Bubble(x2,y2));
//}
}
function mousePressed() {
// checking where the mouse presses so that clicking outside the circle does nothing
for (let i = 0; i < bubbles.length; i++) {
//for (let i = 0; i < 4; i++) {
// using this function on all the circles and again using .this to bring properties from /bubble
bubbles[i].clicked();
}
}
function draw() {
background(140);
for (let i = 0; i < 1; i++) {
boxii[i].createBox();
}
for (let i = 0; i < bubbles.length; i++) {
//bubbles[i].move();
bubbles[i].display();
}
if (mousePressed) {
for (let i = 0; i < bubbles.length; i++) {
bubbles[i].display(fill(0))
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>

p5.js: Assigning a static unique colour to each ellipse in a group

As you can see, each ellipse is part of a wave object and the fill is getting applied on each frame over and over and giving this blinking effect on all ellipses. I want to take a random colour and assign to each ellipse when it is drawn so that it remains with that fill colour instead of defining a new colour at each frame. I tried a lot but couldn't achieve that. Any help would be appreciated.
class Wave {
constructor(amp, period, phase) {
this.amplitude = amp;
this.period = period;
this.phase = phase;
}
evaluate(x) {
return sin(this.phase + (TWO_PI * x) / this.period) * this.amplitude;
}
update() {
this.phase += 0.05;
}
}
let waves = [];
let y;
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
}
}
function draw() {
background(0);
for (let x = 0; x < width; x += 10) {
for (let wave of waves) {
y = wave.evaluate(x);
noStroke();
fill(random(255), random(255), random(255));
ellipse(x, y + height / 2, 6);
}
}
for (let wave of waves) {
wave.update();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Create a list of about 20 colors for each wave. Use color() to create a color:
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
colors = [];
for (let j = 0; j < 20; j++) {
colors.push(color(random(255), random(255), random(255)))
}
waves_colors.push(colors);
}
Use this color to draw the waves. Use the % (modulo) operator to compute the rest of an integra division. The colors are repeated after every 20 points:
for (let i = 0; i < 5; i++) {
wave = waves[i];
colors = waves_colors[i];
for (let j = 0; j < width/10; j ++) {
x = j*10;
y = wave.evaluate(x);
fill(colors[j % colors.length]);
ellipse(x, y + height / 2, 6);
}
}
class Wave {
constructor(amp, period, phase) {
this.amplitude = amp;
this.period = period;
this.phase = phase;
}
evaluate(x) {
return sin(this.phase + (TWO_PI * x) / this.period) * this.amplitude;
}
update() {
this.phase += 0.05;
}
}
let waves = [];
let waves_colors = [];
let y;
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
colors = [];
for (let j = 0; j < 20; j++) {
if (i % 2 == 1)
colors.push(color(0, 0, 255, random(128,255)));
else
colors.push(color(random(255), random(255), random(255)))
}
waves_colors.push(colors);
}
}
function draw() {
background(0);
noStroke();
for (let i = 0; i < 5; i++) {
wave = waves[i];
colors = waves_colors[i];
for (let j = 0; j < width/10; j ++) {
x = j*10;
y = wave.evaluate(x);
fill(colors[j % colors.length]);
ellipse(x, y + height / 2, 6);
}
}
for (let wave of waves) {
wave.update();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

Outputting an array of text values in the shape of a circle in p5.js

Ahoy! I am new to programming and working in p5.js. My conundrum is this: I'd like to create a digital clock, and output the numbers on the clock by using some for loops and an array for the clock values (text 1-12). I've figured out how to make a ticking image of a clock...but can't figure the rest out. When I run the below code, it doesn't throw any errors but the text/numbers on the clock aren't executing. I've tried putting the first for loop below within the setup function, and nothing changes. What am I doing wrong? I feel like I'm confused around the second for loop and how to actually print the numbers to the screen, like regarding: (text([i])). Please let me know if I need to clarify more - any help is appreciated! Trying to learn as much as I can.
//Simple second clock.
// An exercise in translating from polar to cartesian coordinates
var radius = 120.0;
var angle = 0.0;
var x=0, y=0;
var digits = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
function setup() {
createCanvas(windowWidth,windowHeight);
}
function draw() {
for (var i = 0; i < 12; i++) { //loop for digits. Populate array.
digits[i] = text("[i]", 10, -radius+10);
for (var i = 0; i < digits.length; i++) {
fill(255,0,255)
text([i]);
}
}
background(255);
translate(width/2, height/2);
stroke(205,205,55);
fill(255,0,255);
ellipse(0,0,10,10);
noFill();
ellipse(0,0,250,250);
stroke(25);
fill(205,205,55);
//text("12", 0, -radius+PI+10); //if I were to manually do each number
// text("1", 30, -radius+PI+20);
// text("2", 60, -radius+PI+30);
// text("3", 90, -radius+PI+40);
angle = (second() / 59.0) * TWO_PI;
// memorize this formula, it's helpful
x = cos(angle)* radius;
y = sin(angle)* radius;
stroke(255,0,255);
//draw a line from the center of our screen and as long as our radius
line(0,0,x,y);
ellipse(x,y,10,10);
}
This is really a question about polar coordinates. Your x and y coordinates in the commented section are off. This is the idea:
var angleOffset = -1*PI/2;
for (var i=1; i<=12; i++) {
angle = 2*PI*i/12 + angleOffset;
text(i, radius*cos(angle), radius*sin(angle));
}
Edit: Full working code below
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.23/p5.min.js"></script>
<script>
var radius = 120.0;
var angle = 0.0;
var x=0, y=0;
var digits = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
function setup() {
createCanvas(windowWidth,windowHeight);
}
function draw() {
for (var i = 0; i < 12; i++) { //loop for digits. Populate array.
digits[i] = text("[i]", 10, -radius+10);
for (var i = 0; i < digits.length; i++) {
fill(255,0,255)
text([i]);
}
}
background(255);
translate(width/2, height/2);
stroke(205,205,55);
fill(255,0,255);
ellipse(0,0,10,10);
noFill();
ellipse(0,0,250,250);
stroke(25);
fill(205,205,55);
var angleOffset = -1*PI/2;
for (var i=1; i<=12; i++) {
angle = 2*PI*i/12 + angleOffset;
text(i, radius*cos(angle), radius*sin(angle));
}
angle = (second() / 59.0) * TWO_PI;
// memorize this formula, it's helpful
x = cos(angle)* radius;
y = sin(angle)* radius;
stroke(255,0,255);
//draw a line from the center of our screen and as long as our radius
line(0,0,x,y);
ellipse(x,y,10,10);
}
setup();
draw();
</script>
// ABC CLOCK
var radius = 120.0;
var angle = 0.0;
var x = 0,
y = 0;
var digits = [];
var se = 0;
var nloops=0
var sentence="12 1 2 3 4 5 6 7 8 9 10 11"
//var sentence="A B C D E F G"
var nl = 0;
var letter1=''
var letter2=''
function setup() {
createCanvas(windowWidth, windowHeight);
digits = sentence.split(" ");
letter1=digits[0]
letter2=digits[0]
nl = digits.length; //numberOfLetters
textAlign(CENTER, CENTER);
frameRate(1);
}
function draw() {
background(9);
textAlign(LEFT, CENTER);
fill(255)
text(letter1+' '+letter2, 40,40)
//text(nloops+' '+se,40,60)
translate(width / 2, height / 2);
textAlign(CENTER, CENTER);
cont = 0;
mod = (2 * PI) / nl;
ia = -HALF_PI; //init angle
pr1= 0.9; //proportion radius letters
pr2= 0.5; //proportion radius letters
rl = radius * pr1; //radius letter
for (var i = 0; i < nl; i++) {
noFill();
stroke(120);
text(digits[i], rl * cos(cont + ia), rl * sin(cont + ia));
cont += mod;
}
angle = (TWO_PI / nl) * se;
angle2 = (TWO_PI / nl) * nloops;
x = rl * cos(angle + ia);
y = rl * sin(angle + ia);
x1 = rl * cos(angle2 + ia);
y1 = rl * sin(angle2 + ia);
stroke(55);
line(0, 0, x * pr1, y * pr1);
stroke(255);
line(0, 0, x1 * pr2, y1 * pr2);
stroke(55);
fill(0);
ellipse(0, 0, 10, 10);
noFill();
ellipse(0, 0, 250, 250);
se += 1;
if(se%nl==0){
nloops+=1
if (nloops%nl==0){
nloops=0
}
se=0
}
letter1=digits[nloops]
letter2=digits[se]
}
A little more developed

JS: How do I create a 10x10 grid of filled rectangles?

I'm trying to create 100 filled rectangles in a 10x10 grid. Each of these rectangles is 20px*20px big, and 20px apart from each other. I completely understand the logic behind it, and roughly how to put it into code, but there is one part I can't seem to get my head around; how I make the rectangles appear on the next line after the first 10 have been drawn.
I've got a fiddle here with my current progress: http://jsfiddle.net/z3wsxa8j/
As you can see, they go diagonally. I understand why, because X and Y keep getting +40px added to their coordinates. If I remove the yvalue += 40; part, they all go on the same row, obviously. I don't know how I can elegantly make them go on another row after reaching 10 rectangles. I tried using if/else statements, so when there's 11 rectangles, make it my_context.fillRect(xvalue,40,20,20); ...
if it's 21 rectangles
my_context.fillRect(xvalue,80,20,20); and so on.
But that would A) result in a lot of if statements and B) It didn't even work (they printed on the same line, still).
Any hints are appreciated, thanks!
Every 10th square, you'll need to do 2 things:
Increase the "y" value to move down to the next line, and
Set the "x" value back to 0
Also, you need to make sure you only do 100 boxes and not 101:
for (var x = 0; x < 100; x++) {
my_context.fillRect(xvalue, yvalue, 20, 20);
xvalue += 40;
if ((x+1) % 10 === 0) {
yvalue += 40;
xvalue = 0;
}
}
The value of (x+1) % 10 will be 0 when "x" is 9, 19, 29, etc.
Basically start drawing with one axis 10 rects using an inner loop, and repeating that with 40px shiftign for the other axis, repeating it 10 times JS Fiddle
NOTE: that in your code you have (var x = 0; x <= 10; x++) this will draw 11 rectangles not 10, because you started from 0 and ended at 10, so it should be (var x = 0; x < 10; x++) instead of <=
var canvas = document.getElementById("canvas");
var my_context = canvas.getContext('2d');
my_context.strokeStyle = "white"; // Draws the canvas border
my_context.rect(0, 0, 1000, 1000);
my_context.stroke();
my_context.fillStyle = "white";
var xvalue = 0;
var yvalue = 0;
for (var y = 0; y < 10; y++) {
for (var x = 0; x < 10; x++) {
my_context.fillRect(xvalue, yvalue, 20, 20);
xvalue += 40;
}
xvalue = 0;
yvalue += 40;
}
body {
background-color: gray;
margin: 0px;
overflow: hidden;
}
<body>
<canvas id="canvas" width="1000" height="1000"></canvas>
</body>
Just use an x and a y loop instead of one big loop:
for (var x = 0; x <= 10; x++) {
for (var y = 0; y <= 10; y++) {
my_context.fillRect(x*40, y*40, 20, 20);
}
}
Try using nested for loops:
var canvas = document.getElementById("canvas");
var my_context = canvas.getContext('2d');
my_context.strokeStyle = "white"; // Draws the canvas border
my_context.rect(0, 0, 1000, 1000);
my_context.stroke();
my_context.fillStyle = "white";
var step = 40;
for (var x = 0; x <= 10; x++) {
for(var y = 0; y <= 10; y++) {
my_context.fillRect(x*step, y*step, 20, 20);
}
}
This code draws the rectangles column by column. Here's a fiddle.
You can accomplish this using single if statement and a variable to keep track of number of boxes drawn in a row. When 10 boxes are drawn reset the count and increment the y value.
Updated Fiddle: Demo
var canvas = document.getElementById("canvas");
var my_context = canvas.getContext('2d');
my_context.strokeStyle = "white"; // Draws the canvas border
my_context.rect(0, 0, 1000, 1000);
my_context.stroke();
my_context.fillStyle = "white";
var xvalue = 0;
var yvalue = 0;
var boxes = 1;
for (var x = 0; x <= 100; x++) {
if(boxes>10){
boxes = 1;
xvalue = 0;
yvalue += 40;
}
boxes++;
my_context.fillRect(xvalue, yvalue, 20, 20);
xvalue += 40;
}
As others have stated you can have a for loop within a for loop, such that you increment each row first, then increment each column.
http://jsfiddle.net/z3wsxa8j/10/
var canvasSize = 1000;
var blockSize = 20;
var numBlocks = canvasSize/blockSize;
// Outer loop for each columns
for (var i = 0; i < numBlocks; i++) {
xvalue = 0;
yvalue = blockSize*i;
// Inner loop for the rows
for (var j = 0; j < numBlocks; j++) {
my_context.fillRect(xvalue, yvalue, blockSize, blockSize);
xvalue += blockSize;
}
}

Javascript error while dropping balls

I wrote a javascript code to drop in ball multiple times when clicked on canvas. It is an experiment.
Here is the code:
HTML
<br style="clear: both" />
<canvas id="myCanvas1" width="134px" height="331px" onclick="draw(0)"></canvas>
<canvas id="myCanvas2" width="134px" height="331px" onclick="draw(1)"></canvas>
<canvas id="myCanvas3" width="134px" height="331px" onclick="draw(2)"></canvas>
JAVASCRIPT
var balls = [[], [], []],
canvases = document.getElementsByTagName('canvas'),
context = [],
interval,
boxWidth = 150,
ballRadius = 10,
canvasHeight = 235;
for (var i = 0; i < canvases.length; i++) {
context.push(canvases[i].getContext('2d'));
}
function draw() {
var movement = false;
for (var i = 0; i < 3; i++) {
context[i].clearRect(0, 0, boxWidth, canvasHeight);
for (var j = 0; j < balls[i].length; j++) {
if (balls[i][j].y < balls[i][j].yStop) {
balls[i][j].y += 4;
movement = true;
}
context[i].beginPath();
context[i].fillStyle = "red";
context[i].arc(balls[i][j].x, balls[i][j].y, ballRadius, 0, Math.PI * 2, true);
context[i].closePath();
context[i].fill();
}
}
if (!movement) {
clearInterval(interval);
interval = null;
}
}
function newBall(n) {
console.log('new ball', n);
var last = balls[n][balls[n].length - 1],
ball = {x: ballRadius, y: ballRadius, yStop: canvasHeight - ballRadius};
if (last) {
if (last.x < boxWidth - ballRadius * 3) {
ball.x = last.x + ballRadius * 2;
ball.yStop = last.yStop;
} else {
ball.yStop = last.yStop - ballRadius * 2;
}
}
balls[n].push(ball);
if (!interval) {
interval = setInterval(draw, 10);
}
}
But balls aren't dropping in. Please tell me that where am I wrong so that I can fix it...
balls is [] when the loop starts. So balls[0] is undefined, and thus has no property length.
Your code is always looping from 0 to 3. However, at first, there is no ball around. When you try to reach balls[0], balls[1] and balls[2], you get undefined error.
What you have to do is to change the loop to:
for (var i = 0; i < balls.length; i++)
or if you do not want to change the loop, you can initialize 3 balls at the start:
balls = [ball1, ball2, ball3];
where ball1, ball2 and ball3 are defined as how your ball data type is.
EDIT:
As I understand, you have some number of contexts, and for each context, you want to have a list of balls so that you can draw them.
Then:
balls = []
for (var i = 0; i < canvases.length; i++) {
context.push(canvases[i].getContext('2d'));
balls.push([]);
}
and use the remaining code same.

Categories