• בלוג
  • פיתוח משחק צוללות ב React, TypeScript ו MobX. חלק 2.

פיתוח משחק צוללות ב React, TypeScript ו MobX. חלק 2.

29/02/2020

בחלק הקודם של המדריך פיתחנו את הלוגיקה של משחק הצוללות. היום נוסיף את הפונקציה repr וגם מספר בדיקות אוטומטיות כדי לוודא שהקוד שלנו לא נשבר.

1. הפונקציה repr

בסוף הפוסט אתמול הצעתי לכם לכתוב את הפונקציה BoardSquare.repr שמחזירה מה יש במשבצת. זה תרגיל נחמד בפיתוח מונחה עצמים כי במשבצת יכולים להיות כמה סוגים של דברים, וכל דבר יכול להציג את עצמו בצורה קצת אחרת.

במקום לשים את כל הלוגיקה במקום אחד אני מוסיף פונקציה בשם repr לכל אחד מהפריטים שיכולים להיות במשבצת. כך הצוללת:

abstract class Submarine extends Sea {
    // ...

    repr() {
        if (this.sank) {
            return "X";
        } else {
            return "/";
        }
    }
}

הים:

class Sea {
    // ...

    repr() {
        return "0";
    }
}

וכמובן המשבצת עצמה:

class BoardSquare {
    // ... 
    repr() {
        if (this.revealed) {
            return this.item.repr();
        } else {
            return " ";
        }
    }
}

המשבצת אחראית לזהות האם היא כבר נחשפה, אבל אם כן כל פריט אחראי לצייר את התוכן שלו עצמו. בצורה כזאת הקוד שלנו יתמודד יפה גם עם שינויים עתידיים, למשל אם נוסיף למשחק גם דולפינים או יצורים אחרים.

2. כתיבת בדיקות יחידה

בפרויקט שיצרנו עם create-react-app אנחנו מקבלים במתנה את התשתית לכתיבה והרצה של בדיקות יחידה. הוסיפו בתוך התיקיה lib וליד הקובץ submarines.tsx את הקובץ submarines.test.tsx ובו התוכן הבא:

import { Board, VerticalSubmarine, HorizontalSubmarine } from "./submarines";

test('can hit the sea', () => {
    const b = new Board(10, 10);
    b.bomb([0, 0]);
    expect(b.cellAt([0, 0])?.revealed).toBe(true);
    expect(b.repr()[0]).toBe('0');
});

test('can hit a submarine', () => {
    const b = new Board(10, 10);
    const s = new HorizontalSubmarine(4);
    b.addSubmarine(s, 0, 0);
    b.bomb([0, 0]);
    expect(b.cellAt([0, 0])?.revealed).toBe(true);
    expect(b.repr()[0]).toBe('/');
});

test('can sunk a submarine', () => {
    const b = new Board(10, 10);
    const s = new HorizontalSubmarine(4);
    b.addSubmarine(s, 0, 0);
    b.bomb([0, 0]);
    b.bomb([0, 1]);
    b.bomb([0, 2]);
    b.bomb([0, 3]);
    expect(b.cellAt([0, 0])?.revealed).toBe(true);
    expect((b.cellAt([0, 0])?.item as HorizontalSubmarine).sank).toBe(true);
    expect(b.repr()[0]).toBe('X');
    expect(b.repr()[1]).toBe('X');
});

הפקודה test אחראית על הרצת תסריט בדיקה. פקודה זו משתמשת בפקודה נוספת בשם expect כדי לזהות שדברים מסוימים עובדים כמו שרצינו (או לא). לדוגמא בבדיקה הראשונה אנחנו יוצרים לוח, מפציצים את המשבצת השמאלית עליונה ומקווים שהיא אכן מזהה שהיא הופצצה.

המבנה של expect ואז toBe נראה מבלבל בהתחלה אבל אחרי שתתרגלו תראו שדווקא מאוד קל לקרוא אותו.

אחרי שתסיימו לכתוב את הבדיקות תוכלו להריץ אותן עם:

$ yarn test

מתוך שורת הפקודה.

וכשתסיימו הפרויקט כנראה יראה דומה לגיטהאב שלי בקישור: https://github.com/ynonp/mobx-submarines-demo/tree/bb7ba1e67cf8daaab35c5e6ecfd0337a1c5ab970.

3. תרגילים להרחבה

סיימתם לכתוב את הבדיקות והכל עובד? נשאר לכם עוד קצת זמן? הנה כמה רעיונות להרחבה:

  1. מה קורה אם ניסיתי לשים צוללת מחוץ ללוח? מה קורה אם הצוללת שלי קיבלה גודל שלילי? ומה אם אני מפציץ את אותה משבצת שוב ושוב? כתבו בדיקות לכל מקרי הקצה שאתם יכולים לדמיין ותקנו את הקוד כך שיתאים לציפיות שלכם.

  2. תשתית הבדיקות ש create-react-app יצר בשבילנו נקראת jest. לכו לקרוא קצת על הפקודה expect בתיעוד של jest כדי לקבל רעיונות לדברים נוספים שתוכלו לבדוק. קישור לתיעוד: https://jestjs.io/docs/en/expect.