منتدى مصر التقني
هل تريد التفاعل مع هذه المساهمة؟ كل ما عليك هو إنشاء حساب جديد ببضع خطوات أو تسجيل الدخول للمتابعة.

[Java]مشروع مفتوح المصدر لبرمجة لعبة المربعات المتساقطة Tetris game

اذهب الى الأسفل

[Java]مشروع مفتوح المصدر لبرمجة لعبة المربعات المتساقطة Tetris game Empty [Java]مشروع مفتوح المصدر لبرمجة لعبة المربعات المتساقطة Tetris game

مُساهمة من طرف NEXT الأحد فبراير 23, 2020 8:15 pm

اهلا بكم

تعد لعبة Tetris واحدة من ألعاب الكمبيوتر الأكثر شعبية التي تم إنشاؤها على الإطلاق. تم تصميم اللعبة الأصلية وبرمجتها بواسطة مبرمج روسي Alexey Pajitnov في عام 1985. ومنذ ذلك الحين ، أصبح Tetris متاحًا على كل منصة كمبيوتر تقريبًا في الكثير من الاختلافات. حتى هاتفي المحمول يحتوي على نسخة معدلة من لعبة #Tetris.


في هذه اللعبة ، لدينا سبعة أشكال مختلفة تسمى #tetrominoes. شكل S ، شكل Z ، شكل حرف T ، شكل حرف L ، شكل خط ، شكل MirroredL وشكل مربع. يتكون كل شكل من هذه الأشكال من أربعة مربعات. الأشكال تسقط من اعلى اللوحة. الهدف من لعبة Tetris هو تحريك الأشكال وتدويرها ، بحيث تتلاءم مع أكبر قدر ممكن. إذا نجحنا في تشكيل صف ، يتم تدمير الصف ونحرز نقاطًا. نلعب لعبة تتريس حتى نتفوق.

[Java]مشروع مفتوح المصدر لبرمجة لعبة المربعات المتساقطة Tetris game Tetris

بعض الأفكار وراء اللعبة.

نستخدم فئة Timer لإنشاء دورة لعبة
يتم رسمها tetrominoes
تتحرك الأشكال على أساس مربع (لا بكسل بالبكسل)
رياضيا لوحة هي قائمة بسيطة من الأرقام

لقد بسّطت اللعبة قليلاً ، بحيث يكون من الأسهل فهمها. تبدأ اللعبة على الفور ، بعد إطلاقها. يمكننا إيقاف اللعبة عن طريق الضغط على مفتاح p. سوف مفتاح الفضاء إسقاط قطعة تتريس على الفور إلى أسفل. سوف المفتاح d إسقاط قطعة سطر واحد لأسفل. (يمكن استخدامه لتسريع السقوط قليلاً). تسير اللعبة بسرعة ثابتة ، ولا يتم تنفيذ أي تسارع. النتيجة هي عدد الخطوط التي أزلناها.

وتتكون اللعبة من المفئات التالية :



  • Tetris.java
  • Shape.java
  • Board.java


1_كتابة محتوي الفئة Tetris.java

هذه هى الفئة الرئيسية للعبة تبدأ طريقة start () في لعبة 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(" 0");
        add(statusbar, BorderLayout.SOUTH);
        Board board = new Board(this);
        add(board);
        board.start();

        setSize(200, 400);
        setTitle("Tetris");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
   }

   public JLabel getStatusBar() {
       return statusbar;
   }

    public static void main(String[] args) {

        Tetris game = new Tetris();
        game.setLocationRelativeTo(null);
        game.setVisible(true);

    }
}


2_كتابة محتوي الفئة Shape.java

تقوم هذه الفئة بانشاء الاشكال او القطع الهندسية المستخدمة فى اللعبة
الكود:


import java.util.Random;
import java.lang.Math;


public class Shape {

//التعداد Tetrominoes يحمل جميع أشكال تتريس السبعة. بالإضافة إلى شكل فارغ يسمى هنا NoShape
    enum Tetrominoes { NoShape, ZShape, SShape, LineShape,
               TShape, SquareShape, LShape, MirroredLShape };

//هذا هو مُنشئ فئة الشكل. تحتوي مجموعة coords على الإحداثيات الفعلية لقطعة Tetris.
    private Tetrominoes pieceShape;
    private int coords[][];
    private int[][][] coordsTable;


    public Shape() {

        coords = new int[4][2];
        setShape(Tetrominoes.NoShape);

    }

