如何用选定的颜色填充网格上的选定单元格?
How to fill selected cells on a grid with a selected color?
我正在创建一个游戏,在该游戏中,用户必须匹配由正方形网格组成的随机生成的目标图像。用户可以 select 一整行(在左侧圈出 select 或一整列(在顶部圈出 select 圈)和一个单独的单元格,这算作一次移动。目前,我的程序允许我 select 行、列和单元格(并对它们进行 deselected),但我还没有找到填充 selected 单元格的方法从我的颜色 select 或 canvas 的顶部。我想知道是否有人可以给我任何有关如何实现此目标的提示?
final color RED = #D12020;
final color BLUE = #515DD8;
final color GREEN = #21AF20;
final color YELLOW = #F5EF74;
final color ORANGE = #F59219;
final color PURPLE = #B219F5;
final color WHITE = #FFFFFF;
final int ROWS = 12;
final int COLUMNS = 8;
final int BLOCK_SIZE = 40;
int blockSize;
int spacing;
int cornerX;
int cornerY;
int size;
int space;
int cell = -1;
int col = -1;
int row = -1;
color[] colour = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, WHITE};
void setup() {
size(1000, 1000);
background(0);
cornerX = width/8;
cornerY = height/8;
size = height/33;
space = width/100;
targetImage();
}
void draw() {
//background(0);
colourCells();
grid();
selectCell();
columnSelectors();
rowSelectors();
counter();
}
//draws the colour selectors
void colourCells() {
int blockSize = width/20;
int spacing = width/200;
int colourBlocks = 7;
int squareX = blockSize;
for (int i=0; i < colourBlocks; i++) {
stroke(167);
fill(colour[i]);
rect(squareX, 0, blockSize, blockSize);
squareX += spacing+blockSize;
}
}
//draws the grid
void grid() {
cornerX = width/8;
cornerY = height/5;
noFill();
stroke(167);
strokeWeight(1);
for (int i = 0; i<ROWS; i++) {
cornerX = width/8;
for (int j = 0; j<COLUMNS; j++) {
rect(cornerX, cornerY, BLOCK_SIZE, BLOCK_SIZE);
cornerX += BLOCK_SIZE;
}
cornerY += BLOCK_SIZE;
}
}
//changes the selected cell stroke to red (or deselected cell outline back to grey)
void selectCell() {
cornerX = width/8;
cornerY = height/5;
if (cell != -1) {
stroke(RED);
rect(cornerX + (cell % COLUMNS) * BLOCK_SIZE, cornerY + (cell / COLUMNS) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
stroke(167);
}
}
//creates the circular column selectors
void columnSelectors() {
int columnX = (cornerX) + (size/2) + (space/2);
int columnY = (cornerY) - (size/2) - space;
noFill();
for ( int i = 0; i<COLUMNS; i++) {
if (col != -1 && col == i)
stroke(RED);
else
stroke(167);
ellipse(columnX, columnY, size, size);
columnX += size + space;
}
}
//creates the circular row selectors
void rowSelectors() {
int rowX = (cornerX) - (size/2) - space;
int rowY = (cornerY) + (size/2) + (space/2);
noFill();
for ( int j = 0; j<ROWS; j ++) {
if (row != -1 && row == j)
stroke(RED);
else
stroke(167);
ellipse(rowX, rowY, size, size);
rowY += size + space;
}
}
//creates the score counter at the bottom of canvas
void counter() {
float x = width/3;
float y = 4*height/5;
float boxLength = width/3;
float boxHeight = height/20;
int counter = 0;
fill(255);
rect(x, y, boxLength, boxHeight);
String counterText = "Num Moves: " + counter;
fill(0);
textSize(40);
text(counterText, x + (boxLength*1/14.0), y + (boxHeight*3/4.0));
}
//loads in a random target image
void targetImage() {
float y = height/5;
float x = width/2;
String [] file = {"target0.png", "target1.png", "target2.png", "target3.png", "target4.png"};
PImage target;// create a variable that can point to an off-screen buffer
String filename = file[int(random(0, 4))]; //"target" + int(random(0,4)) + ".png";// create filename
target = loadImage(filename);// load image file into off-screen buffer
image(target, x, y, width/3.125, height/2.08);// display the buffer on canvas at location x, y
}
//allows the user to select/deselect individual cells
int cellSelected() {
int x;
int y;
int xPos= mouseX - cornerX;
int yPos= mouseY - cornerY;
x = xPos/BLOCK_SIZE;
y = yPos/BLOCK_SIZE;
int num = x + (y*COLUMNS);
if (num == cell)
return -1;
else
return num;
}
//allows the user to select/deselect a column
int selectColumn() {
int x;
int xPos= mouseX - cornerX;
x = xPos/(size+space);
if (x == col)
return -1;
else
return x;
}
//allows the user to select/deselect a row
int selectRow() {
int y;
int yPos= mouseY - cornerY;
y = yPos/(size+space);
if (y == row)
return -1;
else
return y;
}
//mouse click functions for selecting cells/rows/columns/colour
void mouseClicked() {
spacing = width/200;
blockSize = width/20;
if (mouseX > cornerX && mouseY > cornerY && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
cell = cellSelected();
}
if (mouseX > cornerX && mouseY > (cornerY - (space + size)) && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY) {
col = selectColumn();
}
if (mouseX > (cornerX - (space + size)) && mouseY > cornerY && mouseX < cornerX
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
row = selectRow();
}
if (mouseX < blockSize && mouseX > ((blockSize*colour.length) + (spacing*(colour.length - 1)))) {
for (int c = 0; c < colour.length; c++) {
if (get(mouseX, mouseY) == colour[c]) {
fill(colour[c]);
break;
}
}
}
}
/*
to do
fill colour
increse score counter
*/```
[1]: https://i.stack.imgur.com/eyX4g.png
我喜欢你的项目。我特别喜欢你评论它。到目前为止做得很好。我应该睡觉,但我会帮你的。而且,让我们面对现实吧,反正我睡不好。
首先,您可以猜到,要为您的解决方案着色,您必须将这些信息储存在某个地方。
然后,要验证玩家是否找到了正确的答案,您必须能够将他的工作与解决方案进行比较。
我看到你用图像来显示目标状态。我建议您改为编写代码,这样您就可以更轻松地进行比较(并且您还可以轻松生成许多不同的 "levels")。
Java是面向对象的。你没有写任何 class,所以我想你还在学习。让我告诉你一些事情:class 很棒。它们是自己的对象,有自己的方法和变量。您可以通过多种方式实例化它们。比方说……您自己的对象数组。一个物体可能是……比方说……一个正方形?彩色方块?
是的。 您可以定义一个 class 让他们自己画。 并记住他们自己的颜色,而不是绘制大约 100 个正方形。并知道它们是否被点击。
而且,基本上,随心所欲。
这是一个正方形示例 class:
class Square{
//modal variables
private float xPos = 0;
private float yPos = 0;
private float myWidth = 0;
private float myHeight = 0;
public color myColor = color(0); //myColor and isSelected are public because I want to access them directly from outside the class
public boolean isSelected = false; //public modal variables are not a popular choice, with good reasons, but for now let's just roll with it
//this is a constructor. Every time you instantiate this class, you must call it's constructor. This one can be overloaded with the square's cordinates and size
public Square(int xx, int yy, float ww, float hh) {
xPos = xx;
yPos = yy;
myWidth = ww;
myHeight = hh;
}
//you can call this method to make the square draw itself
public void Render() {
if (isSelected) {
stroke(RED);
} else {
stroke(167);
}
fill(myColor);
rect(xPos, yPos, myWidth, myHeight);
}
//give coordinates to this function to know if this squared has been clicked on
public boolean ClickedOn(float xx, float yy) {
return ((xx > xPos && xx < xPos + myWidth) && (yy > yPos && yy < yPos + myHeight));
}
}
现在,我不打算重写整个内容,但这里有一个最小的、可重现的例子来说明这个 class 的功能(您可以将以下代码复制并粘贴到 Processing 中并学习来自它):
final color RED = #D12020;
final color BLUE = #515DD8;
final color GREEN = #21AF20;
final color YELLOW = #F5EF74;
final color ORANGE = #F59219;
final color PURPLE = #B219F5;
final color WHITE = #FFFFFF;
final int ROWS = 12;
final int COLUMNS = 8;
final color[] colour = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, WHITE};
ArrayList <Square> picker, grid, answer; //there are 3 groups of squared to manage
class Square{
//modal variables
private float xPos = 0;
private float yPos = 0;
private float myWidth = 0;
private float myHeight = 0;
public color myColor = color(0); //myColor and isSelected are public because I want to access them directly from outside the class
public boolean isSelected = false; //public modal variables are not a popular choice, with good reasons, but for now let's just roll with it
//this is a constructor. Every time you instantiate this class, you must call it's constructor. This one can be overloaded with the square's cordinates and size
public Square(float xx, float yy, float ww, float hh) {
xPos = xx;
yPos = yy;
myWidth = ww;
myHeight = hh;
}
//you can call this method to make the square draw itself
public void Render() {
if (isSelected) {
stroke(RED);
} else {
stroke(167);
}
fill(myColor);
rect(xPos, yPos, myWidth, myHeight);
}
//give coordinates to this function to know if this squared has been clicked on
public boolean ClickedOn(float xx, float yy) {
return ((xx > xPos && xx < xPos + myWidth) && (yy > yPos && yy < yPos + myHeight));
}
}
//setup() is meant for you to initialize stuff before the main loop, which is draw()
void setup() {
size(1000, 1000);
InitializeSquares();
}
//let's initialize EVERYTHING SQUARE-SHAPED!
public void InitializeSquares(){
float blockSize = width/20;
float cornerX = width/12;
float cornerY = height/8;
float answerCornerX = cornerX * 6.5;
float answerCornerY = cornerY;
float pickerSize = blockSize * 1.5;
float pickerCornerX = cornerX/2;
float pickerCornerY = cornerY - (pickerSize * 1.5);
//the grid:
grid = new ArrayList <Square>();
for (int i = 0; i<ROWS; i++) {
for (int j = 0; j<COLUMNS; j++) {
grid.add(new Square(cornerX + (j*blockSize), cornerY + (i*blockSize), blockSize, blockSize));
}
}
//the target answer:
answer = new ArrayList <Square>();
for (int i = 0; i<ROWS; i++) {
for (int j = 0; j<COLUMNS; j++) {
answer.add(new Square(answerCornerX + (j*blockSize), answerCornerY + (i*blockSize), blockSize, blockSize));
answer.get(answer.size()-1).myColor = colour[floor(random(colour.length))];
}
}
//the color pickers
picker = new ArrayList <Square>();
for (int i = 0; i < colour.length; i++) {
picker.add(new Square(pickerCornerX + (i*pickerSize), pickerCornerY, pickerSize, pickerSize));
picker.get(picker.size()-1).myColor = colour[picker.size()-1];
}
}
void draw() {
background(0); //it's ok, the squares will draw themselves
//let's draw the player's squares
for (Square s : grid) {
s.Render();
}
for (Square s : grid) {
//I'm drawing the selected squared over the unselected ones so we see them better
if (s.isSelected) {s.Render();}
}
//drawing the answer grid
for (Square s : answer) {
s.Render();
}
//drawing the color pickers
for (Square s : picker) {
s.Render();
}
}
void mouseClicked() {
//checking if is the player selecting squares
for (Square s : grid) {
if (s.ClickedOn(mouseX, mouseY)) {
s.isSelected = !s.isSelected;
}
}
//checking if the player is coloring squares. If so, coloring the squared and unselecting them
for (Square p : picker) {
if (p.ClickedOn(mouseX, mouseY)) {
for (Square s : grid) {
if (s.isSelected) {
s.isSelected = false;
s.myColor = p.myColor;
}
}
}
}
}
根据我从您的代码中读到的内容,我相信您将能够使用这些行来实现您的目标。你的代码表明你还有很多东西要学,但它仍然显示出很多承诺。如果你自己完成所有这些,那么我也相信你会非常擅长,而且很快。所以我不会列出你所做的每件小事,无论是错误的还是其他什么。你会在适当的时候学习。
不要忘记在学习的同时享受乐趣。这已经完成了一半以上!如果你有问题,我会在附近闲逛。
-------------------------------------------- ------
这是一些基于您的原始代码的代码 post。它是 "being able to select one column and one row and one cell" 的实现,并在其中添加了一些颜色,但没有任何 class.
老实说,这比我昨天做的难多了。
final color RED = #D12020;
final color BLUE = #515DD8;
final color GREEN = #21AF20;
final color YELLOW = #F5EF74;
final color ORANGE = #F59219;
final color PURPLE = #B219F5;
final color WHITE = #FFFFFF;
final int ROWS = 12;
final int COLUMNS = 8;
final int BLOCK_SIZE = 40;
int blockSize;
int spacing;
int cornerX;
int cornerY;
int size;
int space;
int cell = -1;
int col = -1;
int row = -1;
color[] colour = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, WHITE};
//I added these variables. The color array is 2 dimentional, so you can use it like if it had grid coordinates (square [0][2] is third on the first line)
PVector square_selected; //this will hold the grid coordinates of the currently selected square, or -1 for "nothing"
color[][] square_color;
int columnSelected = -1;
int rowSelected = -1;
void setup() {
size(1000, 1000);
background(0);
cornerX = width/8;
cornerY = height/8;
size = height/33;
space = width/100;
targetImage();
//initializing the new array
square_color = new color[COLUMNS][ROWS];
for (int i=0; i<COLUMNS; i++) {
for (int j=0; j<ROWS; j++) {
square_color[i][j] = color(0);
}
}
square_selected = new PVector(-1, -1);
//You might have heard about this or not, but as a general rule global variables are shunned upon. That's because when the program becomes more complex, they become exponentially harder to control,
//and can cause unexpected behavior. No joke, Toyota programmers actually caused death because of these (search for "Toyota spaghetti code" if you're curious)
//So I'm initializing these here and removing the places where the code would change them unexpectedly.
//You may have had a better idea of what you're doing that I do, though, so you can chalk up this decision to my coding preferences.
blockSize = width/20;
spacing = width/200;
}
void draw() {
background(0);
grid();
colourCells();
//selectCell();
columnSelectors();
rowSelectors();
counter();
}
//draws the colour selectors
void colourCells() {
int colourBlocks = 7;
int squareX = blockSize;
for (int i=0; i < colourBlocks; i++) {
stroke(167);
fill(colour[i]);
rect(squareX, 0, blockSize, blockSize);
squareX += spacing+blockSize;
}
}
//draws the grid
void grid() {
for (int i=0; i<ROWS; i++) {
for (int j=0; j<COLUMNS; j++) {
stroke(167);
fill(square_color[j][i]);
rect(cornerX + (BLOCK_SIZE * j), cornerY + (BLOCK_SIZE * i), BLOCK_SIZE, BLOCK_SIZE);
}
}
//drawing the selected square over the others
if (square_selected.x > -1) {
stroke(RED);
fill(square_color[(int)square_selected.x][(int)square_selected.y]);
rect(cornerX + (BLOCK_SIZE * (int)square_selected.x), cornerY + (BLOCK_SIZE * (int)square_selected.y), BLOCK_SIZE, BLOCK_SIZE);
}
}
//creates the circular column selectors
void columnSelectors() {
int columnX = (cornerX) + (size/2) + (space/2);
int columnY = (cornerY) - (size/2) - space;
noFill();
for ( int i = 0; i<COLUMNS; i++) {
if (i == columnSelected) {
stroke(RED);
} else {
stroke(167);
}
ellipse(columnX, columnY, size, size);
columnX += size + space;
}
}
//creates the circular row selectors
void rowSelectors() {
int rowX = (cornerX) - (size/2) - space;
int rowY = (cornerY) + (size/2) + (space/2);
noFill();
for ( int j = 0; j<ROWS; j ++) {
if (j == rowSelected) {
stroke(RED);
} else {
stroke(167);
}
ellipse(rowX, rowY, size, size);
rowY += size + space;
}
}
//creates the score counter at the bottom of canvas
void counter() {
float x = width/3;
float y = 4*height/5;
float boxLength = width/3;
float boxHeight = height/20;
int counter = 0;
fill(255);
rect(x, y, boxLength, boxHeight);
String counterText = "Num Moves: " + counter;
fill(0);
textSize(40);
text(counterText, x + (boxLength*1/14.0), y + (boxHeight*3/4.0));
}
//loads in a random target image
void targetImage() {
float y = height/5;
float x = width/2;
String [] file = {"target0.png", "target1.png", "target2.png", "target3.png", "target4.png"};
PImage target;// create a variable that can point to an off-screen buffer
String filename = file[int(random(0, 4))]; //"target" + int(random(0,4)) + ".png";// create filename
target = loadImage(filename);// load image file into off-screen buffer
//image(target, x, y, width/3.125, height/2.08);// display the buffer on canvas at location x, y
}
//allows the user to select/deselect a column
int selectColumn() {
int x;
int xPos= mouseX - cornerX;
x = xPos/(size+space);
if (x == col)
return -1;
else
return x;
}
//allows the user to select/deselect a row
int selectRow() {
int y;
int yPos= mouseY - cornerY;
y = yPos/(size+space);
if (y == row)
return -1;
else
return y;
}
//mouse click functions for selecting cells/rows/columns/colour
void mouseClicked() {
//user is clicking inside the grid
if (mouseX > cornerX && mouseY > cornerY && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
//cell = cellSelected();
square_selected.x = floor((mouseX - cornerX)/BLOCK_SIZE);
square_selected.y = floor((mouseY - cornerY)/BLOCK_SIZE);
}
//user is selectong a column
if (mouseX > cornerX && mouseY > (cornerY - (space + size)) && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY) {
if (columnSelected == selectColumn()) {
columnSelected = -1;
} else {
columnSelected = selectColumn();
}
}
//user is selecting a row
if (mouseX > (cornerX - (space + size)) && mouseY > cornerY && mouseX < cornerX
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
if (rowSelected == selectRow()) {
rowSelected = -1;
} else {
rowSelected = selectRow();
}
}
//user is picking a color
if (mouseY < blockSize) {
//validating the color
for (int c = 0; c < colour.length; c++) {
if (get(mouseX, mouseY) == colour[c]) {
//if a square has been selected
if (square_selected.x > -1) {
square_color[(int)square_selected.x][(int)square_selected.y] = colour[c];
square_selected = new PVector(-1,-1);
}
//if a row has been selected
if (rowSelected > -1) {
for (int i = 0; i < COLUMNS; i++) {
square_color[i][rowSelected] = colour[c];
}
rowSelected = -1;
}
//if a column has been selected
if (columnSelected > -1) {
for (int i = 0; i < ROWS; i++) {
square_color[columnSelected][i] = colour[c];
}
columnSelected = -1;
}
break;
}
}
}
}
诀窍是保持一切整洁并避免意外更改。要认识到这一点,一些良好的工作习惯会大有帮助。习惯如:
- 评论代码
- 将任务拆分为命名良好的函数(请记住,较小的函数更好,因为它们更人性化!)
- 保持变量整洁
- 良好的代码格式
所以,您会在代码中看到它,但基本上我只是添加了几个变量来跟踪方块的颜色,以及当前选择的是哪个单元格或 row/column。我还调整了绘制对象的函数,因此颜色取决于属性(在我刚才提到的变量中),而不仅仅是程序在它发生时绘制一次的东西——所以循环的新迭代不会擦除它们.哦,由于这些更改,我删除了不再需要的功能。
和上次一样,我会留下来,所以不要犹豫,问任何不坚持或你没有得到的问题。玩得开心!
我正在创建一个游戏,在该游戏中,用户必须匹配由正方形网格组成的随机生成的目标图像。用户可以 select 一整行(在左侧圈出 select 或一整列(在顶部圈出 select 圈)和一个单独的单元格,这算作一次移动。目前,我的程序允许我 select 行、列和单元格(并对它们进行 deselected),但我还没有找到填充 selected 单元格的方法从我的颜色 select 或 canvas 的顶部。我想知道是否有人可以给我任何有关如何实现此目标的提示?
final color RED = #D12020;
final color BLUE = #515DD8;
final color GREEN = #21AF20;
final color YELLOW = #F5EF74;
final color ORANGE = #F59219;
final color PURPLE = #B219F5;
final color WHITE = #FFFFFF;
final int ROWS = 12;
final int COLUMNS = 8;
final int BLOCK_SIZE = 40;
int blockSize;
int spacing;
int cornerX;
int cornerY;
int size;
int space;
int cell = -1;
int col = -1;
int row = -1;
color[] colour = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, WHITE};
void setup() {
size(1000, 1000);
background(0);
cornerX = width/8;
cornerY = height/8;
size = height/33;
space = width/100;
targetImage();
}
void draw() {
//background(0);
colourCells();
grid();
selectCell();
columnSelectors();
rowSelectors();
counter();
}
//draws the colour selectors
void colourCells() {
int blockSize = width/20;
int spacing = width/200;
int colourBlocks = 7;
int squareX = blockSize;
for (int i=0; i < colourBlocks; i++) {
stroke(167);
fill(colour[i]);
rect(squareX, 0, blockSize, blockSize);
squareX += spacing+blockSize;
}
}
//draws the grid
void grid() {
cornerX = width/8;
cornerY = height/5;
noFill();
stroke(167);
strokeWeight(1);
for (int i = 0; i<ROWS; i++) {
cornerX = width/8;
for (int j = 0; j<COLUMNS; j++) {
rect(cornerX, cornerY, BLOCK_SIZE, BLOCK_SIZE);
cornerX += BLOCK_SIZE;
}
cornerY += BLOCK_SIZE;
}
}
//changes the selected cell stroke to red (or deselected cell outline back to grey)
void selectCell() {
cornerX = width/8;
cornerY = height/5;
if (cell != -1) {
stroke(RED);
rect(cornerX + (cell % COLUMNS) * BLOCK_SIZE, cornerY + (cell / COLUMNS) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
stroke(167);
}
}
//creates the circular column selectors
void columnSelectors() {
int columnX = (cornerX) + (size/2) + (space/2);
int columnY = (cornerY) - (size/2) - space;
noFill();
for ( int i = 0; i<COLUMNS; i++) {
if (col != -1 && col == i)
stroke(RED);
else
stroke(167);
ellipse(columnX, columnY, size, size);
columnX += size + space;
}
}
//creates the circular row selectors
void rowSelectors() {
int rowX = (cornerX) - (size/2) - space;
int rowY = (cornerY) + (size/2) + (space/2);
noFill();
for ( int j = 0; j<ROWS; j ++) {
if (row != -1 && row == j)
stroke(RED);
else
stroke(167);
ellipse(rowX, rowY, size, size);
rowY += size + space;
}
}
//creates the score counter at the bottom of canvas
void counter() {
float x = width/3;
float y = 4*height/5;
float boxLength = width/3;
float boxHeight = height/20;
int counter = 0;
fill(255);
rect(x, y, boxLength, boxHeight);
String counterText = "Num Moves: " + counter;
fill(0);
textSize(40);
text(counterText, x + (boxLength*1/14.0), y + (boxHeight*3/4.0));
}
//loads in a random target image
void targetImage() {
float y = height/5;
float x = width/2;
String [] file = {"target0.png", "target1.png", "target2.png", "target3.png", "target4.png"};
PImage target;// create a variable that can point to an off-screen buffer
String filename = file[int(random(0, 4))]; //"target" + int(random(0,4)) + ".png";// create filename
target = loadImage(filename);// load image file into off-screen buffer
image(target, x, y, width/3.125, height/2.08);// display the buffer on canvas at location x, y
}
//allows the user to select/deselect individual cells
int cellSelected() {
int x;
int y;
int xPos= mouseX - cornerX;
int yPos= mouseY - cornerY;
x = xPos/BLOCK_SIZE;
y = yPos/BLOCK_SIZE;
int num = x + (y*COLUMNS);
if (num == cell)
return -1;
else
return num;
}
//allows the user to select/deselect a column
int selectColumn() {
int x;
int xPos= mouseX - cornerX;
x = xPos/(size+space);
if (x == col)
return -1;
else
return x;
}
//allows the user to select/deselect a row
int selectRow() {
int y;
int yPos= mouseY - cornerY;
y = yPos/(size+space);
if (y == row)
return -1;
else
return y;
}
//mouse click functions for selecting cells/rows/columns/colour
void mouseClicked() {
spacing = width/200;
blockSize = width/20;
if (mouseX > cornerX && mouseY > cornerY && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
cell = cellSelected();
}
if (mouseX > cornerX && mouseY > (cornerY - (space + size)) && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY) {
col = selectColumn();
}
if (mouseX > (cornerX - (space + size)) && mouseY > cornerY && mouseX < cornerX
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
row = selectRow();
}
if (mouseX < blockSize && mouseX > ((blockSize*colour.length) + (spacing*(colour.length - 1)))) {
for (int c = 0; c < colour.length; c++) {
if (get(mouseX, mouseY) == colour[c]) {
fill(colour[c]);
break;
}
}
}
}
/*
to do
fill colour
increse score counter
*/```
[1]: https://i.stack.imgur.com/eyX4g.png
我喜欢你的项目。我特别喜欢你评论它。到目前为止做得很好。我应该睡觉,但我会帮你的。而且,让我们面对现实吧,反正我睡不好。
首先,您可以猜到,要为您的解决方案着色,您必须将这些信息储存在某个地方。
然后,要验证玩家是否找到了正确的答案,您必须能够将他的工作与解决方案进行比较。
我看到你用图像来显示目标状态。我建议您改为编写代码,这样您就可以更轻松地进行比较(并且您还可以轻松生成许多不同的 "levels")。
Java是面向对象的。你没有写任何 class,所以我想你还在学习。让我告诉你一些事情:class 很棒。它们是自己的对象,有自己的方法和变量。您可以通过多种方式实例化它们。比方说……您自己的对象数组。一个物体可能是……比方说……一个正方形?彩色方块?
是的。 您可以定义一个 class 让他们自己画。 并记住他们自己的颜色,而不是绘制大约 100 个正方形。并知道它们是否被点击。
而且,基本上,随心所欲。
这是一个正方形示例 class:
class Square{
//modal variables
private float xPos = 0;
private float yPos = 0;
private float myWidth = 0;
private float myHeight = 0;
public color myColor = color(0); //myColor and isSelected are public because I want to access them directly from outside the class
public boolean isSelected = false; //public modal variables are not a popular choice, with good reasons, but for now let's just roll with it
//this is a constructor. Every time you instantiate this class, you must call it's constructor. This one can be overloaded with the square's cordinates and size
public Square(int xx, int yy, float ww, float hh) {
xPos = xx;
yPos = yy;
myWidth = ww;
myHeight = hh;
}
//you can call this method to make the square draw itself
public void Render() {
if (isSelected) {
stroke(RED);
} else {
stroke(167);
}
fill(myColor);
rect(xPos, yPos, myWidth, myHeight);
}
//give coordinates to this function to know if this squared has been clicked on
public boolean ClickedOn(float xx, float yy) {
return ((xx > xPos && xx < xPos + myWidth) && (yy > yPos && yy < yPos + myHeight));
}
}
现在,我不打算重写整个内容,但这里有一个最小的、可重现的例子来说明这个 class 的功能(您可以将以下代码复制并粘贴到 Processing 中并学习来自它):
final color RED = #D12020;
final color BLUE = #515DD8;
final color GREEN = #21AF20;
final color YELLOW = #F5EF74;
final color ORANGE = #F59219;
final color PURPLE = #B219F5;
final color WHITE = #FFFFFF;
final int ROWS = 12;
final int COLUMNS = 8;
final color[] colour = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, WHITE};
ArrayList <Square> picker, grid, answer; //there are 3 groups of squared to manage
class Square{
//modal variables
private float xPos = 0;
private float yPos = 0;
private float myWidth = 0;
private float myHeight = 0;
public color myColor = color(0); //myColor and isSelected are public because I want to access them directly from outside the class
public boolean isSelected = false; //public modal variables are not a popular choice, with good reasons, but for now let's just roll with it
//this is a constructor. Every time you instantiate this class, you must call it's constructor. This one can be overloaded with the square's cordinates and size
public Square(float xx, float yy, float ww, float hh) {
xPos = xx;
yPos = yy;
myWidth = ww;
myHeight = hh;
}
//you can call this method to make the square draw itself
public void Render() {
if (isSelected) {
stroke(RED);
} else {
stroke(167);
}
fill(myColor);
rect(xPos, yPos, myWidth, myHeight);
}
//give coordinates to this function to know if this squared has been clicked on
public boolean ClickedOn(float xx, float yy) {
return ((xx > xPos && xx < xPos + myWidth) && (yy > yPos && yy < yPos + myHeight));
}
}
//setup() is meant for you to initialize stuff before the main loop, which is draw()
void setup() {
size(1000, 1000);
InitializeSquares();
}
//let's initialize EVERYTHING SQUARE-SHAPED!
public void InitializeSquares(){
float blockSize = width/20;
float cornerX = width/12;
float cornerY = height/8;
float answerCornerX = cornerX * 6.5;
float answerCornerY = cornerY;
float pickerSize = blockSize * 1.5;
float pickerCornerX = cornerX/2;
float pickerCornerY = cornerY - (pickerSize * 1.5);
//the grid:
grid = new ArrayList <Square>();
for (int i = 0; i<ROWS; i++) {
for (int j = 0; j<COLUMNS; j++) {
grid.add(new Square(cornerX + (j*blockSize), cornerY + (i*blockSize), blockSize, blockSize));
}
}
//the target answer:
answer = new ArrayList <Square>();
for (int i = 0; i<ROWS; i++) {
for (int j = 0; j<COLUMNS; j++) {
answer.add(new Square(answerCornerX + (j*blockSize), answerCornerY + (i*blockSize), blockSize, blockSize));
answer.get(answer.size()-1).myColor = colour[floor(random(colour.length))];
}
}
//the color pickers
picker = new ArrayList <Square>();
for (int i = 0; i < colour.length; i++) {
picker.add(new Square(pickerCornerX + (i*pickerSize), pickerCornerY, pickerSize, pickerSize));
picker.get(picker.size()-1).myColor = colour[picker.size()-1];
}
}
void draw() {
background(0); //it's ok, the squares will draw themselves
//let's draw the player's squares
for (Square s : grid) {
s.Render();
}
for (Square s : grid) {
//I'm drawing the selected squared over the unselected ones so we see them better
if (s.isSelected) {s.Render();}
}
//drawing the answer grid
for (Square s : answer) {
s.Render();
}
//drawing the color pickers
for (Square s : picker) {
s.Render();
}
}
void mouseClicked() {
//checking if is the player selecting squares
for (Square s : grid) {
if (s.ClickedOn(mouseX, mouseY)) {
s.isSelected = !s.isSelected;
}
}
//checking if the player is coloring squares. If so, coloring the squared and unselecting them
for (Square p : picker) {
if (p.ClickedOn(mouseX, mouseY)) {
for (Square s : grid) {
if (s.isSelected) {
s.isSelected = false;
s.myColor = p.myColor;
}
}
}
}
}
根据我从您的代码中读到的内容,我相信您将能够使用这些行来实现您的目标。你的代码表明你还有很多东西要学,但它仍然显示出很多承诺。如果你自己完成所有这些,那么我也相信你会非常擅长,而且很快。所以我不会列出你所做的每件小事,无论是错误的还是其他什么。你会在适当的时候学习。
不要忘记在学习的同时享受乐趣。这已经完成了一半以上!如果你有问题,我会在附近闲逛。
-------------------------------------------- ------
这是一些基于您的原始代码的代码 post。它是 "being able to select one column and one row and one cell" 的实现,并在其中添加了一些颜色,但没有任何 class.
老实说,这比我昨天做的难多了。
final color RED = #D12020;
final color BLUE = #515DD8;
final color GREEN = #21AF20;
final color YELLOW = #F5EF74;
final color ORANGE = #F59219;
final color PURPLE = #B219F5;
final color WHITE = #FFFFFF;
final int ROWS = 12;
final int COLUMNS = 8;
final int BLOCK_SIZE = 40;
int blockSize;
int spacing;
int cornerX;
int cornerY;
int size;
int space;
int cell = -1;
int col = -1;
int row = -1;
color[] colour = {RED, BLUE, GREEN, YELLOW, ORANGE, PURPLE, WHITE};
//I added these variables. The color array is 2 dimentional, so you can use it like if it had grid coordinates (square [0][2] is third on the first line)
PVector square_selected; //this will hold the grid coordinates of the currently selected square, or -1 for "nothing"
color[][] square_color;
int columnSelected = -1;
int rowSelected = -1;
void setup() {
size(1000, 1000);
background(0);
cornerX = width/8;
cornerY = height/8;
size = height/33;
space = width/100;
targetImage();
//initializing the new array
square_color = new color[COLUMNS][ROWS];
for (int i=0; i<COLUMNS; i++) {
for (int j=0; j<ROWS; j++) {
square_color[i][j] = color(0);
}
}
square_selected = new PVector(-1, -1);
//You might have heard about this or not, but as a general rule global variables are shunned upon. That's because when the program becomes more complex, they become exponentially harder to control,
//and can cause unexpected behavior. No joke, Toyota programmers actually caused death because of these (search for "Toyota spaghetti code" if you're curious)
//So I'm initializing these here and removing the places where the code would change them unexpectedly.
//You may have had a better idea of what you're doing that I do, though, so you can chalk up this decision to my coding preferences.
blockSize = width/20;
spacing = width/200;
}
void draw() {
background(0);
grid();
colourCells();
//selectCell();
columnSelectors();
rowSelectors();
counter();
}
//draws the colour selectors
void colourCells() {
int colourBlocks = 7;
int squareX = blockSize;
for (int i=0; i < colourBlocks; i++) {
stroke(167);
fill(colour[i]);
rect(squareX, 0, blockSize, blockSize);
squareX += spacing+blockSize;
}
}
//draws the grid
void grid() {
for (int i=0; i<ROWS; i++) {
for (int j=0; j<COLUMNS; j++) {
stroke(167);
fill(square_color[j][i]);
rect(cornerX + (BLOCK_SIZE * j), cornerY + (BLOCK_SIZE * i), BLOCK_SIZE, BLOCK_SIZE);
}
}
//drawing the selected square over the others
if (square_selected.x > -1) {
stroke(RED);
fill(square_color[(int)square_selected.x][(int)square_selected.y]);
rect(cornerX + (BLOCK_SIZE * (int)square_selected.x), cornerY + (BLOCK_SIZE * (int)square_selected.y), BLOCK_SIZE, BLOCK_SIZE);
}
}
//creates the circular column selectors
void columnSelectors() {
int columnX = (cornerX) + (size/2) + (space/2);
int columnY = (cornerY) - (size/2) - space;
noFill();
for ( int i = 0; i<COLUMNS; i++) {
if (i == columnSelected) {
stroke(RED);
} else {
stroke(167);
}
ellipse(columnX, columnY, size, size);
columnX += size + space;
}
}
//creates the circular row selectors
void rowSelectors() {
int rowX = (cornerX) - (size/2) - space;
int rowY = (cornerY) + (size/2) + (space/2);
noFill();
for ( int j = 0; j<ROWS; j ++) {
if (j == rowSelected) {
stroke(RED);
} else {
stroke(167);
}
ellipse(rowX, rowY, size, size);
rowY += size + space;
}
}
//creates the score counter at the bottom of canvas
void counter() {
float x = width/3;
float y = 4*height/5;
float boxLength = width/3;
float boxHeight = height/20;
int counter = 0;
fill(255);
rect(x, y, boxLength, boxHeight);
String counterText = "Num Moves: " + counter;
fill(0);
textSize(40);
text(counterText, x + (boxLength*1/14.0), y + (boxHeight*3/4.0));
}
//loads in a random target image
void targetImage() {
float y = height/5;
float x = width/2;
String [] file = {"target0.png", "target1.png", "target2.png", "target3.png", "target4.png"};
PImage target;// create a variable that can point to an off-screen buffer
String filename = file[int(random(0, 4))]; //"target" + int(random(0,4)) + ".png";// create filename
target = loadImage(filename);// load image file into off-screen buffer
//image(target, x, y, width/3.125, height/2.08);// display the buffer on canvas at location x, y
}
//allows the user to select/deselect a column
int selectColumn() {
int x;
int xPos= mouseX - cornerX;
x = xPos/(size+space);
if (x == col)
return -1;
else
return x;
}
//allows the user to select/deselect a row
int selectRow() {
int y;
int yPos= mouseY - cornerY;
y = yPos/(size+space);
if (y == row)
return -1;
else
return y;
}
//mouse click functions for selecting cells/rows/columns/colour
void mouseClicked() {
//user is clicking inside the grid
if (mouseX > cornerX && mouseY > cornerY && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
//cell = cellSelected();
square_selected.x = floor((mouseX - cornerX)/BLOCK_SIZE);
square_selected.y = floor((mouseY - cornerY)/BLOCK_SIZE);
}
//user is selectong a column
if (mouseX > cornerX && mouseY > (cornerY - (space + size)) && mouseX < cornerX + COLUMNS*BLOCK_SIZE
&& mouseY < cornerY) {
if (columnSelected == selectColumn()) {
columnSelected = -1;
} else {
columnSelected = selectColumn();
}
}
//user is selecting a row
if (mouseX > (cornerX - (space + size)) && mouseY > cornerY && mouseX < cornerX
&& mouseY < cornerY + ROWS*BLOCK_SIZE) {
if (rowSelected == selectRow()) {
rowSelected = -1;
} else {
rowSelected = selectRow();
}
}
//user is picking a color
if (mouseY < blockSize) {
//validating the color
for (int c = 0; c < colour.length; c++) {
if (get(mouseX, mouseY) == colour[c]) {
//if a square has been selected
if (square_selected.x > -1) {
square_color[(int)square_selected.x][(int)square_selected.y] = colour[c];
square_selected = new PVector(-1,-1);
}
//if a row has been selected
if (rowSelected > -1) {
for (int i = 0; i < COLUMNS; i++) {
square_color[i][rowSelected] = colour[c];
}
rowSelected = -1;
}
//if a column has been selected
if (columnSelected > -1) {
for (int i = 0; i < ROWS; i++) {
square_color[columnSelected][i] = colour[c];
}
columnSelected = -1;
}
break;
}
}
}
}
诀窍是保持一切整洁并避免意外更改。要认识到这一点,一些良好的工作习惯会大有帮助。习惯如:
- 评论代码
- 将任务拆分为命名良好的函数(请记住,较小的函数更好,因为它们更人性化!)
- 保持变量整洁
- 良好的代码格式
所以,您会在代码中看到它,但基本上我只是添加了几个变量来跟踪方块的颜色,以及当前选择的是哪个单元格或 row/column。我还调整了绘制对象的函数,因此颜色取决于属性(在我刚才提到的变量中),而不仅仅是程序在它发生时绘制一次的东西——所以循环的新迭代不会擦除它们.哦,由于这些更改,我删除了不再需要的功能。
和上次一样,我会留下来,所以不要犹豫,问任何不坚持或你没有得到的问题。玩得开心!