Java İle Tetris Projesi (+Kaynak Kodlar)
-
Geçen dönem c# ile puzzle ödevinden sonra bu dönem java ile tetris ödevi hazırladım. Aslında proje zetcode.com adlı siteden çalıntı ama değişken ve fonksiyon isimlerini falan Türkçeleştirdim, birkaç yeni özellik ve bu özelliklerle birlikte birkaç bug ekledim :D Gönül isterdi ki sıfırdan yapayım ama ödev grup ödevi ve tek uğraşanda ben olunca mecbur böyle birşey yaptım...
Neyse, buyrun kodlar;-------------------------Tetris.java-------------------------------------------------------------------
package tetris; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JLabel; public class Tetris extends JFrame { JLabel statusbar; public Tetris() { statusbar = new JLabel("Puan: 0"); add(statusbar, BorderLayout.SOUTH); Board board = new Board(this); add(board); board.basla(); setSize(250, 570); setResizable(false); setTitle("NDAT - Tetris - 2012"); setDefaultCloseOperation(EXIT_ON_CLOSE); } public JLabel getStatusBar() { return statusbar; } public static void main(String[] args) { Tetris oyun = new Tetris(); oyun.setLocationRelativeTo(null); oyun.setVisible(true); } }--------------------------------------------Sekil.java-----------------------------------------------------------------
package tetris;
import java.util.Random;
public class Sekil
{
enum parcalar { Bos, ZSekli, SSekli, CizgiSekli, TSekli, KareSekli, LSekli, TersLSekli };
private parcalar pSekil;
private int koordinatlar[][];
private int[][][] koordinatTablosu;
public Sekil()
{
koordinatlar = new int[4][2];
setSekil(parcalar.Bos);
}
public void setSekil(parcalar sekil)
{
koordinatTablosu = new int[][][]
{
{ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
{ { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, 1 } },
{ { 0, -1 }, { 0, 0 }, { 1, 0 }, { 1, 1 } },
{ { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 } },
{ { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } },
{ { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } },
{ { -1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } },
{ { 1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } }
};
for (int i = 0; i < 4 ; i++)
{
for (int j = 0; j < 2; ++j)
{
koordinatlar[i][j] = koordinatTablosu[sekil.ordinal()][i][j];
}
}
pSekil = sekil;
}
private void setX(int index, int x)
{
koordinatlar[index][0] = x;
}
private void setY(int index, int y)
{
koordinatlar[index][1] = y;
}
public int x(int index)
{
return koordinatlar[index][0];
}
public int y(int index)
{
return koordinatlar[index][1];
}
public parcalar getSekil()
{
return pSekil;
}
public void setRandomSekil()
{
Random r = new Random();
int x = Math.abs(r.nextInt()) % 7 + 1;
parcalar[] values = parcalar.values();
setSekil(values[x]);
}
public int minX()
{
int m = koordinatlar[0][0];
for (int i=0; i < 4; i++)
{
m = Math.min(m, koordinatlar[i][0]);
}
return m;
}
public int minY()
{
int m = koordinatlar[0][1];
for (int i=0; i < 4; i++)
{
m = Math.min(m, koordinatlar[i][1]);
}
return m;
}
public Sekil solaCevir()
{
if (pSekil == parcalar.KareSekli)
return this;
Sekil result = new Sekil();
result.pSekil = pSekil;
for (int i = 0; i < 4; ++i)
{
result.setX(i, y(i));
result.setY(i, -x(i));
}
return result;
}
public Sekil sagaCevir()
{
if (pSekil == parcalar.KareSekli)
return this;
Sekil result = new Sekil();
result.pSekil = pSekil;
for (int i = 0; i < 4; ++i)
{
result.setX(i, -y(i));
result.setY(i, x(i));
}
return result;
}
}---------------------Board.java------------------------------------------------------------------------
package tetris;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import tetris.Sekil.parcalar;
public class Board extends JPanel implements ActionListener
{
final int BoardEn = 10;
final int BoardBoy = 22;
Timer timer;
boolean dususFlag = false;
boolean baslamaFlag = false;
boolean duraklamaFlag = false;
int silinenSatir = 0;
int curX = 0;
int curY = 0;
JLabel statusbar;
Sekil curParca;
parcalar[] board;
public Board(Tetris parent)
{
setFocusable(true);
curParca = new Sekil();
timer = new Timer(300, this);
timer.start();
statusbar = parent.getStatusBar();
board = new parcalar[BoardEn * BoardBoy];
addKeyListener(new TAdapter());
temizle();
}
@Override
public void actionPerformed(ActionEvent e)
{
if (dususFlag)
{
dususFlag = false;
yeniParca();
}
else
{
birSatirAsagi();
}
}
int kareEn()
{
return (int) getSize().getWidth() / BoardEn;
}
int kareBoy()
{
return (int) getSize().getHeight() / BoardBoy;
}
parcalar shapeAt(int x, int y)
{
return board[(y * BoardEn) + x];
}
public void basla()
{
if (duraklamaFlag)
return;
baslamaFlag = true;
dususFlag = false;
silinenSatir = 0;
temizle();
yeniParca();
timer.start();
}
private void duraklat()
{
if (!baslamaFlag)
return;
duraklamaFlag = !duraklamaFlag;
if (duraklamaFlag)
{
timer.stop();
statusbar.setText("Duraklatıldı");
}
else
{
timer.start();
statusbar.setText("Puan: " + String.valueOf(silinenSatir*100));
}
repaint();
}
public void paint(Graphics g)
{
super.paint(g);
Dimension size = getSize();
int boardTop = (int) size.getHeight() - BoardBoy * kareBoy();
for (int i = 0; i < BoardBoy; ++i)
{
for (int j = 0; j < BoardEn; ++j)
{
parcalar sekil = shapeAt(j, BoardBoy - i - 1);
if (sekil != parcalar.Bos)
kareCiz(g, 0 + j * kareEn(),boardTop + i * kareBoy(), sekil);
}
}
if (curParca.getSekil() != parcalar.Bos)
{
for (int i = 0; i < 4; ++i)
{
int x = curX + curParca.x(i);
int y = curY - curParca.y(i);
kareCiz(g, 0 + x * kareEn(),
boardTop + (BoardBoy - y - 1) * kareBoy(),
curParca.getSekil());
}
}
}
private void enDibe()
{
int newY = curY;
while (newY > 0)
{
if (!hareketDene(curParca, curX, newY - 1))
break;
--newY;
}
pieceDropped();
}
private void birSatirAsagi()
{
if (!hareketDene(curParca, curX, curY - 1))
pieceDropped();
}
private void temizle()
{
for (int i = 0; i < BoardBoy * BoardEn; ++i)
board[i] = parcalar.Bos;
}
private void pieceDropped()
{
for (int i = 0; i < 4; ++i)
{
int x = curX + curParca.x(i);
int y = curY - curParca.y(i);
board[(y * BoardEn) + x] = curParca.getSekil();
}
satirSil();
if (!dususFlag)
yeniParca();
}
private void yeniParca()
{
curParca.setRandomSekil();
curX = BoardEn / 2;
curY = BoardBoy - 1 + curParca.minY();
if (!hareketDene(curParca, curX, curY))
{
timer.stop();
statusbar.setText("Oyun Bitti!");
}
}
private boolean hareketDene(Sekil yeniParca, int yeniX, int yeniY)
{
//Parçaların form dışına çıkmasını engelleme kontrolü
//True döndürülürse istenilen hareketin gerçekleştirilmesi
for (int i = 0; i < 4; ++i)
{
int x = yeniX + yeniParca.x(i);
int y = yeniY - yeniParca.y(i);
if (x < 0 || x >= BoardEn || y < 0 || y >= BoardBoy)
return false;
if (shapeAt(x, y) != parcalar.Bos)
return false;
}
curParca = yeniParca;
curX = yeniX;
curY = yeniY;
repaint();
return true;
}
private void satirSil()
{
//Tam dolan satırların silinmesi ve silinen satırın üstündeki parçaların
//aşağıya kaydırılması.
//Kazanılan puanın label üstünde görüntülenmesi.
int silinenStrSayisi = 0;
for (int i = BoardBoy - 1; i >= 0; --i)
{
boolean satirDolu = true;
for (int j = 0; j < BoardEn; ++j)
{
if (shapeAt(j, i) == parcalar.Bos)
{
satirDolu = false;
break;
}
}
if (satirDolu)
{
++silinenStrSayisi;
for (int k = i; k < BoardBoy - 1; ++k)
{
for (int j = 0; j < BoardEn; ++j)
board[(k * BoardEn) + j] = shapeAt(j, k + 1);
}
}
}
if (silinenStrSayisi > 0)
{
silinenSatir += silinenStrSayisi;
if(silinenSatir<10)
statusbar.setText("Puan: " + String.valueOf(silinenSatir*100));
else if(silinenSatir>10 || silinenSatir<20)
statusbar.setText("Puan: " + String.valueOf(silinenSatir*110));
else if(silinenSatir <30 ||silinenSatir>20)
statusbar.setText("Puan: " + String.valueOf(silinenSatir*120));
else if(silinenSatir>30 || silinenSatir<40)
statusbar.setText("Puan: " + String.valueOf(silinenSatir*130));
else if(silinenSatir>40)
statusbar.setText("Puan: " + String.valueOf(silinenSatir*140));
dususFlag = true;
curParca.setSekil(parcalar.Bos);
repaint();
}
}
private void kareCiz(Graphics g, int x, int y, parcalar sekil)
{
Color colors[] =
{
new Color(0, 0, 0) , new Color(204, 102, 102),
new Color(204, 102, 204), new Color(102, 204, 204),
new Color(204, 204, 102), new Color(102, 204, 102),
new Color(102, 102, 204), new Color(218, 170, 0)
};
Color color = colors[sekil.ordinal()];
g.setColor(color);
g.fillRect(x + 1, y + 1, kareEn() - 2, kareBoy() - 2);
}
class TAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
if (!baslamaFlag || curParca.getSekil() == parcalar.Bos)
{
return;
}
int keycode = e.getKeyCode();
if (keycode == 'p' || keycode == 'P')
{
duraklat();
return;
}
if (keycode == 'e' || keycode == 'E')
{
System.exit(0);
}
if (keycode == 'r' || keycode == 'R')
{
baslamaFlag = true;
dususFlag = false;
silinenSatir = 0;
statusbar.setText("Puan: 0");
temizle();
yeniParca();
timer.start();
}
if (keycode == '.')
{
enDibe();
}
if (duraklamaFlag)
return;
switch (keycode)
{
case KeyEvent.VK_LEFT:
hareketDene(curParca, curX - 1, curY);
break;
case KeyEvent.VK_RIGHT:
hareketDene(curParca, curX + 1, curY);
break;
case KeyEvent.VK_DOWN:
hareketDene(curParca.sagaCevir(), curX, curY);
break;
case KeyEvent.VK_UP:
hareketDene(curParca.solaCevir(), curX, curY);
break;
case KeyEvent.VK_SPACE:
birSatirAsagi();
break;
}
}
}
}------------------------------------------------------------------------------
Kodları Belirtilen isimlerdeki dosyaları oluşturup içlerine c/p yapın. Sonra 3 kaynak kod dosyasınıda tetris adında bi klasör oluşturup onun içine atın. Package kullanıldığı için bu şekilde yapmanız gerekiyor ama yinede komut satırında derleyemeyebilirsiniz eğer benim gibi javada yeniyseniz :) o yüzden tavsiyem netbeans ya da eclipse kullanmanız.
Proje çalıntı ama açıklayamayacağım biyeri yok diyebilirim, her satırını tek tek okuyup çalıştım herşeyini açıklayabilirim eğer anlamadığınız yeri olursa.
Gelelim eklemelerime ve buglara:
-Oyunda puanlama yoktu, 5dakikada yaptım oldu. Hızı arttırma yapacaktım zorluk seviyesi için bununla birlikte ama alelacele eklediğim bişey oldu bu :p
-Oyun bittikten sonra kapat aç yapmak gerekiyodu, R tuşuna bikaç bişey ekledim yeni oyun ve reset olayını yaptırdım. Tabi buglarda bununla birlikte geldi(son parçanın iç içe geçmesi) duraklatma olayıyla falan karıştı, flaglarla oynayarak düzeltilebilir.
Başkada bişey aklıma gelmiyor şu an, oyunu başlattıktan sonra oynayabilmeniz için önce şu en sondaki switch-case yapısını incelemenizi tavsiye ederim :)
Oyunun Mantığı-Algoritması:
Tetris oyununda her parça 4 kutucuktan oluşur.(Latince Tetra kelimesi 4 anlamındadır) Burda yapılan koordinat düzlemini oluşturmak ve kutucukları koordinat düzleminde çizdirmek ve hareketleri içinde repaint yapmak. Bütün sıkıntısı çizim kısmı,hareketler tamamen koordinat düzlemi bilgisi ve 4 işlemden ibaret.
Anlamadığınız yerleri sorabilirsiniz hadi kolay gelsin :)
-
Çok güzelmiş hocam eline sağlık :)
-
derleyip bir yere upload edebilecek bir friendo var mı?
-
çiz
-
http://s2.dosya.tc/server14/Kinpnv/tetris.jar.html
Bu derlenmiş hali. Dün ben güzelce bi cevap yazmıştım ama şu "ipdeğişti" muhabbeti yüzünden yalan olmuş sanırım :/ oyun olarak saracağını sanmıyorum, direk başlıyor,gram görsellik yok,hızlanma yok,puanlama dandirik vs vs(85 aldım bu ödevle ama oynanmaz yani :D)... Olayı ufaktan java ve algoritma konularında birşeyler öğrenme & öğretme.
-
oyunu denedim. güzel olmuş :P
-
deniyeceğim.
teşekkürler hocam.