    public void setShape(Tetrominoes shape) {
//تحتوي مجموعة coordsTable على جميع قيم الإحداثيات الممكنة لقطع تتريس لدينا.
//هذا هو القالب الذي تأخذ منه جميع القطع قيم الإحداثيات الخاصة بها
         coordsTable = 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 } }
        };

//نحن هنا نضع صفًا واحدًا من قيم الإحداثيات من ملف coordsTable إلى مجموعة coords من قطعة تتريس.
//لاحظ استخدام الطريقة ordinal() في C ++ ، يعد نوع التعداد عددًا صحيحًا. على عكس C ++ ، تعد enums Java فئات كاملة.
//وتقوم الطريقة الترتيبية () بإرجاع الموضع الحالي لنوع التعداد في كائن التعداد.
        for (int i = 0; i < 4 ; i++) {
            for (int j = 0; j < 2; ++j) {
                coords[i][j] = coordsTable[shape.ordinal()][i][j];
            }
        }
        pieceShape = shape;

    }

    private void setX(int index, int x) { coords[index][0] = x; }
    private void setY(int index, int y) { coords[index][1] = y; }
    public int x(int index) { return coords[index][0]; }
    public int y(int index) { return coords[index][1]; }
    public Tetrominoes getShape()  { return pieceShape; }

//هذا الكود يدور القطعة إلى اليسار. لا يلزم تدوير المربع. لهذا السبب نرجع ببساطة الإشارة إلى الكائن الحالي.
    public void setRandomShape()
    {
        Random r = new Random();
        int x = Math.abs(r.nextInt()) % 7 + 1;
        Tetrominoes[] values = Tetrominoes.values();
        setShape(values[x]);
    }

    public int minX()
    {
      int m = coords[0][0];
      for (int i=0; i < 4; i++) {
          m = Math.min(m, coords[i][0]);
      }
      return m;
    }


    public int minY()
    {
      int m = coords[0][1];
      for (int i=0; i < 4; i++) {
          m = Math.min(m, coords[i][1]);
      }
      return m;
    }

    public Shape rotateLeft()
    {
        if (pieceShape == Tetrominoes.SquareShape)
            return this;

        Shape result = new Shape();
        result.pieceShape = pieceShape;

        for (int i = 0; i < 4; ++i) {
            result.setX(i, y(i));
            result.setY(i, -x(i));
        }
        return result;
    }

    public Shape rotateRight()
    {
        if (pieceShape == Tetrominoes.SquareShape)
            return this;

        Shape result = new Shape();
        result.pieceShape = pieceShape;

        for (int i = 0; i < 4; ++i) {
            result.setX(i, -y(i));
            result.setY(i, x(i));
        }
        return result;
    }
}

3_كتابة محتوي الفئة Board.java

الكود:
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.Shape.Tetrominoes;


public class Board extends JPanel implements ActionListener {

//تهيئة بعض المتغيرات الهامة.

    final int BoardWidth = 10;
    final int BoardHeight = 22;

    Timer timer;
//يحدد المتغير isFallingFinished ما إذا كان شكل تتريس قد انتهى من السقوط ومن ثم نحتاج إلى إنشاء شكل جديد.
    boolean isFallingFinished = false;

    boolean isStarted = false;
    boolean isPaused = false;
 //يحسب numLinesRemoved عدد الأسطر التي أزلناها حتى الآن. تحدد متغيرات curX و cury الموضع الفعلي لشكل تتريس السقوط.
    int numLinesRemoved = 0;
    int curX = 0;
    int curY = 0;
    JLabel statusbar;
    Shape curPiece;
    Tetrominoes[] board;



    public Board(Tetris parent) {

//يجب علينا استدعاء الأسلوب setFocusable () بشكل صريح. من الآن ، لوحة لديه المدخلات لوحة المفاتيح.
       setFocusable(true);
       curPiece = new Shape();
//كائن مؤقت لحدث واحد أو أكثر من الأحداث بعد تأخير محدد.
// في حالتنا ، يقوم المؤقت باستدعاء طريقة actionPerformed () لكل 400 مللي ثانية.
       timer = new Timer(400, this);
       timer.start();

       statusbar =  parent.getStatusBar();
       board = new Tetrominoes[BoardWidth * BoardHeight];
       addKeyListener(new TAdapter());
       clearBoard();
    }
//يتحقق الأسلوب actionPerformed () مما إذا كان السقوط قد انتهى.
//إذا كان الأمر كذلك ، يتم إنشاء قطعة جديدة. إذا لم يكن الأمر كذلك ، فإن قطعة تتريس السقوط تسقط سطر واحد لأسفل.
    public void actionPerformed(ActionEvent e) {
        if (isFallingFinished) {
            isFallingFinished = false;
            newPiece();
        } else {
            oneLineDown();
        }
    }


