如何知道我触摸了网格的哪个单元格(10x10)?

Posted

技术标签:

【中文标题】如何知道我触摸了网格的哪个单元格(10x10)?【英文标题】:How to know which cell of a grid (10x10) I've touched? 【发布时间】:2015-03-18 16:34:19 【问题描述】:

我正在使用 Canvas 和我使用 canvas.drawRect 绘制的 10x10 网格创建一个扫雷器。问题是,我不知道如何获取任何单元格的坐标(例如:在我的网格上的位置 (2,3) 中,物理坐标是什么?)。也许我没有正确地做网格? (我是初学者..)但我必须使用画布,没有图形。我在这里看到了一些答案,但没有真正帮助我..

代码如下:

package com.example.meinsweeper_ja;

import java.util.Random;
import android.annotation.SuppressLint;
import android.content.*;
import android.graphics.*;
import android.util.*;
import android.view.*;

public class CustomView extends View 

private Paint black, grey, white, blue, green, yellow, red;
private Rect square, edge;
private boolean grid[][]; // true = uncovered false = covered
private boolean mines[][]; // true = mine false = no mine
private int arround[][]; // Nb of mine around
private float touchx[];
private float touchy[];
private int nb_mines, nb_ard;

public CustomView(Context c) 
    super(c);
    init();


public CustomView(Context c, AttributeSet as) 
    super(c, as);
    init();


public CustomView(Context c, AttributeSet as, int default_style) 
    super(c, as, default_style);
    init();


private void init() 
    black = new Paint(Paint.ANTI_ALIAS_FLAG);
    grey = new Paint(Paint.ANTI_ALIAS_FLAG);
    white = new Paint(Paint.ANTI_ALIAS_FLAG);
    yellow = new Paint(Paint.ANTI_ALIAS_FLAG);
    red = new Paint(Paint.ANTI_ALIAS_FLAG);
    green = new Paint(Paint.ANTI_ALIAS_FLAG);
    blue = new Paint(Paint.ANTI_ALIAS_FLAG);

    black.setColor(0xFF000000);
    grey.setColor(0xFF808080);
    white.setColor(0xFFFFFFFF);
    yellow.setColor(0xFFFFFF00);
    red.setColor(0xFFFF0000);
    green.setColor(0xFF00FF00);
    blue.setColor(0xFF0000FF);

    touchx = new float[10];
    touchy = new float[10];
    grid = new boolean[10][10];
    mines = new boolean[10][10];

    arround = new int[10][10];

    nb_mines = 20;

    square = new Rect(-24, -24, 24, 24);
    edge = new Rect(100, 100, 100, 100);

    reset();


