如何将以像素为单位的鼠标位置转换为网格上的行和列?

How to convert the mouse position in pixels into the row and column on the grid?

我基本上是在制作一款战舰猜谜游戏,您必须通过单击鼠标来确定战舰的位置。当船的位置被猜对时,它会从数组中删除该船单元,当每个单元都被正确猜到时,游戏就结束了。

我现在正在努力的是

  1. 将飞船单元保持在 canvas
  2. 范围内
  3. 将鼠标位置(以像素为单位)转换为网格上的行和列
  4. 如果猜测正确,则将猜测添加到 hit 数组中,如果未猜中,则将其添加到 miss 数组中。
  5. 做出猜测后,除了给单元格着色之外,打印“Hit!”或“小姐!”在单元格上
  6. 当所有格子都被击中后沉船

在您的代码中,您混合了行和列。 x 坐标从左到右,这是列。 y轴从上到下对应行

不要将 columnrowhitmiss 存储在数组中。但是用二维数组来存储船的位置和鼠标点击的位置:

boolean [][] ship;
boolean [][] click;
  1. keep the ship cells within the canvas

如果方向是水平的,那么船的x起始位置必须小于NUM_COLS - shipLength:

randomX = (int)random(NUM_COLS - shipLength);
randomY = (int)random(NUM_ROWS);

如果方向是水平的,那么船的y起始位置必须小于NUM_ROWS - shipLength:

randomX = (int)random(NUM_COLS);
randomY = (int)random(NUM_ROWS - shipLength);

setup 中调用 randomShip 而不是 draw:

void setup() {
    size(600, 500);
    randomShip();
    println(store);
}

void draw() {
    // randomShip(); <---- delete
    drawCells (row, column, shipLength, (255) );
}

randomShip中生成船的随机位置和大小;

void randomShip () {

    ship = new boolean[NUM_COLS][NUM_ROWS];
    click = new boolean[NUM_COLS][NUM_ROWS];

    shipLength = (int)random (3, 8);

    int store = (int)random(vert, horz);  
    if (store >= 0) {

        int randomX = (int)random(NUM_COLS - shipLength);
        int randomY = (int)random(NUM_ROWS);

        for (int i = 0; i < shipLength; i++ ) {
            ship[randomX + i][randomY] = true;
        }
    } else  {

        int randomX = (int)random(NUM_COLS);
        int randomY = (int)random(NUM_ROWS - shipLength); 

        for (int i = 0; i < shipLength; i++ ) {
            ship[randomX][randomY+1] = true;
        }
    }
    println(shipLength);
}
  1. convert the mouse position in pixels into the row and column on the grid
  2. if the guess is correct, add the guess to the hit array and if missed adding it to the miss array.

鼠标坐标mouseXmouseY除以CELLSIZE

得到被点击的单元格
int cell_x = mouseX / CELLSIZE; 
int cell_y = mouseY / CELLSIZE; 

存储标记单击的单元格并计算 mouseClicked 中的命中和未命中:

void mouseClicked () {

    int cell_x = mouseX / CELLSIZE; 
    int cell_y = mouseY / CELLSIZE;

    if (!click[cell_x][cell_y]) {
        click[cell_x][cell_y] = true;

        if ( ship[cell_x][cell_y] ) {
            hitCount ++;
        } else {
            missCount ++;
        }
    }
}
  1. when a guess is made, in addition to colouring the cell, print either “Hit!” or “Miss!” on the cell

在 drawCells 中计算船舶位置 (ship[][]) 和点击位置 (click[][])。根据 2 个嵌套循环中的状态绘制单元格和文本:

void drawCells(int colour) {

    for (int i = 0; i < NUM_COLS; i++) {
        for (int j = 0; j < NUM_ROWS; j++) {

            float x = i * CELLSIZE;
            float y = j * CELLSIZE;

            if (ship[i][j]) {
                fill (colour);
                rect(x, y, CELLSIZE, CELLSIZE);
            }

            if (click[i][j]) {
                fill(255, 0, 0);
                textSize(15);
                text(ship[i][j] ? "hit" : "miss", x+10, y+30); 
            }
        }
    }
}
  1. sinking the ship when all cells have been hit

draw处理游戏结束:

例如

void draw() {

    drawCells(255);

    if (hitCount == shipLength ) {

        // [...]

    }
}

完整代码清单:

final int CELLSIZE = 50;
final int NUM_ROWS = 10;
final int NUM_COLS = 12;

int horz = (int)random(50);
int vert = (int)random(-50);

int store;
int shipLength;

boolean [][] ship;
boolean [][] click;

int hitCount = 0;
int missCount = 0;

void setup() {
    size(600, 500);
    randomShip();
    println(store);
}

void draw() {

    drawCells(255);

    if (hitCount == shipLength ) {

        // [...]

    }
}

void drawCells(int colour) {

    for (int i = 0; i < NUM_COLS; i++) {
        for (int j = 0; j < NUM_ROWS; j++) {

            float x = i * CELLSIZE;
            float y = j * CELLSIZE;

            if (ship[i][j]) {
                fill (colour);
                rect(x, y, CELLSIZE, CELLSIZE);
            }

            if (click[i][j]) {
                fill(255, 0, 0);
                textSize(15);
                text(ship[i][j] ? "hit" : "miss", x+10, y+30); 
            }
        }
    }
}

void randomShip () {

    ship = new boolean[NUM_COLS][NUM_ROWS];
    click = new boolean[NUM_COLS][NUM_ROWS];
    hitCount = 0;
    missCount = 0;

    shipLength = (int)random (3, 8);

    int store = (int)random(vert, horz);  
    if (store >= 0) {

        int randomX = (int)random(NUM_COLS - shipLength);
        int randomY = (int)random(NUM_ROWS);

        for (int i = 0; i < shipLength; i++ ) {
            ship[randomX + i][randomY] = true;
        }
    } else  {

        int randomX = (int)random(NUM_COLS);
        int randomY = (int)random(NUM_ROWS - shipLength); 

        for (int i = 0; i < shipLength; i++ ) {
            ship[randomX][randomY+1] = true;
        }
    }
    println(shipLength);
}

void mouseClicked () {

    int cell_x = mouseX / CELLSIZE; 
    int cell_y = mouseY / CELLSIZE;

    if (!click[cell_x][cell_y]) {
        click[cell_x][cell_y] = true;

        if ( ship[cell_x][cell_y] ) {
            hitCount ++;
        } else {
            missCount ++;
        }
    }
}