    int squareWidth() { return (int) getSize().getWidth() / BoardWidth; }
    int squareHeight() { return (int) getSize().getHeight() / BoardHeight; }
    Tetrominoes shapeAt(int x, int y) { return board[(y * BoardWidth) + x]; }


    public void start()
    {
        if (isPaused)
            return;

        isStarted = true;
        isFallingFinished = false;
        numLinesRemoved = 0;
        clearBoard();

        newPiece();
        timer.start();
    }

    private void pause()
    {
        if (!isStarted)
            return;

        isPaused = !isPaused;
        if (isPaused) {
            timer.stop();
            statusbar.setText("paused");
        } else {
            timer.start();
            statusbar.setText(String.valueOf(numLinesRemoved));
        }
        repaint();
    }

//داخل طريقة الطلاء ، نرسم كل الكائنات على السبورة. اللوحة لها خطوتين
    public void paint(Graphics g)
    {
        super.paint(g);

        Dimension size = getSize();
        int boardTop = (int) size.getHeight() - BoardHeight * squareHeight();
//في الخطوة الأولى ، نقوم برسم جميع الأشكال ، أو بقايا الأشكال التي تم إسقاطها في أسفل اللوحة.
//يتم تذكر جميع المربعات في مجموعة اللوحة. يمكننا الوصول إليها باستخدام طريقة shapeAt ().

        for (int i = 0; i < BoardHeight; ++i) {
            for (int j = 0; j < BoardWidth; ++j) {
                Tetrominoes shape = shapeAt(j, BoardHeight - i - 1);
                if (shape != Tetrominoes.NoShape)
                    drawSquare(g, 0 + j * squareWidth(),
                               boardTop + i * squareHeight(), shape);
            }
        }
//في الخطوة الثانية ، نحن نرسم قطعة السقوط الفعلية.
        if (curPiece.getShape() != Tetrominoes.NoShape) {
            for (int i = 0; i < 4; ++i) {
                int x = curX + curPiece.x(i);
                int y = curY - curPiece.y(i);
                drawSquare(g, 0 + x * squareWidth(),
                           boardTop + (BoardHeight - y - 1) * squareHeight(),
                           curPiece.getShape());
            }
        }
    }
//إذا ضغطنا على مفتاح المسافة ، يتم إسقاط القطعة إلى الأسفل.
// نحن ببساطة نحاول إسقاط القطعة سطر واحد لأسفل حتى تصل إلى أسفل أو الجزء العلوي من قطعة تتريس الساقطة.
    private void dropDown()
    {
        int newY = curY;
        while (newY > 0) {
            if (!tryMove(curPiece, curX, newY - 1))
                break;
            --newY;
        }
        pieceDropped();
    }

    private void oneLineDown()
    {
        if (!tryMove(curPiece, curX, curY - 1))
            pieceDropped();
    }

//طريقة clearBoard () تملأ اللوحة بـ NoSpapes الفارغة. يستخدم لاحقا في الكشف عن التصادم.
    private void clearBoard()
    {
        for (int i = 0; i < BoardHeight * BoardWidth; ++i)
            board[i] = Tetrominoes.NoShape;
    }

//يضع الأسلوب pieceDropped () قطعة السقوط في صفيف اللوحة.
//مرة أخرى ، تحمل اللوحة جميع مربعات القطع وبقايا القطع التي انتهت من السقوط.
//عندما تنتهي القطعة من السقوط ، حان الوقت للتحقق مما إذا كان بإمكاننا إزالة بعض الخطوط من اللوحة.
// هذه هي وظيفة أسلوب removeFullLines (). ثم نقوم بإنشاء قطعة جديدة. بتعبير أدق ، نحاول إنشاء قطعة جديدة.
    private void pieceDropped()
    {
        for (int i = 0; i < 4; ++i) {
            int x = curX + curPiece.x(i);
            int y = curY - curPiece.y(i);
            board[(y * BoardWidth) + x] = curPiece.getShape();
        }

        removeFullLines();

        if (!isFallingFinished)
            newPiece();
    }

//تنشئ طريقة newPiece () قطعة تتريس جديدة.
// قطعة يحصل على شكل عشوائي جديد. ثم نقوم بحساب قيم curX و cury الأولية.
//إذا لم نتمكن من الانتقال إلى المراكز الأولية ، فإن اللعبة قد انتهت. نحن خارج. توقف الموقت. نضع اللعبة على السلسلة على شريط المعلومات.
    private void newPiece()
    {
        curPiece.setRandomShape();
        curX = BoardWidth / 2 + 1;
        curY = BoardHeight - 1 + curPiece.minY();

        if (!tryMove(curPiece, curX, curY)) {
            curPiece.setShape(Tetrominoes.NoShape);
            timer.stop();
            isStarted = false;
            statusbar.setText("game over");
        }
    }

