Just a little question to how to make the game "battleships"

edited April 2016 in How To...

Hi.

So we all know the good old game "battleships", which i am trying to make as my exam project. However, i am WAY far away from being just a decent programmer.

All i want to ask is hints about how to make the battlefields in "battleships". Like, am i gonna need to use arrays in arrays? Or is there anything from cp5 that i can use to make the battlefields?

Thanks for any answer.

Tagged:

Answers

  • 2d arrays?

    Did you google it here in the forum?

  • Answer ✓

    Hey, that's a good one! Haven't had someone ask for this before.

    As with all software development projects, let's start simple and work our way up to complex. The first step is a simple layout / blank sketch.

    void setup(){
      size(1060,600);
      fill(255);
    }
    
    void draw(){
      background(0);
      rect(20,20,500,500);
      rect(540,20,500,500);
      rect(20,540,1020,40);
    }
    

    So far so good. We now know where we'll draw the different displays the game needs.

  • Answer ✓

    Now let's just make that a little bit more pretty.

    void setup(){
      size(1060,600);
      textSize(18);
    }
    
    void draw(){
      background(0);
      fill(128,128,255);
      stroke(0,0,255);
      for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
          rect(20+50*i,20+50*j,50,50);
          rect(540+50*i,20+50*j,50,50);
        }
      }
      //rect(20,20,500,500);
      //rect(540,20,500,500);
      fill(0);
      stroke(0,255,0);
      rect(20,540,1020,40);
      textAlign(CENTER,CENTER);
      fill(0,255,0);
      text("=== Text Area For Game Messages ===", width/2, 560);
    }
    

    Alright. Now we can see the sea, and we've got grid lines drawn and taken care of. We've also verified that the system message text will show up in the right position and is aligned properly.

  • edited April 2016

    @Chrisir Your question makes me feel like i dont even understand what 2d arrays are, haha, yea that's how bad of a programmer i am. But no i didnt google anything in the forum

  • edited April 2016 Answer ✓

    Now we need to make sure that we can draw different symbols in the grids based on the values stored in some data structures. So we create two arrays to store what is being displayed in each grid. We then call a function to draw these symbols instead of the plain rectangles we were drawing before. This function also has a secret parameter which determines if ships can be seen.

    int mine[][] = new int[10][10];
    int comp[][] = new int[10][10];
    
    void setup() {
      size(1060, 600);
      textSize(18);
      for( int t = 0; t < 20; t++){
        mine[int(random(10))][int(random(10))] = int(random(4));
        comp[int(random(10))][int(random(10))] = int(random(4));
      }
    }
    
    void draw() {
      background(0);
      for (int i=0; i<10; i++) {
        for (int j=0; j<10; j++) {
          pushMatrix();
          translate(20+50*i, 20+50*j);
          draw_square( mine[i][j], true );
          translate(520, 0);
          draw_square( comp[i][j], false );
          popMatrix();
          //      rect(20+50*i,20+50*j,50,50);
          //      rect(540+50*i,20+50*j,50,50);
        }
      }
      fill(0);
      stroke(0, 255, 0);
      rect(20, 540, 1020, 40);
      textAlign(CENTER, CENTER);
      fill(0, 255, 0);
      text("=== Text Area For Game Messages ===", width/2, 560);
    }
    
    void draw_square( int type, boolean secret ) {
      fill(128, 128, 255);
      stroke(0, 0, 255);
      rect(0, 0, 50, 50);
      // An draw other symbols.
      if ( type == 1 ) {
        fill(255);
        stroke(0);
        ellipse(25, 25, 30, 30);
      }
      if ( secret && ( type == 2 || type == 3  ) ) {
        fill(128);
        stroke(0);
        rect(5, 5, 40, 40);
      }
      if ( type == 3 ) {
        fill(255, 0, 0);
        stroke(0);
        ellipse(25, 25, 30, 30);
      }
    }
    

    Well, this takes care of all the visuals we'll need. Now we need to start programming some game logic. The next step is to add states to this sketch. We'll start in state #0, which is where you can click to place ships. Then we'll need a state where we're waiting for the user to click on the computer's grid. We might also want a YOU WIN state and a YOU LOSE state that show where the hidden computer controlled ships were, with an appropriate message displayed.

  • @TfGuy44 Wow, it looks pretty nice. Surprises me more than it should :).

    Well, apparently there was something else i wanted to ask too in my question, but i forgot because im so nervous about this exam project because im not a good programmer.

    Anyway, what i also wanted to know is when it comes to the shooting part in the game(where you click on the fields), what codes are good to use to make the clickable fields, if you know what i mean. Is there something from cp5 that can be used?

    Sorry if my question sounds dumb, because i am kinda dumb when it comes to programming.

    Thanks in advance.

  • edited April 2016

    @TfGuy44 Man, i wish i at least was as good as you at programming so simple things like this. Those codes you have in your comments in this thread - aren't they very easy for you to figure out? Because it isn't for me. Well i can only say thank you. Im gonna take my time to read and try to understand your code! :)

  • And so instead of adding states... I made some other changes.

    ArrayList<Sea> seas = new ArrayList();
    
    void setup() {
      size(1060, 600);
      textSize(18);
      for (int i=0; i<10; i++) {
        for (int j=0; j<10; j++) {
          seas.add(new Sea(20+50*i, 20+50*j, false) );
          seas.add(new Sea(540+50*i, 20+50*j, true) );
        }
      }
    }
    
    void draw() {
      background(0);
      for( int i = 0; i < seas.size(); i++){
        seas.get(i).draw();
      }
      fill(0);
      stroke(0, 255, 0);
      rect(20, 540, 1020, 40);
      textAlign(CENTER, CENTER);
      fill(0, 255, 0);
      text("=== Text Area For Game Messages ===", width/2, 560);
    }
    
    class Sea {
      boolean has_ship;
      boolean secret;
      boolean clicked;
      int x, y;
      Sea(int ix, int iy, boolean isecret) {
        has_ship = random(1)<.5;//false;
        secret = isecret;
        clicked = random(1)<.5;//false;
        x = ix;
        y = iy;
      }
      void draw() {
        pushMatrix();
        translate(x, y);
        fill(128, 128, 255);
        stroke(0, 0, 255);
        rect(0, 0, 50, 50);
        // An draw other symbols.
        if ( !has_ship && clicked ) {
          fill(255);
          stroke(0);
          ellipse(25, 25, 30, 30);
        }
        if ( !secret && has_ship ) {
          fill(128);
          stroke(0);
          rect(5, 5, 40, 40);
        }
        if ( has_ship && clicked ) {
          fill(255, 0, 0);
          stroke(0);
          ellipse(25, 25, 30, 30);
        }
        popMatrix();
      }
    }
    

    Whoa, what even changed here? Well, now I have a Sea class, which represents a single sea square. Why bother with this step? Well, even though it LOOKS the same, this step allows me to add logic to every square without worrying too much about the details...

  • ArrayList<Sea> seas = new ArrayList();
    
    void setup() {
      size(1060, 600);
      textSize(18);
      for (int i=0; i<10; i++) {
        for (int j=0; j<10; j++) {
          seas.add(new Sea(20+50*i, 20+50*j, false) );
          seas.add(new Sea(540+50*i, 20+50*j, true) );
        }
      }
    }
    
    void draw() {
      background(0);
      for ( int i = 0; i < seas.size (); i++) {
        seas.get(i).draw();
      }
      fill(0);
      stroke(0, 255, 0);
      rect(20, 540, 1020, 40);
      textAlign(CENTER, CENTER);
      fill(0, 255, 0);
      text("TRY CLICKING ON THE OCEANS!!!", width/2, 560);
    }
    
    void mousePressed() {
      for ( int i = 0; i < seas.size (); i++) {
        seas.get(i).click();
      }
    }
    
    class Sea {
      boolean has_ship;
      boolean secret;
      boolean clicked;
      int x, y;
      Sea(int ix, int iy, boolean isecret) {
        has_ship = random(1)<.5;//false;
        secret = isecret;
        clicked = false;
        x = ix;
        y = iy;
      }
      void draw() {
        pushMatrix();
        translate(x, y);
        fill(128, 128, 255);
        stroke(0, 0, 255);
        rect(0, 0, 50, 50);
        // An draw other symbols.
        if ( !has_ship && clicked ) {
          fill(255);
          stroke(0);
          ellipse(25, 25, 30, 30);
        }
        if ( !secret && has_ship ) {
          fill(128);
          stroke(0);
          rect(5, 5, 40, 40);
        }
        if ( has_ship && clicked ) {
          fill(255, 0, 0);
          stroke(0);
          ellipse(25, 25, 30, 30);
        }
        popMatrix();
      }
      void click() {
        if ( mouseX > x && mouseX < x+50 && mouseY > y && mouseY < y+50 ) {
          clicked = true;
        }
      }
    }
    

    And just like that, the grid suddenly recognizes where it's clicked.

  • And here's a version with a basic state system added. The sketch starts is a ship_place_state, and this lets you place your ship parts. This state ends when space is pressed, and then you can click on the enemy ocean to try to find where it randomly placed some ship parts. After each time you click, the computer will have a turn too. It's not a very smart AI yet, obviously, but at least now you have some code to work with, and all the basics are there.

    ArrayList<Sea> seas = new ArrayList();
    String msg = "";
    
    void setup() {
      size(1060, 600);
      textSize(18);
      for (int i=0; i<10; i++) {
        for (int j=0; j<10; j++) {
          seas.add(new Sea(20+50*i, 20+50*j, false) );
          seas.add(new Sea(540+50*i, 20+50*j, true) );
        }
      }
      msg = "Click your own ocean to place ship parts. Press space when done.";
    }
    
    void draw() {
      background(0);
      for ( int i = 0; i < seas.size (); i++) {
        seas.get(i).draw();
      }
      fill(0);
      stroke(0, 255, 0);
      rect(20, 540, 1020, 40);
      textAlign(CENTER, CENTER);
      fill(0, 255, 0);
      text(msg, width/2, 560);
    }
    
    void mousePressed() {
      for ( int i = 0; i < seas.size (); i++) {
        seas.get(i).click();
      }
    }
    
    class Sea {
      boolean has_ship;
      boolean secret;
      boolean clicked;
      int x, y;
      Sea(int ix, int iy, boolean isecret) {
        secret = isecret;
        has_ship = secret && random(1)<.2;//false;
        clicked = false;
        x = ix;
        y = iy;
      }
      void draw() {
        pushMatrix();
        translate(x, y);
        fill(128, 128, 255);
        stroke(0, 0, 255);
        rect(0, 0, 50, 50);
        // An draw other symbols.
        if ( !has_ship && clicked ) {
          fill(255);
          stroke(0);
          ellipse(25, 25, 30, 30);
        }
        if ( !secret && has_ship ) {
          fill(128);
          stroke(0);
          rect(5, 5, 40, 40);
        }
        if ( has_ship && clicked ) {
          fill(255, 0, 0);
          stroke(0);
          ellipse(25, 25, 30, 30);
        }
        popMatrix();
      }
      void click() {
        if ( mouseX > x && mouseX < x+50 && mouseY > y && mouseY < y+50 ) {
          if( ship_place_state && !secret ){
            has_ship = !has_ship;
          }
          if( secret && !ship_place_state ){
            clicked = true;
            computers_turn();
          }
        }
      }
    }
    
    void computers_turn(){
      for(int i = 0; i < seas.size(); i++){
        if( !seas.get(i).secret && !seas.get(i).clicked ){
          seas.get(i).clicked = true;
          return;
        }
      }
    }
    
    boolean  ship_place_state = true;
    
    void keyPressed(){
      if( ship_place_state && key == ' ' ){
        ship_place_state = false;
        msg = "Click on the Computer's grid to try to locate one of the enemy ships!";
      }
    }
    

    Make sure you understand how this code works before you try improving it. You'll need to learn quite a bit, but them's the brakes!

  • @TfGuy44

    I didnt ask for this much, but i guess it can't hurt. Thank you so much for your appreciable help, like really!! I will try to read and understand your wonderful code!

  • im so nervous about this exam project

    I think you've overstepped the mark here about supplying solutions to obvious homework questions. Poster even asked for hints and got pages of code written for him. Hopefully he'll do the right thing.

  • edited April 2016

    Yes, I agree.

    I mean, best write your own code and ask when / where you are stuck and post your own code.

    Otherwise you won't learn - and fail in any oral exam

  • That's why i asked for hints, not solutions.

  • yes, i appreciate that. my dismay wasn't aimed at you 8)

  • And also this wasn't homework.

  • edited April 2016

    No, I critized tfguy44 not you

    Also exam>>homework

  • But just come back when you have questions please

  • Hey agian, guys. I have a silly question. Can someone explain what the pushMatrix and popMatrix do exactly?

  • edited April 2016

    It saves and reactivates the matrix configuration:
    https://processing.org/reference/printMatrix_.html

    That includes things like translate(), rotate(), etc btW.

    P.S.: Matrix is automatically reset on each draw():
    https://Processing.org/reference/resetMatrix_.html

  • It means when you rotate or translate different stuff, pushMatrix and popMatrix makes it be isolated from each other

    So you can rotate one cube clockwise and the other counterclockwise

Sign In or Register to comment.