إعلان
دورة تطوير التطبيقات باستخدام لغة JavaScript في هذه الدورة ستتعلم لغة جافا سكريبت, استخدام مكتبة React.js, بناء API الموقع بواسطة Node.js, تطوير تطبيق جوال باستخدام React Native, و في نهاية الدورة ستتعلم تطوير تطبيق محادثة شبيه بتطبيق WhatsApp. تعلم الآن
دورة تطوير واجهات المستخدم في هذه الدورة ستتعلم لغة HTML و لغة CSS و لغة JavaScript. من ناحية التطبيق العملي ستتعلم طريقة بناء واجهة متجر إلكتروني مكون من ست صفحات, تحويل خمسة تصاميم PSD إلى صفحات ويب, بناء واجهة مستخدم تشبه موقع يوتيوب, بناء لوحة تحكم إحترافية. تعلم الآن
تطوير تطبيقات باستخدام لغة بايثون في هذه الدورة ستتعلم أساسيات البرمجة بلغة بايثون وصولاً إلى التعامل مع أشهر أطر العمل (Flask و Django) و ستتعلم كيف تبني متجر إلكتروني يمكن للمستخدمين البيع و الشراء من خلاله. تعلم الآن
دورة تطوير تطبيقات الويب باستخدام لغة PHP في هذه الدورة ستتعلم لغة PHP من الصفر, استخدام إطار العمل Laravel بشرح مفصّل و عملي, كيفية تطوير شبكة اجتماعية تشبه Instagram, بناء API لتطبيق جوال وفق أسلوب RESTful, تطوير موقع إعلانات مبوبة, تطوير نظام إدارة محتوى CMS كامل. تعلم الآن
دورة تطوير تطبيقات الويب باستخدام لغة Ruby في هذه الدورة ستتعلم البرمجة بلغة Ruby إنطلاقاً من أبسط المفاهيم وحتى بناء تطبيق حقيقي, إستخدام إطار العمل Ruby on Rails بشرح مفصّل و عملي, بناء تطبيق حقيقي عبارة عن شبكة اجتماعية تشبه تويتر, تطوير مجتمع الكتروني يشبه حسوب I/O. تعلم الآن
دورة علوم الحاسوب هذه الدورة معدة لتكون مدخل لعلوم الحاسوب و لغات البرمجة حيث ستتعرف فيها على أنظمة التشغيل و ستتعمق في نظام لينكس و في كيفية التعامل معه من خلال موجه الأوامر, بالإضافة إلى قواعد البيانات و أساسيات الشبكات و الخوادم و مبادئ الحماية والأمان في الويب. تعلم الآن

    Swing طريقة إنشاء لعبة الأفعى Snake 2D

    في هذا الدرس ستتعلم طريقة إنشاء لعبة ( Snake 2D ) إحترافية بإستخدام إطار الـ Swing.

    java swing 2d snake game source code تحميل كود لعبة الأفعى في جافا


    مميزات اللعبة

    • أعلى مجموع يصل إليه اللاعب يبقى مخزناً حتى إذا تم إغلاق اللعبة.
    • يمكن إيقاف و متابعة اللعبة بالنقر على زر المسافة الفارغة Space.
    • إذا لمست الأفعى الحائط لا يخسر اللاعب, لأن الأفعى ستظهر من الجهة المقابلة.
    • يمكن تعديل كود اللعبة بكل سهولة لأنه غير معقد.


    بناء اللعبة

    في هذا المشروع قمنا بوضع ملفات الجافا بداخل مجلد إسمه snake_2d.
    و قمنا بوضع الصور بداخل مجلد إسمه images كما في الصورة التالية.

    ⇓ تحميل اللعبة ⇓ تحميل المشروع كاملاً ⇓ تحميل مجلد الصور فقط



    كود اللعبة

    Position.java
    //  snake_2d  موجود بداخل المجلد  Position.java   هنا ذكرنا أن الملف
    package snake_2d;
    
    // قمنا بإنشاء هذا الكلاس لجعل أي كائن منه يمثل موقع دائرة من الدوائر الموجودة في الأفعى
    public class Position {
     
        // إذاً كل دائرة في الأفعى ستكون موجودة في نفس الوقت على خط طول و خط عرض محددين
        int x, y;
     
        // قمنا بتجهيز هذا الكونستركتور لتحديد مكان وجود أي دائرة في الأفعى لحظة إنشاء الكائن منه
        public Position(int x, int y) {
            this.x = x;
            this.y = y;
        }
     
    }
    		

    GameDrawer.java
    //  snake_2d  موجود بداخل المجلد  GameDrawer.java   هنا ذكرنا أن الملف
    package snake_2d;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.util.LinkedList;
    import java.util.Random;
    import javax.swing.ImageIcon;
    import javax.swing.JPanel;
    import javax.swing.Timer;
     
    // أي أصبح هذا الكلاس يمثل حاوية ,JPanel هنا قمنا بإنشاء كلاس يرث من الكلاس
    // حتى نجعل المستخدم قادر على تحريك الأفعى من الكيبورد KeyListener و جعلناه يطبق الإنترفيس
    // حتى نستطيع رسم الأفعى من جديد كلما تحركت ActionListener و جعلناه يطبق الإنترفيس
    public class GameDrawer extends JPanel implements KeyListener, ActionListener{
     
        // قمنا بإنشاء هاتين المصفوفتين لتخزين مكان وجود كل دائرة من الأفعى كل لحظة, أي لتحديد المكان المحجوز لعرض دوائر الأفعى
        // ( بما أن عدد الدوائر الأقصى بالطول هو 22 و بالعرض هو أيضاً 22, فهذا يعني أنه يمكن تخزين 22×22 دائرة ( أي 484
        final int[] boardX = new int[484];
        final int[] boardY = new int[484];
     
        // سنستخدم هذه المصفوفة لتخزين مكان وجود كل دائرة في الأفعى حتى نعرف الموقع الذي لا يجب أن نظهر فيه الدائرة الحمراء
        // ملاحظة: سبب إستخدام هذا المصفوفة لتخزين موقع كل دائرة في الأفعى من جديد هو فقط لجعل اللعبة لا تعلق, أي لتحسين أداء اللعبة
        LinkedList<Position> snake = new LinkedList();
     
        // سنستخدم هذه المتغيرات لتحديد الإتجاه الذي ستتجه إليه الأفعى
        boolean left = false;
        boolean right = false;
        boolean up = false;
        boolean down = false;
     
        // سنستخدم هذه الكائنات لرسم إتجاه وجه الأفعى
        ImageIcon lookToRightImage = new ImageIcon(this.getClass().getResource("/images/face-look-right.jpg"));
        ImageIcon lookToLeftImage = new ImageIcon(this.getClass().getResource("/images/face-look-left.jpg"));
        ImageIcon lookToUpImage = new ImageIcon(this.getClass().getResource("/images/face-look-up.jpg"));
        ImageIcon lookToDownImage = new ImageIcon(this.getClass().getResource("/images/face-look-down.jpg"));
     
        // سنستخدم هذا الكائن في كل مرة لرسم جسد الأفعى
        ImageIcon snakeBodyImage = new ImageIcon(this.getClass().getResource("/images/body.png"));
     
        // سنستخدم هذا الكائن في كل مرة لرسم طعام الأفعى
        ImageIcon fruitImage = new ImageIcon(this.getClass().getResource("/images/fruit.png"));
     
        // سنستخدم هذا المتغير لتخزين عدد الدوائر التي تشكل الأفعى
        int lengthOfSnake = 3;
     
        // سنستخدم هاتين المصفوفتين لتحديد الأماكن التي يمكن أن يظهر فيها الطعام
        int[] fruitXPos = {20, 40, 60, 80, 100, 120, 140, 160, 200, 220, 240, 260, 280, 300, 320, 340, 360, 380, 400, 420, 440, 460};
        int[] fruitYPos = {20, 40, 60, 80, 100, 120, 140, 160, 200, 220, 240, 260, 280, 300, 320, 340, 360, 380, 400, 420, 440, 460};
     
        // سنستخدم هذا الكائن لجعل الأفعى تستمر بالحركة .Thread و الذي يشبه الـ Timer هنا قمنا بإنشاء كائن من الكلاس
        Timer speedTimer;
     
        // سنستخدم هذا المتغير لتحديد أنه كل 0.1 ثانية سستتحرك الأفعى
        int delay = 100;
     
        // سنستخدم هذا المتغير لمعرفة إذا كانت الأفعى تتحرك أم لا
        int moves = 0;
     
        // سنستخدم هذه المتغيرات لتحديد المجموع الذي يحققه اللاعب أثناء اللعب
        int totalScore = 0;
        int fruitEaten = 0;
        int scoreReverseCounter = 99;
     
        // في حال كان اللاعب قد حقق مجموع عالي من قبل, سيتم إظهاره كأفضل مجموع وصل إليه
        int bestScore = readBestScorefromTheFile();
     
        // لتوليد أماكن ظهور طعام الأفعى بشكل عشوائي random سنستخدم الكائن
        Random random = new Random();
     
        // هنا قمنا بتحديد مكان أول طعام سيظهر في اللعبة قبل أن يبدأ المستخدم باللعب, و جعلناه يظهر تحت الأفعى
        int xPos = random.nextInt(22);
        int yPos = 5+random.nextInt(17);
     
        // سنستخدم هذا المتغير لمعرفة ما إذا كان المستخدم قد خسر أم لا
        boolean isGameOver = false;
     
        // هنا تحديد حجم اللعبة و تهيئتها لإستشعار الأزرار التي ينقر عليها المستخدم لحظة إنشاء كائن من هذا الكلاس
        // لجعل اللعبة تتحرك بسرعة 0.1 بالثانية speedTimer و قمنا تهيئة اللعبة لإستشعار الأزرار التي ينقر عليها المستخدم و تهيئة الكائن
        public GameDrawer()
        {
            setPreferredSize(new Dimension(750, 500));
            addKeyListener(this);
            setFocusable(true);
            setFocusTraversalKeysEnabled(false);
            speedTimer = new Timer(delay, this);
        }
     
        @Override
        public void setSize(int width, int height) {
            super.setSize(width, height);
        }
     
        @Override
        public void setBounds(int x, int y, int width, int height) {
            super.setBounds(x, y, width, height);
        }
     
        // (لتحديد كيف سيتم رسم و تلوين كل شيء في الحاوية (أي في اللعبة paint() للدالة Override هنا فعلنا
        // ملاحظة هذه الدالة تستدعى بشكل تلقائي عند رسم أي شيء في الحاوية
        @Override
        public void paint(Graphics g)
        {
            // هنا قمنا بتحديد مكان وجود الأفعى في كل مرة يقوم المستخدم ببدأ اللعبة من جديد
            if(moves == 0)
            {
                boardX[2] = 40;
                boardX[1] = 60;
                boardX[0] = 80;
     
                boardY[2] = 100;
                boardY[1] = 100;
                boardY[0] = 100;
     
                scoreReverseCounter = 99;
                speedTimer.start();
            }
     
            // هنا قمنا بجعل المجموع الحالي الذي وصل إليه المستخدم يظهر كأعلى مجموع وصل إليه في حال تخطى المجموع القديم
            if(totalScore > bestScore)
                bestScore = totalScore;
     
            // هنا قمن بإنشاء مربع أسود يمثل لون خلفية اللعبة
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, 750, 500);
     
            // هنا قمنا برسم المربعات التي تشكل الحدود التي لا تستطيع الأفعى عبورها باللون الرمادي
            // حجم كل مربع 13 بيكسل و المسافة بينهما 5 بيكسل
            g.setColor(Color.DARK_GRAY);
            for(int i=6; i<=482; i+=17)
                for(int j=6; j<=482; j+=17)
                    g.fillRect(i, j, 13, 13);
     
            // هنا فمنا بإنشاء مربع أسود كبير فوق المربعات التي تشكل حدود اللعبة لتظهر و كأنها فارغة من الداخل
            g.setColor(Color.BLACK);
            g.fillRect(20, 20, 460, 460);
     
            // هنا قمنا بكتابة إسم اللعبة و تلوينه بالأزرق
            g.setColor(Color.CYAN);
            g.setFont(new Font("Arial", Font.BOLD, 26));
            g.drawString("Snake 2D", 565, 35);
     
            // هنا قمنا بكتابة إسم اللعبة و تلوينه بالأزرق
            g.setFont(new Font("Arial", Font.PLAIN, 13));
            g.drawString("+ "+scoreReverseCounter, 510, 222);
     
            // هنا جعلنا أي شيء سنقوم بكتابته يظهر باللون الرمادي
            g.setColor(Color.LIGHT_GRAY);
     
            // هنا قمنا بطباعة أنه تم تطوير اللعبة بواسطة موقعنا
            g.setFont(new Font("Arial", Font.PLAIN, 15));
            g.drawString("Developed by harmash.com", 530, 60);
     
            // لقياس حجم الأرفام الظاهرة في المربعات الثلاث بالبيكسل حتى نستطيع عرضهم في الوسط FontMetrics هنا قمنا بإنشاء الكائن
            FontMetrics fm = g.getFontMetrics();
     
            // هنا جعلنا أي شيء سنقوم بكتابته يظهر بنوع و حجم هذا الخط
            g.setFont(new Font("Arial", Font.PLAIN, 18));
     
            //و المربع الذي تحته و الرقم الذي بداخله Best Score هنا قمنا برسم النص
            g.drawString("Best Score", 576, 110);
            g.drawRect(550, 120, 140, 30);
            g.drawString(bestScore+"", 550+(142-fm.stringWidth(bestScore+""))/2, 142);
     
            //و المربع الذي تحته و الرقم الذي بداخله Total Score هنا قمنا برسم النص
            g.drawString("Total Score", 573, 190);
            g.drawRect(550, 200, 140, 30);
            g.drawString(totalScore+"", 550+(142-fm.stringWidth(totalScore+""))/2, 222);
     
            //و المربع الذي تحته و الرقم الذي بداخله Fruit Eaten هنا قمنا برسم النص
            g.drawString("Fruit Eaten", 575, 270);
            g.drawRect(550, 280, 140, 30);
            g.drawString(fruitEaten+"", 550+(142-fm.stringWidth(fruitEaten+""))/2, 302);
     
            // Controls هنا قمنا برسم النص
            g.setFont(new Font("Arial", Font.BOLD, 16));
            g.drawString("Controls", 550, 360);
     
            // Controls هنا قمنا برسم النصوص الظاهرة تحت النص
            g.setFont(new Font("Arial", Font.PLAIN, 14));
            g.drawString("Pause / Start : Space", 550, 385);
            g.drawString("lookTo Up : Arrow Up", 550, 410);
            g.drawString("lookTo Down : Arrow Down", 550, 435);
            g.drawString("lookTo Left : Arrow Left", 550, 460);
            g.drawString("lookTo Right : Arrow Right", 550, 485);
     
            // هنا جعلنا الأفعى تنظر ناحية اليمين قبل أن يبدأ اللاعب بتحريكها
            lookToRightImage.paintIcon(this, g, boardX[0], boardY[0]);
     
            // هنا قمنا بمسح مكان وجود الأفعى السابق لأننا سنقوم بتخزين المكان الجديد كلما تحركت
            snake.clear();
     
            // هنا قمنا بإنشاء حلقة ترسم كامل الدوائر التي تشكل الأفعى كل 0.1 ثانية
            for(int i=0; i<lengthOfSnake; i++)
            {
                if(i==0 && left)
                    lookToLeftImage.paintIcon(this, g, boardX[i], boardY[i]);
     
                else if(i==0 && right)
                    lookToRightImage.paintIcon(this, g, boardX[i], boardY[i]);
     
                else if(i==0 && up)
                    lookToUpImage.paintIcon(this, g, boardX[i], boardY[i]);
     
                else if(i==0 && down)
                    lookToDownImage.paintIcon(this, g, boardX[i], boardY[i]);
     
                else if(i!=0)
                    snakeBodyImage.paintIcon(this, g, boardX[i], boardY[i]);
     
                // snake هنا قمنا بتخزين الموقع الحالي لكل دائرة في الأفعى في الكائن
                snake.add(new Position(boardX[i], boardY[i]));
            }
     
            // تقل بشكل تدريجي و أدنى قيمة ممكن أن تصل إليها هي 10 scoreReverseCounter هنا جعلنا قيمة العداد
            if(scoreReverseCounter != 10)
                scoreReverseCounter--;
     
            // هنا قمنا بإنشاء هذه الحلقة للتأكد إذا كان رأس الأفعى قد لامس أي جزء من جسدها
            for(int i=1; i<lengthOfSnake; i++)
            {
                // إذاً عندما يلمس رأس الأفعى جسدها سيتم جعل أول دائرة موجودة خلف الرأس تمثل رأس الأفعى حتى لا يظهر رأسها فوق جسدها
                if(boardX[i] == boardX[0] && boardY[i] == boardY[0])
                {
                    if(right)
                        lookToRightImage.paintIcon(this, g, boardX[1], boardY[1]);
     
                    else if(left)
                        lookToLeftImage.paintIcon(this, g, boardX[1], boardY[1]);
     
                    else if(up)
                        lookToUpImage.paintIcon(this, g, boardX[1], boardY[1]);
     
                    else if(down)
                        lookToDownImage.paintIcon(this, g, boardX[1], boardY[1]);
     
                    // للإشارة إلى أن اللاعب قد خسر true تساوي isGameOver بعدها سيتم جعل قيمة الـ
                    // Space و بالتالي يمكنه أن يبدأ من جديد بالنقر على زر المسافة الفارغة
                    isGameOver = true;
     
                    // يتوقف و بالتالي ستتوقف الأفعى تماماً عن الحركة speedTimer بعدها سيتم جعل الـ
                    speedTimer.stop();
     
                    // Game Over بعدها سيتم إظهار النص
                    g.setColor(Color.WHITE);
                    g.setFont(new Font("Arial", Font.BOLD, 50));
                    g.drawString("Game Over", 110, 220);
     
                    // تحته Press Space To Restart و سيتم إظهار النص
                    g.setFont(new Font("Arial", Font.BOLD, 20));
                    g.drawString("Press Space To Restart", 130, 260);
     
                    // في الأخير سيتم إستدعاء هذه الدالة لحفظ أكبر مجموع وصل إليه اللاعب
                    writeBestScoreInTheFile();
                }
            }
     
            // إذا لمس رأس الأفعى الطعام سيتم إخفاء الطعام و زيادة مجموع اللاعب
            if((fruitXPos[xPos] == boardX[0]) && fruitYPos[yPos] == boardY[0])
            {
                totalScore += scoreReverseCounter;
                scoreReverseCounter = 99;
                fruitEaten++;
                lengthOfSnake++;
            }
     
            // هنا في كل مرة سيتم ضمان أن لا يظهر الطعام فوق الأفعى
            for(int i=0; i<snake.size(); i++)
            {
                // في حال ظهر الطعام فوق جسد الأفعى سيتم خلق مكان عشوائي آخر لوضعها فيه
                if(snake.get(i).x == fruitXPos[xPos] && snake.get(i).y == fruitYPos[yPos]) {
                    xPos = random.nextInt(22);
                    yPos = random.nextInt(22);
                }
            }
     
            // في الأخير سيتم عرض الطعام بعيداً عن جسد الأفعى
            fruitImage.paintIcon(this, g, fruitXPos[xPos], fruitYPos[yPos]);
     
            // قمنا باستدعاء هذه الدالة للتخلص من أي مصادر لا حاجة لها في البرنامج و يمكنك إزالتها لأنها لن تؤثر هنا
            g.dispose();
        }
     
     
        // لتحديد الإتجاه الذي ستتحرك فيه النافذة keyPressed() للدالة Override هنا فعلنا
        @Override
        public void keyPressed(KeyEvent e) {
     
            // Space هنا قمنا بتحديد ما سيحدث إذا قام اللاعب بالنقر على زر المسافة الفارغة
            if(e.getKeyCode() == KeyEvent.VK_SPACE)
            {
     
                // سيتم إيقاف اللعبة بشكل مؤقت إذا كانت اللعبة شغالة
                if(speedTimer.isRunning() && isGameOver == false)
                    speedTimer.stop();
     
                // سيتم إعادة اللعبة للعمل إذا كان قد تم إيقافها سابقاً
                else if(!speedTimer.isRunning() && isGameOver == false)
                    speedTimer.start();
     
                // سيتم بدأ اللعبة من جديد في حال كان قد تم إيقاف اللعبة لأن اللاعب قد خسر
                else if(!speedTimer.isRunning() && isGameOver == true)
                {
                    isGameOver = false;
                    speedTimer.start();
                    moves = 0;
                    totalScore = 0;
                    fruitEaten = 0;
                    lengthOfSnake = 3;
                    right = true;
                    left = false;
                    xPos = random.nextInt(22);
                    yPos = 5+random.nextInt(17);
                }
            }
     
            // هنا قمنا بتحديد ما سيحدث إذا قام اللاعب بالنقر على زر السهم الأيمن
            else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
            {
                // إذا لم تكن الأفعى تسير في الإتجاه الأيسر سيتم توجيهها نحو الإتجاه الأيمن
                moves++;
                right = true;
     
                if(!left)
                    right = true;
     
                else
                {
                    right = false;
                    left = true;
                }
     
                up = false;
                down = false;
            }
     
            // هنا قمنا بتحديد ما سيحدث إذا قام اللاعب بالنقر على زر السهم الأيسر
            else if(e.getKeyCode() == KeyEvent.VK_LEFT)
            {
                // إذا لم تكن الأفعى تسير في الإتجاه الأيمن سيتم توجيهها نحو الإتجاه الأيسر
                moves++;
                left = true;
     
                if(!right)
                    left = true;
     
                else
                {
                    left = false;
                    right = true;
                }
     
                up = false;
                down = false;
            }
     
            // هنا قمنا بتحديد ما سيحدث إذا قام اللاعب بالنقر على زر السهم المتجه للأعلى
            else if(e.getKeyCode() == KeyEvent.VK_UP)
            {
                // إذا لم تكن الأفعى تسير في اتجاه الأسفل سيتم توجيهها نحو الأعلى
                moves++;
                up = true;
     
                if(!down)
                    up = true;
     
                else
                {
                    up = false;
                    down = true;
                }
     
                left = false;
                right = false;
            }
     
            // هنا قمنا بتحديد ما سيحدث إذا قام اللاعب بالنقر على زر السهم المتجه للأسفل
            else if(e.getKeyCode() == KeyEvent.VK_DOWN)
            {
                // إذا لم تكن الأفعى تسير في اتجاه الأعلى سيتم توجيهها نحو الأسفل
                moves++;
                down = true;
     
                if(!up)
                    down = true;
     
                else
                {
                    up = true;
                    down = false;
                }
     
                left = false;
                right = false;
            }
        }
     
     
        // هنا قمنا بتحديد المكان الذي ستظهر فيه الأفعى لحظة تحركها
        // و لاحظ أنه يوجد شرط متعلق بكل إتجاه تسلكه الأفعى حالياً
        // هذه الشروط الموضوعة تجعل الأفعى تظهر في الجهة المقابلة لها عندما تلمس الحائط
        @Override
        public void actionPerformed(ActionEvent e) {
     
            if(right)
            {
                for(int i = lengthOfSnake-1; i>=0; i--)
                    boardY[i+1] = boardY[i];
     
                for(int i = lengthOfSnake; i>=0; i--)
                {
                    if(i==0)
                        boardX[i] = boardX[i] + 20;
     
                    else
                        boardX[i] = boardX[i-1];
     
                    if(boardX[i] > 460)
                        boardX[i] = 20;
                }
            }
     
            else if(left)
            {
                for(int i = lengthOfSnake-1; i>=0; i--)
                    boardY[i+1] = boardY[i];
     
                for(int i = lengthOfSnake; i>=0; i--)
                {
                    if(i==0)
                        boardX[i] = boardX[i] - 20;
     
                    else
                        boardX[i] = boardX[i-1];
     
                    if(boardX[i] < 20)
                        boardX[i] = 460;
                }
            }
     
            else if(up)
            {
                for(int i = lengthOfSnake-1; i>=0; i--)
                    boardX[i+1] = boardX[i];
     
                for(int i = lengthOfSnake; i>=0; i--)
                {
                    if(i==0)
                        boardY[i] = boardY[i] - 20;
     
                    else
                        boardY[i] = boardY[i-1];
     
                    if(boardY[i] < 20)
                        boardY[i] = 460;
                }
            }
     
            else if(down)
            {
                for(int i = lengthOfSnake-1; i>=0; i--)
                    boardX[i+1] = boardX[i];
     
                for(int i = lengthOfSnake; i>=0; i--)
                {
                    if(i==0)
                        boardY[i] = boardY[i] + 20;
     
                    else
                        boardY[i] = boardY[i-1];
     
                    if(boardY[i] > 460)
                        boardY[i] = 20;
                }
            }
     
            repaint();
        }
     
     
        @Override
        public void keyReleased(KeyEvent e) {
     
        }
     
     
        @Override
        public void keyTyped(KeyEvent e) {
     
        }
     
     
        // هذه الدالة تحفظ أعلى مجموع وصل إليه اللاعب في ملف خارجي بجانب ملف اللعبة
        private void writeBestScoreInTheFile()
        {
            if(totalScore >= bestScore)
            {
                try {
                    FileOutputStream fos = new FileOutputStream("./snake-game-best-score.txt");
                    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
                    osw.write(bestScore+"");
                    osw.flush();
                    osw.close();
                }
                catch(IOException e) {
                }
            }
        }
     
     
        // هذه الدالة تقرأ أعلى مجموع وصل إليه اللاعب من الملف الخارجي الموجود بجانب ملف اللعبة
        // في حال كان لا يوجد ملف خارجي ستقوم بإنشائه و وضع القيمة 0 فيه كقيمة أولية و هذا ما سيحدث عندما يقوم اللاعب بتشغيل اللعبة أول مرة
        private int readBestScorefromTheFile()
        {
            try {
                InputStreamReader isr = new InputStreamReader( new FileInputStream("./snake-game-best-score.txt"), "UTF-8" );
                BufferedReader br = new BufferedReader(isr);
     
                String str = "";
                int c;
                while( (c = br.read()) != -1){
                    if(Character.isDigit(c))
                        str += (char)c;
                }
                if(str.equals(""))
                    str = "0";
     
                br.close();
                return Integer.parseInt(str);
            }
            catch(IOException e) {
            }
            return 0;
        }
     
    }
    		

    Main.java
    //  snake_2d  موجود بداخل المجلد  Main.java   هنا ذكرنا أن الملف
    package snake_2d;
    
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
     
    // و بالتالي أصبح إنشاء كائن منه يمثل إنشاء نافذة JFrame يرث من الكلاس Main هنا جعلنا الكلاس
    public class Main extends JFrame {
     
        // فقط createAndShowGUI() سيقوم الكونستركتور بإستدعاء الدالة Main عند إنشاء كائن من الكلاس
        public Main() {
            createAndShowGUI();
        }
     
        // هنا نضع كود إنشاء النافذة و محتوياتها
        private void createAndShowGUI() {
     
            // هنا قمنا بإنشاء كائن من الحاوية التي تحتوي على اللعبة
            GameDrawer gameDrawer = new GameDrawer();
     
            // هنا وضعنا الحاوية التي تحتوي على اللعبة في النافذة حتى تظهر بداخلها
            add(gameDrawer);
     
            // هنا قمنا بتحديد بعض خصائص النافذة و جعلناها مرئية
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setResizable(false);
            pack();
            setLocationRelativeTo(null);
            setVisible(true);
     
        }
     
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    // التي ستنشئ النافذة createAndShowGUI() و بالتالي سيتم إستدعاء الدالة Main هنا قمنا بإنشاء كائن من الكلاس
                    new Main();
                }
            });
        }
     
    }
    		
    إعلان

    Eqla3Tech.com

    شروحات مكتوبة حول لغات البرمجة و تقنية المعلومات باللغة العربية مقدمة من إقلاع تك.

    لغة جافا لغة ++C قواعد البيانات نظام ويندوز نظام لينكس الشبكات تقنية المعلومات الأمن السيبراني

    الدورات

    أدوات مساعدة

    الأقسام

    دورات
    مقالات أسئلة مشاريع كتب