    private boolean tryMove(Shape newPiece, int newX, int newY)
    {
        for (int i = 0; i < 4; ++i) {
            int x = newX + newPiece.x(i);
            int y = newY - newPiece.y(i);
            if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
                return false;
            if (shapeAt(x, y) != Tetrominoes.NoShape)
                return false;
        }

        curPiece = newPiece;
        curX = newX;
        curY = newY;
        repaint();
        return true;
    }

    private void removeFullLines()
    {
        int numFullLines = 0;

        for (int i = BoardHeight - 1; i >= 0; --i) {
            boolean lineIsFull = true;

            for (int j = 0; j < BoardWidth; ++j) {
                if (shapeAt(j, i) == Tetrominoes.NoShape) {
                    lineIsFull = false;
                    break;
                }
            }

            if (lineIsFull) {
                ++numFullLines;
                for (int k = i; k < BoardHeight - 1; ++k) {
                    for (int j = 0; j < BoardWidth; ++j)
                         board[(k * BoardWidth) + j] = shapeAt(j, k + 1);
                }
            }
        }

        if (numFullLines > 0) {
            numLinesRemoved += numFullLines;
            statusbar.setText(String.valueOf(numLinesRemoved));
            isFallingFinished = true;
            curPiece.setShape(Tetrominoes.NoShape);
            repaint();
        }
     }

    private void drawSquare(Graphics g, int x, int y, Tetrominoes shape)
    {
        Color colors[] = { new Color(0, 0, 0), new Color(204, 102, 102),
            new Color(102, 204, 102), new Color(102, 102, 204),
            new Color(204, 204, 102), new Color(204, 102, 204),
            new Color(102, 204, 204), new Color(218, 170, 0)
        };


        Color color = colors[shape.ordinal()];

        g.setColor(color);
        g.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2);

        g.setColor(color.brighter());
        g.drawLine(x, y + squareHeight() - 1, x, y);
        g.drawLine(x, y, x + squareWidth() - 1, y);

        g.setColor(color.darker());
        g.drawLine(x + 1, y + squareHeight() - 1,
                         x + squareWidth() - 1, y + squareHeight() - 1);
        g.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,
                         x + squareWidth() - 1, y + 1);
    }

    class TAdapter extends KeyAdapter {
         public void keyPressed(KeyEvent e) {

             if (!isStarted || curPiece.getShape() == Tetrominoes.NoShape) {
                 return;
             }

             int keycode = e.getKeyCode();

             if (keycode == 'p' || keycode == 'P') {
                 pause();
                 return;
             }

             if (isPaused)
                 return;

             switch (keycode) {
             case KeyEvent.VK_LEFT:
                 tryMove(curPiece, curX - 1, curY);
                 break;
             case KeyEvent.VK_RIGHT:
                 tryMove(curPiece, curX + 1, curY);
                 break;
             case KeyEvent.VK_DOWN:
                 tryMove(curPiece.rotateRight(), curX, curY);
                 break;
             case KeyEvent.VK_UP:
                 tryMove(curPiece.rotateLeft(), curX, curY);
                 break;
             case KeyEvent.VK_SPACE:
                 dropDown();
                 break;
             case 'd':
                 oneLineDown();
                 break;
             case 'D':
                 oneLineDown();
                 break;
             }

         }
     }
}

ـــــــــــــــــــ التوقيع ــــــــــــــــــــ
[Java]مشروع مفتوح المصدر لبرمجة لعبة المربعات المتساقطة Tetris game Do.php?imgf=154090993464951
NEXT
NEXT
الادارة
الادارة

تاريخ التسجيل : 18/02/2011
المساهمات : 446
النقاط : 200660
التقيم : 28
الدولة : مصر
الجنس : ذكر

الرجوع الى أعلى الصفحة اذهب الى الأسفل

الرجوع الى أعلى الصفحة

ََ

مواضيع ذات صلة


 
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى