مرحبا بالجميع! 
نشرنا منذ بضعة أيام 
منشورًا عن الألغاز التي تم تقديمها في مؤتمر الجوكر 2018 ، ولكن هذا ليس كل شيء! في هذا العام ، خاصة بالنسبة إلى Joker ، صنعنا لعبة كاملة لا تتضمن مهام Java أقل إثارة للاهتمام (وليس فقط) ، والتي سنتحدث عنها اليوم.
لقد صنعنا ألعابًا مماثلة في المؤتمرات من قبل ، على سبيل المثال ، في JPoint الأخير هذا الربيع. لصنع لعبة ، كان علينا: 1) ابتكار آليات اللعبة ، 2) طرح الأسئلة ، 3) إدراك كل هذا.
يجب أن تكون ميكانيكا اللعبة بسيطة للغاية وبديهية ، ولكن في نفس الوقت ليست عادية للغاية ، حتى لا تحرم من الإثارة. نتيجة للمناقشات الطويلة ، توصلنا إلى اللعبة التالية:
عند الإجابة على الأسئلة ، يجب أن نحاول قيادة الدوق (في الزاوية اليسرى العليا) إلى أحد الأبواب في الزوايا الأخرى. لجلسة واحدة من اللعبة يتم تخصيص 3 دقائق. لفتح الخلية ، تحتاج إلى الإجابة على السؤال بشكل صحيح ، والذي يتم تحديده في كل مرة بشكل عشوائي وفقًا للفئة. يتم منح النقاط للإجابات الصحيحة ، وعقوبة للإجابات غير الصحيحة ، ويتم حظر الخلية مع السؤال ويجب تجاوزها. ونتيجة لذلك ، قد يتبين أن المسار طويل جدًا أو قد يتم حظره. يمكن للاعبين اختيار استراتيجيات مختلفة: الوصول إلى الخروج في أقرب وقت ممكن والحصول على مكافأة إضافية ؛ الإجابة على أكبر عدد ممكن من الأسئلة في الوقت المخصص ؛ قطع شوطًا طويلاً على الأسئلة البسيطة ، أو مباشرةً على الأسئلة الأكثر تعقيدًا والحصول على المزيد من النقاط.

تعاملنا مع الميكانيكا ، والآن نحتاج إلى طرح الأسئلة. يجب أن تكون من ثلاث فئات من التعقيد ، من أبسط إلى المتشددين. يجب أن تكون صياغة الأسئلة قصيرة للغاية ، ولن يكون هناك وقت لقراءة أوراق النص. يجب أن تكون خيارات الإجابة مثل عدم إعطاء الكثير من القرائن. حسنًا ، يجب أن تكون الأسئلة نفسها مثيرة للاهتمام وعملية. علاوة على ذلك ، كان يجب أن يكون هناك الكثير منهم حتى لا يتكرروا بسرعة كبيرة. نتيجة للجهود المشتركة ، تمكنا من طرح 130 سؤالًا حول هياكل البيانات ، والخوارزميات ، و "لغز جافا" ، والأسئلة المتشددة حول JVM الداخلية ، وحتى بعض الأسئلة حول Docker.

هناك مشكلة: يتم عرض اللعبة على الشاشة الكبيرة ، وسيتذكر أولئك الذين يقفون بالقرب منك معظم الإجابات لعدة ألعاب. في البداية ، يبدو أننا سنحتاج إلى مئات الأسئلة لتقليل إمكانية الحفظ. ولكن عند التفكير ، أدركوا أن هناك خيارات أبسط. للبدء ، أزل عنصر تحكم الماوس ، مع ترك لوحة المفاتيح فقط. الآن أولئك الذين يقفون بالقرب يرون السؤال ، لكن لا يرون الإجابة التي اختارها اللاعب. تمت إضافة مزيج من خيارات الإجابة ، مما يعقد الحفظ. لكل سؤال ، تمت إضافة عدة صيغ متشابهة ولكن مختلفة قليلاً. بالطبع ، لا يزال بإمكانك تذكر الإجابات ، وكان هذا واضحًا من النتائج المحسنة بشكل ملحوظ في اليوم الثاني من المؤتمر. قضى العديد من المستخدمين عشرات الدقائق يلعبون اللعبة ، محاولين كسر الرقم القياسي للآخرين. ولكن هنا كل شيء كما هو الحال في الحياة - يكافأ الحماس.
مرت أسبوعين من الفكرة إلى تحقيق الأسئلة والتنفيذ. بالطبع ، كل شيء في جافا. يستخدم التمهيد الربيع و Gradle. يرصد WEB- واجهة على الزاوي. كمخزن ، يتم استخدام قاعدة بيانات H2 المدمجة ، والتي تأتي من خارج الصندوق مع واجهة ويب ، وهي مريحة للغاية. تكوين الحامل هو جهازين MacBooks ، الصورة مكررة منها على جهازين تلفزيون. لسهولة الإعداد ، تم نشر التطبيق عن بعد على السحابة ( 
https://habr.com/company/odnoklassniki/blog/346868/ ).
تعلمنا منذ وقت طويل: لا ينبغي تطوير أي ميزة دون جمع الإحصاءات. بالطبع ، قمنا أيضًا بإرفاق إحصائيات مفصلة للعبة ، والتي يمكننا مشاركتها.
في المجموع ، لعبت اللعبة 811 مرة في يومين. إحصائيات الإجابات حسب درجة تعقيد السؤال:
| الصعوبة 
 | COUNT 
 | CORRECT_PERCENT 
 | 
| 1 
 | 3552 
 | 61 
 | 
| 2 
 | 2031 
 | 49 
 | 
| 3 
 | 912 
 | 46 
 | 
ما هي خلايا الميدان وعدد المرات التي وصل فيها اللاعبون:
النسبة المئوية للإجابات الصحيحة في كل خلية من الحقول:
لكن الأكثر إثارة للاهتمام هو بالطبع إحصائيات الأسئلة. لم يكن من السهل تقييم مدى تعقيدها مع مراعاة التوزيع حسب الفئة ، والتقييم دائمًا غير موضوعي ، والسؤال البسيط لمستخدم صعب على مستخدم آخر. اقترح 
أوليغ التخلص من أحد الأسئلة بعبارة "حتى عمال النظافة يعرفون ذلك" ، ولكن اتضح أن العديد من عمال النظافة لا يعرفون الإجابات الصحيحة على العديد من الأسئلة "البسيطة" ، والمبرمجين أيضًا. نقدم لك بعض الأسئلة من لعبتنا - القادة على إجابات غير صحيحة ، حاول تقييم قوتك!
- نتيجة استدعاء هذا الرمز؟
 
 System.out.println(1/0d)
 
 - يلقي استثناء حسابي
- يطبع اللانهاية
- طباعة "NaN"
- ستطبع 0
 
 الجوابيبدو أن هذا سؤال بسيط للغاية. هنا حساب بسيط ، ما يمكن أن يكون الصيد ، لماذا قدم 28 ٪ فقط من اللاعبين الإجابة الصحيحة؟ قسمة عدد صحيح على 0 في Java ينتج ArithmeticException. ولكن هل هناك أعداد صحيحة هنا؟ سننظر بعناية. ما هذا "د" بعد 0؟ تعني هذه الرسالة أن هذا ليس عددًا صحيحًا ثابتًا 0 ، ولكنه قيمة من النوعdouble. وتبين أن التعبير مطابق لـ 1.0 / 0.0. وهذا قسمة على نقطة عائمة على صفر ، ونتيجة ذلك هيDouble.POSITIVE_INFINITY. لذا فإن الإجابة الصحيحة هي "ب".
 
 
 
- نتيجة استدعاء هذا الرمز؟
 
  System.out.println( Long.MAX_VALUE==(long)Float.MAX_VALUE );
 
 - طباعة صحيح
- ستطبع خطأ
- يلقي استثناء حسابي
 
 الجوابأولاً ، تحتاج إلى فهم ما هو أكثر: Float.MAX_VALUEأوLong.MAX_VALUE؟ على الرغم من أنfloatله نطاق قيم أقل منdouble، إلا أن قيمته القصوى تقارب 20 أمرًا من الحجم يتجاوز نطاق القيمlongالمحتملة. ولكن كيف يعمل نوع الصب في هذه الحالة؟ يمكن للمرء أن يخمن ، ولكن من الأفضل تشغيل التعليمات البرمجية. والأفضل من ذلك ، افتح مواصفات لغة جافا ، قسم حول تضييق التحويل البدائي ، واقرأ أنه إذا كانت قيمة رقم الفاصلة العائمة كبيرة جدًا وتقع خارج نطاق القيم المتاحة لنوع صحيح ، فإن نتيجة التحويل تساوي الحد الأقصى للقيمة التي يمكن تمثيلها باستخدام نوع صحيح . على سبيل المثال نتيجة التحويل هيLong.MAX_VALUE. الجواب الصحيح قدمه 27٪ من المجيبين.
 
 
- أي فئة غير قابلة Comparable؟
 
 - java.lang.String
- java.util.TreeSet
- java.io.File
- java.lang.Enum
 
 الجوابهذا السؤال الذي يبدو بسيطًا حير الكثير أو بالأحرى 76٪ ممن أجابوا. خمن لنفسك أي من الإجابات هنا صحيحة وأيها كانت الإجابة الأكثر شيوعًا - اختارها 61٪ من اللاعبين.
 
 
 
- ما هو الرمز المطابق؟
 
  Object o = Math.min(-1, Double.MIN_VALUE)
 
 - الكائن س = -1
- الكائن o = Double.MIN_VALUE
- الكائن س = -1.0
 
 الجوابالقيمة doubleالدنيا هي بالتأكيد أقل من -1 ، فماذا يمكن أن يكون خطأ مرة أخرى؟ بالطبع ، كل شيء ليس بهذه البساطة ، وإلا فإننا لن نسأل. اتضح أنDouble.MIN_VALUEلا يحتوي بالضبط على ما هو متوقع ، أي "الاحتفاظ المستمرDouble.MIN_VALUEقيمة موجبة غير صفرية" ، وفقًا للوثائق. سيكونDouble.MIN_POSITIVE_VALUEالأصح أن نسميهاDouble.MIN_POSITIVE_VALUE.Doubleمرة أخرى محاطة بإصبعه! الإجابة الصحيحة هي:Object o = -1.0، وبالتالي أجاب 22٪ فقط من اللاعبين.
 
 
 
- ما الخط الذي سينتج عن استدعاء هذا الرمز؟
 
  Long.toHexString(0x1_0000_0000L + 0xcafe_babe)
 
 - 1 كافيه
- مقهى
- ffffffffcafebabe
 
 الجوابإذا اخترت الإجابة الثانية ، فأنت من بين 22٪ ممن أجابوا بشكل صحيح. هذا السؤال مأخوذ من كتاب Java Puzzlers: Traps و Pitfalls و Corner Cases الذي كتبه Joshua Bloch و Neal Gafter. إذا أجبت بشكل غير صحيح ، فلا تثبط عزيمتك ، وركض لقراءة هذا الكتاب!
 
 
 
- يقدم JDK 8 دعم التعليقات التوضيحية على معلمات الطريقة. هل من الممكن إضافة تعليق توضيحي إلى معلمة thisالطريقة؟
 
 - هذا مستحيل
- ربما ، ولكن فقط في البايت كود
- ربما عن طريق تحديد thisصراحة باعتباره المعلمة الأولى للطريقة
 
 الجوابعندما تمت إضافة القدرة على وضع التعليقات التوضيحية على معلمات الطريقة في JDK 8 ، لم يتم حرمان  this المعلمة. لهذا الغرض ، يمكن الآن تحديد ذلك صراحة في توقيعات الطريقة:  class Foo { public void test(@Annotated Foo this) {} }
 على الرغم من أنه يمكنك الجدل حول فوائدها العملية ، إلا أنها الآن سمة من سمات اللغة. 32٪ من اللاعبين توقعوا الإجابة الصحيحة. 
 
- في JDK 8 ، تؤثر المعلمة concurrencyLevelفي مُنشئConcurrentHashMapعلى:
 
 - قراءة / كتابة التزامن المتاحة
- حجم الجدول الأولي
- على كلا المعلمتين
 
 الجوابإذا اخترت الخيار 2 ، فأنت من بين 15 ٪ ممن أعطوا الإجابة الصحيحة على هذا السؤال الأكثر صعوبة في اللعبة. الشيء هو أنه في JDK 8 تخلىوا عن الأجزاء في ConcurrentHashMap، لذا فقد مستوىconcurrencyLevelالمعنى السابق. إنه يؤثر فقط على الحجم الأولي للجدول ، وحتى ذلك يحد فقط من القيمةinitialCapacityمن الأسفل.