GAMES TWO: LESSON Sixteen: Making Scored Cells Disappear

This version of Cantris is the most advanced to date. It still has a couple bugs. Part of your assignment will be to discover bugs in the applet. You should play several rounds of Cantris to make sure that you understand how it works and what it can do and what it CAN'T do.

This is the applet class. It has very few changes compared to the previous version of the applet.

import java.awt.*; import java.applet.*; import java.awt.event.*; import java.util.*; public class CC5 extends Applet implements Runnable{ Dimension d; Thread tm; Random r = new Random(); Image offI; int speed = 33; String title[] = { "C", "A", "N", "T", "R", "I", "S" }; GRID3 grid = new GRID3(); public void init(){ d = getSize(); offI=createImage(d.width,d.height); reset(); tm = new Thread(this); tm.start(); requestFocus(); this.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent k) { if(grid.keepPlaying()){ if(k.getKeyCode() == KeyEvent.VK_RIGHT){ grid.moveX(1); } else if(k.getKeyCode() == KeyEvent.VK_LEFT){ grid.moveX(-1); } else if(k.getKeyCode() == KeyEvent.VK_DOWN){ grid.rotate(); } else if(k.getKeyCode() == KeyEvent.VK_UP){ speed=100; } } else{ reset(); } repaint(); } }); } public void reset(){ grid=new GRID3(); } public void run(){ while(true){ while(grid.keepPlaying()){ grid.move_can(); if(grid.hit_bottom()){ grid.scoreGrid(); grid.spawn(); } repaint(); try{ Thread.sleep(speed); }catch(InterruptedException e){}; } } } public void update(Graphics g){ paint(g); } public void paint(Graphics g){ Graphics offG = offI.getGraphics(); offG.setColor(Color.white); offG.fillRect(0,0,d.width,d.height); grid.draw(offG); offG.setColor(Color.black); offG.setFont(new Font("sansserif", Font.BOLD, 24)); for(int i = 0; i<title.length; i++){ offG.drawString(title[i], 5, 30+30*i); } offG.setFont(new Font("sansserif", Font.PLAIN, 12)); if( grid.score==0) offG.drawString("Keep playing.",15,d.height-5); else if(grid.keepPlaying()) offG.drawString("SCORE: " + grid.score, 15,d.height-5); else{ offG.drawString("Press 'r'.", 15, d.height-2); offG.drawString("SCORE: " + grid.score,15,d.height-17); } g.drawImage(offI, 0, 0, this); } }

This is the grid class. Most of the changes were made in settle_cells and scoreGrid. Make sure that you understand the entire class completely. Especially note the way that values are assigned to the cells array versus the way that values are assigned to the grid array.

import java.awt.*; import java.util.*; public class GRID3{ CELL2[] cells = new CELL2[120]; CELL2[] can = new CELL2[3]; int[] grid = new int[300]; int col=3; int bottom[] = {210,210,210,210,210,210}; Color sel[] = { Color.red, Color.blue, Color.cyan, Color.green, Color.magenta, Color.yellow }; int next=0; Random r = new Random(); int cnt, lastCHKD, score; boolean gameOn = true; GRID3(){ for(int i = 0; i<grid.length; i++){ grid[i]=-1; } spawn(); } public void moveX(int m){ if(col>0 && m==-1){ if(test_bottom(m)){ col--; can[0].moveX(m); can[1].moveX(m); can[2].moveX(m); } } else if(col<5 && m==1){ if(test_bottom(m)){ col++; can[0].moveX(m); can[1].moveX(m); can[2].moveX(m); } } } public void rotate(){ Color hold = can[0].getColor(); can[0].setColor(can[1].getColor()); can[1].setColor(can[2].getColor()); can[2].setColor(hold); } public void settle_cells(){ for(int i=0; i<grid.length; i++){ if(grid[i]>0){ if(i>5 && grid[i-6]==-5 ){ //check cell under current cell to see if it is empty System.out.println("grid[i]: " + grid[i]); cells[grid[i]].y+=10; grid[i-6]=grid[i]; if(i+6<grid.length && grid[i+6]==-1){ bottom[i%6]+=10; grid[i]=-1; } else grid[i]=-5; } } } } public void move_can(){ can[0].moveY(); can[1].moveY(); can[2].moveY(); } public void scoreGrid(){ for(int i=0; i<grid.length-3; i++){ //System.out.println("VAL: " + grid[i]); if(i%6<4 && grid[i]>=0 && grid[i+1]>0 && grid[i+2]>0){ if(cells[grid[i]].getColor().equals(cells[grid[i+1]].getColor()) && cells[grid[i+1]].getColor().equals(cells[grid[i+2]].getColor()) ){ score++; System.out.println("MATCH: " + i + ", SCORE: " + score); cells[grid[i]].set_invisible(); cells[grid[i+1]].set_invisible(); cells[grid[i+2]].set_invisible(); //grid position emptied grid[i]=-5; grid[i+1]=-5; grid[i+2]=-5; } } settle_cells(); } //System.out.println("-----scoreGrid------"); } public boolean keepPlaying(){ if(cnt>cells.length-3) return false; return gameOn; } public void spawn(){ if(next<cells.length-3){ Color c[] = new Color[3]; col = 3; int x = 0; do{ for(int i = 0; i<c.length; i++){ x = Math.abs(r.nextInt()%sel.length); c[i]=sel[x]; } }while(c[0].equals(c[1]) || c[1].equals(c[2]) || c[2].equals(c[0]) ); can[0] = new CELL2( 0,c[0]); can[1] = new CELL2(10,c[1]); can[2] = new CELL2(20,c[2]); } cnt++; } public boolean hit_bottom(){ if(next>=cells.length-4){ gameOn=false; return true; } if(can[0].y >= bottom[col]){ for(int i=0; i<3; i++){ int grid_index=col+(210-bottom[col])*6/10+i*6; //System.out.println("GI: " + grid_index); grid[grid_index]=next; cells[next]=can[i]; next++; } bottom[col]-=30; return true; } if(bottom[col]<10) gameOn=false; return false; } public boolean test_bottom(int n){ if(can[0].y < bottom[col+n]) return true; return false; } public void draw(Graphics g){ if(next>0){ for(int i=0; i<next; i++){ cells[i].draw(g); } } can[0].draw(g); can[1].draw(g); can[2].draw(g); // for(int i=0; i<sel.length; i++){ // g.setColor(sel[i]); // g.fillRect(30+i*10,210,10,10); // } g.setColor(Color.black); g.drawRect(30,10,60,210); } }
Some slight modifications where made to the cell class:
import java.awt.*; class CELL2{ int x, y; Color c; boolean visible; CELL2(int dd, Color cc){ y = 20-dd; x = 60; c = cc; visible=true; } public Color getColor(){ return c; } public void setColor(Color cc){ c = cc; } public void set_invisible(){ visible=false; } public void set_visible(){ visible=true; } public void moveX(int n){ if(x>30 && n == -1){ x-=10; } else if(x<80 && n == 1){ x+=10; } } public void moveY(){ y+=2; } public void draw(Graphics g){ if(visible){ g.setColor(c); g.fillRect(x,y,10,10); } } }


ASSIGNMENT:

Make a bug list for this applet.

Figure out how to score verticle matches. (Testing for verticle matches will be difficult since they don't occur too often.)