Reputation: 141
I have been trying to remake connect 4 in p5js as a little learning project but i cant get the winning mechanic where having 4 connected makes you win the game. i am using a method that checks every surrounding position in the grid array and then if that one has the same color as the peice thats checking then it adds 1 in the direction the piece is plus the amount that piee has in that direction.`
function setup() {
createCanvas(350, 300);
setBoard();
}
class Slot {
constructor(x, y, scale, color){
this.x = x;
this.y = y;
this.scale = scale;
this.color = color;
this.connectedBlocksX = 0;
this.connectedBlocksY = 0;
this.connectedBlocksXY = 0;
this.connectedBlocksYX = 0;
this.isFilled = false;
}
checkWin(x, y){
if(grid[y][x].color != "gray"){
if(y != 5 && x != 6 && grid[y+1][x+1].color == grid[y][x].color){
grid[y][x].connectedBlocksXY += 1 + grid[y+1][x+1].connectedBlocksXY;
}
if(y != 0 && x != 6 && grid[y-1][x+1].color == grid[y][x].color){
grid[y][x].connectedBlocksYX += 1 + grid[y-1][x+1].connectedBlocksYX;
}
if(y != 5 && x != 0 && grid[y+1][x-1].color == grid[y][x].color){
grid[y][x].connectedBlocksYX+= 1 + grid[y+1][x-1].connectedBlocksYX;
}
if(y != 0 && x != 0 && grid[y-1][x-1].color == grid[y][x].color){
grid[y][x].connectedBlocksXY += 1 + grid[y-1][x-1].connectedBlocksXY;
}
if(x != 6 && grid[y][x+1].color == grid[y][x].color){
grid[y][x].connectedBlocksX+= 1 + grid[y][x+1].connectedBlocksX;
}
if(x != 0 && grid[y][x-1].color == grid[y][x].color){
grid[y][x].connectedBlocksX+= 1 + grid[y][x-1].connectedBlocksX;
}
if(y != 5 && grid[y+1][x].color == grid[y][x].color){
grid[y][x].connectedBlocksY+= 1 + grid[y+1][x].connectedBlocksY;
}
if(y != 0 && grid[y-1][x].color == grid[y][x].color){
grid[y][x].connectedBlocksY += 1 + grid[y-1][x].connectedBlocksY;
}
if(grid[y][x].connectedBlocksY >= 3|| grid[y][x].connectedBlocksX >= 3 || grid[y][x].connectedBlocksYX >= 3 || grid[y][x].connectedBlocksXY >= 3){
if(grid[y][x].color != "gray"){
winner = grid[y][x].color;
}
}
}
}
draw(){
fill(this.color);
ellipseMode(CORNER);
ellipse(this.x,this.y,this.scale, this.scale);
}
drop(){
if(grid[0][(this.x - 5)/50].isFilled == false){
if((this.y - 5)/50 != 0 && this.isFilled == true && grid[0][(this.x - 5)/50].isFilled == false){
grid[(this.y - 5)/50 - 1][(this.x - 5)/50].drop();
this.checkWin((this.x - 5)/50, (this.y - 5)/50 - 1);
}
else if((this.y - 5)/50 != 5){
if(grid[(this.y - 5)/50 + 1][(this.x - 5)/50].isFilled == true && this.isFilled == false){
if(turn == 0){
turn = 1;
}
else{
turn = 0;
}
this.checkWin((this.x - 5)/50, (this.y - 5)/50);
this.isFilled = true;
if(turn == 0){
this.color = "red"
}
else{
this.color = "yellow";
}
}
else{
grid[(this.y - 5)/50 + 1][(this.x - 5)/50].drop();
this.checkWin((this.x - 5)/50, (this.y - 5)/50 + 1);
}
}
else if(this.isFilled == false){
if(turn == 0){
turn = 1;
}
else{
turn = 0;
}
this.checkWin((this.x - 5)/50, (this.y - 5)/50);
this.isFilled = true;
if(turn == 0){
this.color = "red"
}
else{
this.color = "yellow";
}
}
}
}
}
const offset = 5;
var winner = null;
var turn = 0;
var rows = 6;
var cols = 7;
var grid = [];
grid[0] = [0,0,0,0,0,0,0];
grid[1] = [0,0,0,0,0,0,0];
grid[2] = [0,0,0,0,0,0,0];
grid[3] = [0,0,0,0,0,0,0];
grid[4] = [0,0,0,0,0,0,0];
grid[5] = [0,0,0,0,0,0,0];
function draw() {
background("blue");
for(var y = 0; y < rows; y++){
for(var x = 0; x < cols; x++){
grid[y][x].draw();
}
}
if(winner != null){
fill("black");
textSize(50);
text(winner + " Won!", 0, 290);
}
}
function setBoard(){
for(var y = 0; y < rows; y++){
for(var x = 0; x < cols; x++){
grid[y][x] = new Slot(x * 50 + offset, y * 50 + offset, 40, "gray");
}
}
}
function mousePressed(){
for(var y = 0; y < rows; y++){
for(var x = 0; x < cols; x++){
if(mouseX >= grid[y][x].x && mouseX <= grid[y][x].x + grid[y][x].scale && mouseY >= grid[y][x].y && mouseY <= grid[y][x].y + grid[y][x].scale){
grid[y][x].drop();
}
}
}
}`
Upvotes: 1
Views: 187
Reputation: 372
Is this what you mean, I use this function I found long ago. Just put in the 2d array and the x and y position of the object you are trying to find the neighbors of. It will return the neighbors in a separate array.
function neighbors(arr, m, n) {
let v = [[0, 1],[1, 0],[0, -1],[-1, 0]]
return v.filter(([h, j]) => h + m >= 0 && h + m < arr.length && j + n >= 0 && j + n < arr[0].length)
.map(([h, j]) => arr[h + m][j + n])
}
You can also increase the range if you'd like, this can be done in the v array using this:
function neighbors(arr, m, n, radius) {
let v = [];
for(x = -radius; x <= radius; x ++){
for(y = -radius; y <= radius; y ++){
if(x == 0 && y == 0){}else{
v.push([x,y])
}
}
}
return v.filter(([h, j]) => h + m >= 0 && h + m < arr.length && j + n >= 0 && j + n < arr[0].length)
.map(([h, j]) => arr[h + m][j + n])
}
Edit: I hope this explains:
let scale = 100;
let array2d = [];
function setup() {
createCanvas(500, 500);
background(0);
for(x = 0; x < width / scale; x ++){
array2d[x]= [];
for(y = 0; y < height / scale; y ++){
array2d[x][y] = new Point(x,y,0);
}
}
print(array2d)
}
function draw() {
background(0);
for(x = 0; x < array2d.length; x ++){
for(y = 0; y < array2d[x].length; y ++){
array2d[x][y].display();
}
}
}
class Point{
constructor(x,y,color){
this.x = x;
this.y = y;
this.color = color;
}
display(){
fill(this.color);
stroke(100);
rect(x * scale,y * scale,scale)
}
}
function neighbors(arr, m, n, radius) {
let v = [];
for(x = -radius; x <= radius; x ++){
for(y = -radius; y <= radius; y ++){
if(x == 0 && y == 0){}else{
v.push([x,y])
}
}
}
return v.filter(([h, j]) => h + m >= 0 && h + m < arr.length && j + n >= 0 && j + n < arr[0].length)
.map(([h, j]) => arr[h + m][j + n])
}
function mousePressed(){
let nei = neighbors(array2d,round(mouseX / scale - 0.5),round(mouseY / scale - 0.5),1);
print(nei)
for(i = 0; i < nei.length; i ++){
nei[i].color = 255;
}
}
Upvotes: 1