如何使用2D阵列与网格交互(Proce55ing)

时间:2017-01-06 16:28:17

标签: arrays grid processing interaction

对于我需要使用Processing创建Connect Four的项目,我已经创建了游戏将在其中播放的网格,但是当涉及到与之交互的玩家时我迷失了。

我被告知使用2D阵列但是我对阵列的了解非常有限。我目前正在尝试编写程序检测到玩家点击并在那里生成硬币的位置。

int c = 8;
int r = 10;
int[][] grid = new int [c][r];
int CoinSpawn = -1;

void setup () {
  size(1000, 800);
}
void draw () {
  background(1, 1, 1);
  translate(100, 100);
  noStroke();
  drawColumns();
  drawRows();
}
void keyPressed () {
  for (int i=0; i<grid.length-1; i++) {
    grid[i][i] = grid[i+1][i+1];
  }
}
void drawRows(){
  for (int i=0; i < r; i++){
   int x = 80;
   x = x * i;
   translate(x,0);
   drawColumns();
   translate(-x,0);
  }
}

void drawColumns(){
 for (int i=0; i < c; i++){
  int y = 80;
  y = y * i;
  translate(0,y);
  drawCell();
  translate(0,-y);
 }
}

void drawCell(){
  fill(0,0,255);
  rect(0,0,80,80);
  noFill();
  fill(0);
  ellipseMode(CENTER);
  translate(40,40);
  ellipse(0,0,75,75);
  noFill();
  translate(-40,-40);
}

我可以将2D数组分配给网格吗?这样网格中的每个槽代表一个来自数组的元素?这是我目前可以看到的最佳选择,但我不知道该怎么做。

我非常感谢任何回复,因为我现在完全失去了。

1 个答案:

答案 0 :(得分:0)

你有一个非常好的开始,我做了比我原计划更多的改变......加入了一点!

如果您有任何疑问,请告诉我,我确实使用了一个名为cell的简单OOP类来跟踪值和单元格的位置,并提供显示功能,我转换了很多变量和硬编码数字到常数(从final开始,对整个程序具有相同的值)

你会注意到我把胜利条件留给了你!

我希望这有用,我觉得在您熟悉的环境中使用2D数组可能会帮助您理解它们!

使用2D数组进行处理的常规过程: 使用Setup()设置初始数组值 使用Draw()调用项目的每个显示功能 使用其他函数修改数组数据,单元格的显示功能知道如何显示

主文件

// Grid Size constants
final int GRID_COLUMNS = 10;
final int GRID_ROWS = 8;

// Display constants

final int CELL_SCALE = 80;
final int COIN_RADIUS = 75;
final int BOARD_PADDING = 100;
final color[] PLAYER_COLORS = new color[]{color(0), color(200, 10, 10), color(200, 200, 10)};

// cell values
final int EMPTY_CELL = 0;
final int PLAYER_1 = 1;
final int PLAYER_2 = 2;

// game data
Cell[][] grid = new Cell [GRID_COLUMNS][GRID_ROWS];
int currentPlayer;

void setup () {
  size(1000, 800);
  ellipseMode(CENTER); // only needs to be set once per sketch

  setupBlankBoard();
}

// method to populate the array with blank cells, used to initiate and reset the game
void setupBlankBoard() {
  currentPlayer = PLAYER_1; // reset game and start with first player
  // populate array
  for (int y=0; y < GRID_ROWS; y++) { // for every vertical row,
    for (int x=0; x < GRID_COLUMNS; x++) { // for every horizontal cell in that row

      // rather than translates I prefer to calculate the actual x,y position and just display it there,
      // we add the padding offset to every cell, and then take the column/row times the width of the square cell
      grid[x][y] = new Cell(BOARD_PADDING+x*CELL_SCALE, BOARD_PADDING+y*CELL_SCALE);
    }
  }
}

void changePlayers() {
  if (currentPlayer == PLAYER_1) {
    currentPlayer = PLAYER_2;
  } else {
    // already was player 2, so change to 1
    currentPlayer = PLAYER_1;
  }
}

boolean placeCoin(int column) {
  boolean coinPlaced = false;

  // now we know the column, we need to find the lowest cell in that column that is empty
  for (int y = GRID_ROWS-1; y >= 0; y-- ) { // let's start at bottom and move up to reduce computations
    // for every cell, test if it is empty
    if (grid[column][y].isEmpty()) {
      // if found a valid cell,  place current players token and exit the loop (break)
      grid[column][y].setValue(currentPlayer);
      coinPlaced = true;
      break;
    }
  }

  return coinPlaced;
}

