2023年12月21日 星期四

WEEK15

 期末作品進度 : 希望可以解決按level2 和 level3 時 可以分別進到16*16和30*16格子數 每個格子都可以被按到

<程式碼>:

PImage bombImage;  // 儲存炸彈的圖片
boolean gameover = false;
int gameoverTime;
int[][] mine; 
boolean[][] open;
int selectedLevel = 0;//0表示未選擇級別 1表示第一關 2.... 3...
int gameState = 0;  // 0表示起始畫面,1表示遊戲中,2表示Level 2
int totalMines;
void openAll(int i, int j) 
{
  if (i < 0 || j < 0 || i >= rows || j >= cols || gameover) return;
  if (open[i][j] == true) return;

  open[i][j] = true;
  //如果是炸彈,顯示所有炸彈
  if (mine[i][j] == 9) 
  {
    revealAllBombs();
    gameover = true;//遊戲結束
    gameoverTime = millis();//紀錄遊戲結束時間
  }
  //如果是0,則遞迴打開相鄰格子
  if (mine[i][j] == 0) 
  {
    openAll(i - 1, j);
    openAll(i, j - 1);
    openAll(i, j + 1);
    openAll(i + 1, j);
  }
}

void addOne(int i, int j) 
{
  if (i < 0 || j < 0 || i >= rows || j >= cols) return;//範圍外,不處理
  if (mine[i][j] == 9) return;//地雷本身不用再+1
  mine[i][j]++;//如果不是就+1
}

void revealAllBombs() 
{
  //將所有炸彈顯示為已開啟,以顯示所有炸彈
  for (int i = 0; i < rows; i++) 
  {
    for (int j = 0; j < cols; j++) 
    {
      if (mine[i][j] == 9) 
      {
        open[i][j] = true;
      }
    }
  }
}
int rows , cols;
int cellSize;

void setup() {
  size(500, 500);
  rows = 16;
  cols = 30;
  cellSize = width / cols;//根據視窗大小和格子數量計算格子大小
  int mineCount = 0;
  //載入炸彈圖片
  bombImage = loadImage("bomb.png");
}

void draw() 
{
  background(255);

  if (gameState == 0) 
  {
    // 起始畫面 level1 按鈕
    fill(100, 100, 200);//按鈕的顏色
    rect(width / 4, height / 2 - 25, width / 2, 50);
    fill(255);//字的顏色 白色
    textSize(20);
    textAlign(CENTER, CENTER);
    text("LEVEL1", width / 2, height / 2 - 5);

    // level2 按鈕
    fill(100, 100, 200);
    rect(width / 4, height / 2 + 25, width / 2, 50);
    fill(255);
    textSize(20);
    textAlign(CENTER, CENTER);
    text("LEVEL2", width / 2, height / 2 + 45);

    // level3 按鈕
    fill(100, 100, 200);
    rect(width / 4, height / 2 + 75, width / 2, 50);
    fill(255);
    textSize(20);
    textAlign(CENTER, CENTER);
    text("LEVEL3", width / 2, height / 2 + 95);
  } 
  else if (gameState == 1 || gameState == 2) 
  {
    // 踩地雷遊戲
    for (int i = 0; i < rows; i++) 
    {
      for (int j = 0; j < cols; j++) 
      {
        if (open[i][j]) 
        {
          if (mine[i][j] == 0) 
          {
            fill(150);//沒有地雷也沒有數字的空白格子 顏色是深灰色
          } 
          else 
          {
            fill(200);//有數字的格子 顏色是淡灰色
          }
          rect(j * cellSize, i * cellSize, cellSize, cellSize);

          if (mine[i][j] == 0) continue;//如果格子為空就繼續

          if (mine[i][j] == 1) //如果數字為1
          {
            textSize(20);
            fill(0, 0, 255);
            textAlign(CENTER, CENTER);
            text("" + mine[i][j], j * cellSize + cellSize / 2, i * cellSize + cellSize / 2);
          } 
          else if (mine[i][j] == 2) //如果數字為2
          {
            textSize(20);
            fill(24, 123, 29);
            textAlign(CENTER, CENTER);
            text("" + mine[i][j], j * cellSize + cellSize / 2, i * cellSize + cellSize / 2);
          } 
          else if (mine[i][j] == 3) //如果數字為3
          {
            textSize(20);
            fill(255, 0, 0);
            textAlign(CENTER, CENTER);
            text("" + mine[i][j], j * cellSize + cellSize / 2, i * cellSize + cellSize / 2);
          } 
          else if (mine[i][j] == 9) //如果是踩到地雷
          {
            image(bombImage, j * cellSize, i * cellSize, cellSize, cellSize);
          }
        } 
        else 
        {
          fill(200);//沒有被打開的格子 顏色是淡灰色
          rect(j * cellSize, i * cellSize, cellSize, cellSize);
        }
      }
    }
  }

  if (gameover && millis() - gameoverTime > 2000) {//最後遊戲結束的畫面 若遊戲結束/遊戲結束時間超過2000毫秒(2秒) 
    background(0);//背景黑色
    textSize(50);
    fill(255, 0, 0);//紅色的字
    textAlign(CENTER, CENTER);
    text("Game Over", width / 2, height / 2);

    fill ( 100,100,200 );//restart的按鈕
    rect( width/4 , height /2 +50 ,width / 2 , 50);
    fill( 255 );
    textSize(20);
    textAlign(CENTER,CENTER);
    text("RESTART", width / 2 , height / 2 +75);
  }
}