private void reset() 
    for (int i = 0; i < 10; i++) 
        for (int j = 0; j < 10; j++) 
            grid[i][j] = false; // CLEAR THE BOARD
            if (nb_mines > 0)  // PLACE 20 MINES
                Random ping = new Random();
                if ((ping.nextInt(4) == 1)) 
                    mines[i][j] = true;
                    nb_mines--;
                
            
        
    

    for (int i = 0; i < 10; i++)  // CALCULATES NB OF MINES AROUND
        for (int j = 0; j < 10; j++) 
            if (!mines[i][j]) 
                nb_ard = 0;
                if (i == 0 && j == 0)  // TOP LEFT
                    if (mines[0][1])
                        nb_ard++;
                    if (mines[1][0])
                        nb_ard++;
                    if (mines[1][1])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (i == 0 && j > 0 && j < 9)  // 1st Column
                    if (mines[0][j - 1])
                        nb_ard++;
                    if (mines[0][j + 1])
                        nb_ard++;
                    if (mines[1][j])
                        nb_ard++;
                    if (mines[1][j - 1])
                        nb_ard++;
                    if (mines[1][j + 1])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (j == 0 && i < 9)  // 1st Row
                    if (mines[i - 1][0])
                        nb_ard++;
                    if (mines[i + 1][0])
                        nb_ard++;
                    if (mines[i][1])
                        nb_ard++;
                    if (mines[i - 1][1])
                        nb_ard++;
                    if (mines[i + 1][1])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (i == 9 && j == 9)  // BOTTOM RIGHT
                    if (mines[8][8])
                        nb_ard++;
                    if (mines[8][9])
                        nb_ard++;
                    if (mines[9][8])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (i == 9 && j < 9 && j > 0)  // Last Column
                    if (mines[9][j - 1])
                        nb_ard++;
                    if (mines[9][j + 1])
                        nb_ard++;
                    if (mines[8][j])
                        nb_ard++;
                    if (mines[8][j - 1])
                        nb_ard++;
                    if (mines[8][j + 1])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (j == 9 && i < 9 && i > 0)  // Last Row
                    if (mines[i - 1][0])
                        nb_ard++;
                    if (mines[i + 1][0])
                        nb_ard++;
                    if (mines[i][8])
                        nb_ard++;
                    if (mines[i - 1][8])
                        nb_ard++;
                    if (mines[i + 1][8])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (i == 0 && j == 9)  // BOTTOM LEFT
                    if (mines[0][8])
                        nb_ard++;
                    if (mines[1][9])
                        nb_ard++;
                    if (mines[1][8])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else if (i == 9 && j == 0)  // TOP RIGHT
                    if (mines[9][1])
                        nb_ard++;
                    if (mines[8][0])
                        nb_ard++;
                    if (mines[8][1])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                 else  // MIDDLE GRID
                    if (mines[i - 1][j - 1])
                        nb_ard++;
                    if (mines[i - 1][j])
                        nb_ard++;
                    if (mines[i - 1][j + 1])
                        nb_ard++;
                    if (mines[i][j - 1])
                        nb_ard++;
                    if (mines[i][j + 1])
                        nb_ard++;
                    if (mines[i + 1][j - 1])
                        nb_ard++;
                    if (mines[i + 1][j])
                        nb_ard++;
                    if (mines[i + 1][j + 1])
                        nb_ard++;
                    arround[i][j] = nb_ard;
                
            
        
    



@Override
public void onDraw(Canvas canvas) 
    super.onDraw(canvas);
    for (int i = 0; i < 10; i++) 
        for (int j = 0; j < 10; j++) 
            touchy[j] = 50.f;
            canvas.save();
            if (i == 0 && j == 0)
                canvas.translate(200.f, touchy[j]);
            else
                canvas.translate(touchx[i], touchy[j]);
            canvas.drawRect(edge, white);

            if (!grid[i][j])
                canvas.drawRect(square, black);
            else 
                if (arround[i][j] == 1) 
                    canvas.drawRect(square, grey);
                    canvas.drawText(Integer.toString(1), i, j, blue);
                 else if (arround[i][j] == 2) 
                    canvas.drawRect(square, grey);
                    canvas.drawText(Integer.toString(2), i, j, green);
                 else if (arround[i][j] == 3) 
                    canvas.drawRect(square, grey);
                    canvas.drawText(Integer.toString(3), i, j, yellow);
                 else if (arround[i][j] > 3) 
                    canvas.drawRect(square, grey);
                    canvas.drawText(Integer.toString(arround[i][j]), i, j,
                            red);
                 else if (mines[i][j]) 
                    canvas.drawRect(square, red);
                    canvas.drawText("M", i, j, black);
                 else if (arround[i][j] == 0)
                    canvas.drawRect(square, grey);
            
        
        touchx[i] += 50.f;
        canvas.translate(touchx[i], -10 * touchx[i]);
    


@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) 
    if (event.getActionMasked() == MotionEvent.ACTION_DOWN) 
        int pidX = (int) event.getX();
        int pidY = (int) event.getY();
        for (int i = 0; i < 10; i++) 
            for (int j = 0; j < 10; j++) 
                if (touchx[i] == pidX && touchy[j] == pidY) 
                    if (mines[i][j]) 
                        reset();
                    
                
            
        
        invalidate();
        return true;
    
    return super.onTouchEvent(event);