void checkCoins() {
  // scan the array for 4 of the same value in a row
  for (int y=0; y < GRID_ROWS; y++) { // for every vertical row,
    for (int x=0; x < GRID_COLUMNS; x++) { // for every horizontal cell in that row
      //grid[x][y]
      // I will leave this to you ;) 
      // keep in mind to check neighbors all you need to do is add or subtract 1 from the x or y value
      // however when you are at the edge of the board be careful not to try and look at a neighbor that is off the edge, you will get a null pointer or an array out of bounds exception
      if (x+1<GRID_COLUMNS) {
        Cell toTheRight = grid[x+1][y];
      }

      // for each cell you could look at the 3 above the current, 3 below the current, 3 to the right and 3 to the left, 3 diagnal in each direction and then manually try and find 4 adjacent same color cells
      // or a bit more complicated is a recursive solution that checks its 8 immediate neighbor and for each that match the center cell run the same function to test its 8 neighbors keeping track of the current inARowCount and returning true when it is found.
      // would be a bit hard because you would need to make sure the second cell doesn't follow back to the original cell, and start an endless loop
    }
  }
}

void draw () {
  background(1, 1, 1);
  noStroke();

  // draw all cells
  for (int y=0; y < GRID_ROWS; y++) { // for every vertical row,
    for (int x=0; x < GRID_COLUMNS; x++) { // for every horizontal cell in that row
      grid[x][y].display(); // draw this cell
    }
  }

  // draw next coin floating above the board, contrain its positon to above the board
  fill(PLAYER_COLORS[currentPlayer]);
  int currentMouseX = constrain(mouseX, BOARD_PADDING+COIN_RADIUS/2, BOARD_PADDING+(GRID_COLUMNS*CELL_SCALE)-COIN_RADIUS/2);
  //currentMouseX = 40*(ceil(abs(currentMouseX/40)));
  ellipse(currentMouseX, BOARD_PADDING/2, COIN_RADIUS, COIN_RADIUS);
}

// press any key to rest the game, probably want to test for a certain key here!
void keyPressed () {
  setupBlankBoard();
}

// on press attempt to place a coin
void mousePressed() {
  int currentMouseX = constrain(mouseX, BOARD_PADDING+COIN_RADIUS/2, BOARD_PADDING+(GRID_COLUMNS*CELL_SCALE)-COIN_RADIUS/2);

  // determine what column we are over
  int column = (currentMouseX - BOARD_PADDING)/CELL_SCALE;

  // if choice is a valid coin placement
  if (placeCoin(column)) {
    // toggle players if a coin was placed
    changePlayers();
    // after each placement check win conditions
    checkCoins();
  }
}

Cell Class

class Cell {
  int x, y;
  int value; // 0 for empty, 1 for team 1, 2 for team 2 (constants defined at top of main file)

  Cell(int x, int y) {
    // default constructor to create empty cell
    this(x, y, EMPTY_CELL);
  }

  // allows cell value to be set at creation
  Cell(int x, int y, int value) {
    this.x = x;
    this.y = y;
    this.value = value;
  }

  boolean setValue(int value){
    value = constrain(value, EMPTY_CELL,PLAYER_2); // keeps it from setting a value outside of our range

    if(this.value == EMPTY_CELL){
      this.value = value;
      return true; // placed
    }

    return false; // was not able to place it as there is already a value
  }

  boolean isEmpty(){
    return this.value == EMPTY_CELL;
  }

  void display() {
    fill(0, 0, 255);
    rect(this.x, this.y, CELL_SCALE, CELL_SCALE);

    // Draw Circle color based on current value, could simply just put fill(playerColors[this.value]); but this seems a bit more clear
    if(this.value == EMPTY_CELL){
      fill(PLAYER_COLORS[EMPTY_CELL]);
    }else if(this.value == PLAYER_1){
      fill(PLAYER_COLORS[PLAYER_1]); // red
    }else if(this.value == PLAYER_2){
      fill(PLAYER_COLORS[PLAYER_2]); // yellow
    }

    ellipse(this.x + CELL_SCALE/2, this.y + CELL_SCALE/2, COIN_RADIUS, COIN_RADIUS);
  }
}