void mousePressed() 
{
  if (gameState == 0) //在遊戲一開始的畫面檢查哪一個按鈕被按
  {
    // level1 按鈕
    if (mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 - 25 && mouseY < height / 2 + 25) 
    {
      selectedLevel = 1;//選擇第一關的按鈕
      gameState = 1;//遊戲狀態
      initializeGame();//初始化遊戲
    }
    // level2 按鈕
    else if ( mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 + 25 && mouseY < height / 2 + 75 ) 
    {
      selectedLevel = 2;
      gameState = 1;//遊戲狀態
      initializeLevel2();
    }
    // level3 按鈕
    else if (  mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 + 75 && mouseY < height / 2 + 125 ) 
    {
      selectedLevel = 3;
      gameState = 1;
      initializeLevel3();
    }
  } 
  else if (gameState == 1 || gameState == 2) 
  {
    // 獲取滑鼠點擊的位子
    int i = mouseY / cellSize;
    int j = mouseX / cellSize;
    //格子沒有被打開
    if (!open[i][j]) 
    {//就打開
      openAll(i, j);
    }
    
    //遊戲結束且結束過5秒後 看有沒有點restart鍵
    if (gameover && millis() - gameoverTime > 5000) 
    {
      if (mouseX > width / 4 && mouseX < width / 4 + width / 2 && mouseY > height / 2 + 50 && mouseY < height / 2 + 100) 
      {
        restartGame();
      }
    }
  }
}

void initializeGame() {
  int mineCount = 0;

  if (selectedLevel == 1)
  {
    rows = 10;
    cols = 10;
    totalMines = 9;
    cellSize = width / cols;
    surface.setSize(cols * cellSize, rows * cellSize);
  }
  else if (selectedLevel == 2)
  {
    rows = 16;
    cols = 16;
    totalMines = 30;
    cellSize = width / cols;
    surface.setSize(cols * cellSize, rows * cellSize);
  }
  else if (selectedLevel == 3)
  {
    rows = 16;
    cols = 30;
    totalMines = 60;
    cellSize = width / cols;
    surface.setSize(cols * cellSize, rows * cellSize);
  }
  
  mine = new int[rows][cols];
  open = new boolean[rows][cols];
  
  while (mineCount < totalMines) {
    int i = int(random(rows)), j = int(random(cols));
    if (mine[i][j] != 9) {
      mine[i][j] = 9;
      mineCount++;
    }
  }

  
  
  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      if (mine[i][j] == 9) {
        addOne(i - 1, j - 1);
        addOne(i - 1, j);
        addOne(i - 1, j + 1);
        addOne(i, j - 1);
        addOne(i, j + 1);
        addOne(i + 1, j - 1);
        addOne(i + 1, j);
        addOne(i + 1, j + 1);
      }
    }
  }
}

void initializeLevel2() {
  int mineCount = 0;

  rows = 16;
  cols = 16;
  totalMines = 30;
  cellSize = width / cols; // 根據視窗大小和格子數量計算格子大小

  mine = new int[rows][cols];
  open = new boolean[rows][cols];

  while (mineCount < totalMines) {
    int i = int(random(rows)), j = int(random(cols));
    if (mine[i][j] != 9) {
      mine[i][j] = 9;
      mineCount++;
    }
  }
  
  surface.setSize(cols * cellSize, rows * cellSize);

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      if (mine[i][j] == 9) {
        addOne(i - 1, j - 1);
        addOne(i - 1, j);
        addOne(i - 1, j + 1);
        addOne(i, j - 1);
        addOne(i, j + 1);
        addOne(i + 1, j - 1);
        addOne(i + 1, j);
        addOne(i + 1, j + 1);
      }
    }
  }
}

void initializeLevel3() {
  int mineCount = 0;

  rows = 16;
  cols = 30;
  totalMines = 60;
  cellSize = 30;

  mine = new int[rows][cols];
  open = new boolean[rows][cols];

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      open[i][j] = false;
    }
  }
  
  while (mineCount < totalMines) {
    int i = int(random(rows)), j = int(random(cols));
    if (mine[i][j] != 9) {
      mine[i][j] = 9;
      mineCount++;
    }
  }
  
  surface.setSize(cols * cellSize, rows * cellSize);

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      if (mine[i][j] == 9) {
        addOne(i - 1, j - 1);
        addOne(i - 1, j);
        addOne(i - 1, j + 1);
        addOne(i, j - 1);
        addOne(i, j + 1);
        addOne(i + 1, j - 1);
        addOne(i + 1, j);
        addOne(i + 1, j + 1);
      }
    }
  }
}

void restartGame() {
  gameState = 0;//初始化遊戲狀態
  gameover = false;//重置遊戲結束為false
  gameoverTime = 0;//重置遊戲結束時間
  
  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      open[i][j] = false;
      mine[i][j] = 0;
    }
  }
}


沒有留言:

張貼留言