问题肯定出在 onDraw() 方法上,但正如我之前所说,我真的不知道如何以更好的方式绘制网格。希望你能理解我的问题。

我知道我有很大的方法,当我找到任何解决问题的方法时,我会解决这个问题。

提前致谢!

【问题讨论】:

请不要破坏您的帖子。如果你想删除你的问题,那很好。 【参考方案1】:

所以你可能会考虑重构你的代码......

创建一个像“Tile”这样的对象,而不是使用不同的对象。它可能看起来像: public enum DrawState Normal, Safe, Exploded; public class Paints public static Paint NORMAL, SAFE, EXPLODED; static NORMAL = new Paint(); NORMAL.setColor(...) setStyle(...) // etc // these can even be members of the DrawState just pass them into the // constructor then you can do like DrawState.Exploded.getPaint(); public class Tile private final int id; private Rect boundingRect; private boolean hasMine; private DrawState drawState; public Tile(int theId, Rect theBoundingRect, boolean mined) id = theId; boundingRect = theBoundingRect; hasMine = mined; drawState = DrawState.Normal; public boolean containsTouch(int x, int y) return boundingRect.contains(x, y); public void draw(Canvas c) switch (state) case Normal: c.drawRect(boundingRect, Paints.NORMAL); return; case Safe: c.drawRect(boundingRect, Paints.SAFE); return; case Exploded: c.drawRect(boundingRect, Paints.EXPLODED); public void setInspected() drawState = DrawState.SAFE; public boolean isMined() return hasMine; public int getId() return id; // etc

现在在您的自定义字段视图中,您可以执行以下操作:

@Override public boolean onTouch(MotionEvent event) for (Tile t : tiles) if (t.containsTouch(event.getX(), event.getY())) if (t.isMined()) reset(); else t.setInspected(); invalidate();

这让事情变得简单多了。当然,你必须初始化你的瓦片列表,你可以通过计算每个矩形的左、上、右、下,然后将 new Rect(l, t, r, b) 传入瓦片构造函数。然后它可以很容易地获取 id 或数组位置以及许多其他东西......

当然,如果你想把 id 作为一个元组,你可以使用取模运算符;如果您知道您的图块将保留在列表中的初始索引位置,您甚至不需要保存 id。同样,您也可以在初始化图块时传入 i 和 j 而不是 id。

希望这会有所帮助!

为进一步解释而编辑:

所以现在由于每个图块都有足够的信息来照顾自己,它可以有一个绘图功能,例如: public void draw(Canvas c) c.drawRect(boundingRect, drawState.getPaint()); // assuming the paint is set to Style.FILL it'll fill the // rect with t/l/b/r as was set during construction // if you had a flag image, you could draw it on top of the boundingRect // int t = boundingRect.centerX() - (flagImage.getIntrisnicWidth()/2); // int l = boundingRect.centerY() - (flagImage.getIntrisnicHeight()/2); // c.drawBitmap(flagImage, bitmapTop, bitmapLeft, null);

现在从您的自定义网格视图类中: @Override public void onDraw(Canvas c) // draw other things for (Tile t : tiles) t.draw(c); // draw other things

请记住,首先绘制的将被绘制,所以如果你这样做: canvas.drawRect(rect1); canvas.drawRect(rect2); 并且 rect2 与 rect1 在同一个位置,它会将其绘制在 rect1 上。

【讨论】:

谢谢,但在这种情况下,我不明白我是如何绘制网格的..? 更新了我原来的帖子来回答你的评论问题。如果回答对您有帮助,您能否将其标记为解决方案?

以上是关于如何知道我触摸了网格的哪个单元格(10x10)?的主要内容,如果未能解决你的问题,请参考以下文章

当我滚动 tableView 时,我怎么知道哪个单元格触摸了绿色区域

触摸时我的表格单元格不会立即突出显示

获取我正在触摸的文本视图在哪个 UIcollectionviewcell

如何使用 javascript 引用剑道网格中的特定单元格?

我如何知道在 jexcell javascript 库中突出显示了哪个单元格?

我如何知道在详细视图中选择了 tableview 中的哪个单元格?