Analyse des Spiels von Classmates bei Joker 2018


    Hallo allerseits! Vor ein paar Tagen haben wir einen Beitrag über die Rätsel veröffentlicht, die auf der Joker 2018-Konferenz gestellt wurden. Aber das ist noch nicht alles! In diesem Jahr haben wir speziell für Joker ein ganzes Spiel mit nicht weniger interessanten Java-Aufgaben (und nicht nur) gemacht, über die wir heute sprechen werden.

    Wir haben ähnliche Spiele früher auf Konferenzen gemacht, zum Beispiel zuletzt im Frühjahr dieses Jahres. Um ein Spiel zu machen, mussten wir: 1) Spielmechanismen entwickeln, 2) Fragen entwickeln, 3) all dies realisieren.

    Die Spielmechanik sollte sehr einfach, intuitiv und gleichzeitig nicht zu banal sein, um der Aufregung nicht zu berauben. Nach langen Diskussionen haben wir folgendes Spiel entwickelt:


    Bei der Beantwortung von Fragen müssen wir versuchen, Duke (in der oberen linken Ecke) in eine der Türen in anderen Ecken zu führen. Für eine Sitzung des Spiels sind 3 Minuten vorgesehen. Um die Zelle zu öffnen, müssen Sie die Frage richtig beantworten, die jedes Mal nach dem Zufallsprinzip entsprechend der Kategorie ausgewählt wird. Punkte werden für korrekte Antworten vergeben, eine Strafe für falsche Antworten, die Zelle mit der Frage wird blockiert und muss umgangen werden. Infolgedessen kann der Pfad ziemlich lang oder vollständig blockiert sein. Die Spieler können verschiedene Strategien wählen: Sie müssen so schnell wie möglich zum Ausgang gehen und erhalten einen zusätzlichen Bonus. Beantworten Sie so viele Fragen wie möglich in der vorgegebenen Zeit. Gehen Sie bei einfachen Fragen einen weiten Weg oder direkt bei komplexeren Fragen und holen Sie sich mehr Punkte.


    Wir haben uns mit der Mechanik befasst, jetzt müssen wir uns Fragen stellen. Sie sollten aus drei Kategorien von Komplexität bestehen, von der einfachsten bis zur Hardcore. Der Wortlaut der Fragen sollte extrem kurz sein, es bleibt keine Zeit, die Blätter des Textes zu lesen. Die Antwort sollte so gewählt werden, dass nicht zu viele Hinweise gegeben werden. Nun, die Fragen selbst sollten interessant und praktisch sein. Außerdem hätte es genug davon geben sollen, damit sie sich nicht zu schnell wiederholten. In gemeinsamer Arbeit konnten wir 130 Fragen zu Datenstrukturen, Algorithmen, "Java Puzzle", Kernfragen zu den JVM-Interna und sogar einige Fragen zu Docker stellen.


    Es gibt ein Problem: Das Spiel wird auf dem großen Bildschirm angezeigt, und diejenigen, die in der Nähe stehen, werden sich die meisten Antworten für mehrere Spiele merken. Zuerst schien es, als würden wir Hunderte von Fragen benötigen, um das Auswendiglernen auf ein Minimum zu beschränken. Aber nach Überlegungen erkannten sie, dass es einfachere Möglichkeiten gibt. Zunächst wurde die Maussteuerung entfernt und nur die Tastatur belassen. Jetzt sehen diejenigen, die in der Nähe stehen, die Frage, aber sie sehen nicht, welche Antwort der Spieler gewählt hat. Das Mischen von Antwortoptionen wurde hinzugefügt, was das Auswendiglernen erschwert. Zu jeder Frage wurden mehrere ähnliche, aber leicht unterschiedliche Formulierungen hinzugefügt. Natürlich können Sie sich noch an die Antworten erinnern, was sich in den deutlich verbesserten Ergebnissen am zweiten Konferenztag niederschlug. Viele Benutzer haben zig Minuten damit verbracht, das Spiel zu spielen und zu versuchen, den Rekord anderer zu brechen. Aber hier ist alles wie im Leben - Eifer wird belohnt.

    Zwei Wochen vergingen von der Entstehung der Idee bis zur Beantwortung von Fragen und deren Umsetzung. Natürlich ist alles in Java. Gebrauchte Spring Boot und Gradle. Die WEB-Schnittstelle ist auf Angular eingestellt. Als Speicher wird die integrierte H2-Datenbank verwendet, die standardmäßig mit einer sehr praktischen Weboberfläche ausgestattet ist. Die Standkonfiguration besteht aus zwei MacBooks, deren Bild auf zwei Fernsehgeräten dupliziert wird. Zur Vereinfachung der Einrichtung wurde die Anwendung remote in unserer Cloud bereitgestellt ( https://habr.com/company/odnoklassniki/blog/346868/ ).


    Wir haben vor langer Zeit gelernt: Ohne Statistiksammlung sollte kein Feature entwickelt werden. Natürlich haben wir dem Spiel auch detaillierte Statistiken beigefügt, die wir teilen können.

    Insgesamt wurde das Spiel in zwei Tagen 811 Mal gespielt. Statistik der Antworten abhängig von der Komplexität der Frage:

    SCHWIERIGKEIT
    COUNT
    CORRECT_PERCENT
    1
    3552
    61
    2
    2031
    49
    3
    912
    46

    Zu welchen Feldzellen und wie oft erreichten die Spieler:


    Prozentsatz der richtigen Antworten in jeder Zelle des Feldes:


    Am interessantesten ist natürlich die Statistik der Fragen. Es war nicht so einfach, ihre Komplexität unter Berücksichtigung der Verteilung nach Kategorien zu bewerten, die Bewertung ist immer subjektiv und eine einfache Frage für einen Benutzer ist für einen anderen Benutzer schwierig. Oleg schlug vor, eine der Fragen mit den Worten „auch die Putzfrauen wissen es“ wegzuwerfen, aber es stellte sich heraus, dass nicht viele Putzfrauen die richtigen Antworten auf viele „einfache“ Fragen kennen, und auch Programmierer. Wir bieten Ihnen einige Fragen unserer Spielleiter zu falschen Antworten, versuchen Sie, Ihre Stärke zu bewerten!

    1. Das Ergebnis des Aufrufs dieses Codes?

      System.out.println(1/0d)

      • Löst eine ArithmeticException aus
      • Druckt Unendlichkeit
      • Druckt "NaN"
      • Gibt 0 aus

      Die antwort
      Dies scheint eine sehr einfache Frage zu sein. Hier ist einfache Arithmetik, was könnte der Haken sein, warum gaben nur 28% der Spieler die richtige Antwort? Das Teilen einer Ganzzahl durch 0 in Java führt zu ArithmeticException. Aber gibt es hier ganze Zahlen? Wir werden genau hinschauen. Was ist das "d" nach 0? Dieser Buchstabe bedeutet, dass dies keine ganzzahlige Konstante 0 ist, sondern ein Typwert double. Und es stellt sich heraus, dass der Ausdruck mit 1.0 / 0.0 identisch ist. Und dies ist eine Division mit einem Gleitkommawert von Null, dessen Ergebnis gleich ist Double.POSITIVE_INFINITY. Die richtige Antwort lautet also "b".
    2. Das Ergebnis des Aufrufs dieses Codes?

      System.out.println(
          Long.MAX_VALUE==(long)Float.MAX_VALUE
      );
      

      • print true
      • druckt falsch
      • Löst eine ArithmeticException aus

      Die antwort
      Zunächst müssen Sie verstehen, was mehr ist: Float.MAX_VALUEoder Long.MAX_VALUE? Obwohl es float einen kleineren Wertebereich als hat double, liegt sein Maximalwert ungefähr 20 Größenordnungen über dem Bereich möglicher Werte long. Aber wie funktioniert das Typgießen in diesem Fall? Man kann raten, aber es ist besser, den Code auszuführen. Öffnen Sie noch besser die Java-Sprachspezifikation, einen Abschnitt zur Eingrenzung der primitiven Konvertierung, und lesen Sie, dass, wenn der Wert einer Gleitkommazahl zu groß ist und außerhalb des Bereichs der verfügbaren Werte eines Integer-Typs liegt, das Konvertierungsergebnis dem Maximalwert entspricht, der mit einem Integer-Typ dargestellt werden kann . Das heißt Umrechnungsergebnis ist gleich Long.MAX_VALUE. Die richtige Antwort wurde von 27% der Befragten gegeben.
    3. Welche Klasse ist das nicht Comparable?

      • java.lang.String
      • java.util.TreeSet
      • java.io.File
      • java.lang.Enum

      Die antwort
      Diese scheinbar einfache Frage verblüffte viele oder vielmehr 76% der Befragten. Erraten Sie selbst, welche der Antworten hier richtig ist und welche Antwort am beliebtesten war - sie wurde von 61% der Spieler gewählt.
    4. Womit ist der Code identisch?

      Object o = Math.min(-1, Double.MIN_VALUE)

      • Objekt o = -1
      • Objekt o = Double.MIN_VALUE
      • Objekt o = -1,0

      Die antwort
      Der Mindestwert doubleist sicherlich kleiner als -1, was könnte nochmal falsch sein? Natürlich ist nicht alles so einfach, sonst würden wir nicht fragen. Es stellt sich heraus, dass es Double.MIN_VALUEnicht ganz das enthält, was erwartet wird, nämlich „Konstante, die den kleinsten positiven Wert ungleich Null hält“, so die Dokumentation. Es wäre richtiger, es zu nennen Double.MIN_POSITIVE_VALUE. Doublewieder kreiste um den Finger! Richtige Antwort: Object o = -1.0Nur 22% der Spieler haben geantwortet.
    5. Welche Zeile ergibt sich aus dem Aufruf dieses Codes?

      Long.toHexString(0x1_0000_0000L + 0xcafe_babe)

      • 1cafebabe
      • Cafebabe
      • ffffffffcafebabe

      Die antwort
      Wenn Sie die zweite Antwort gewählt haben, sind Sie unter 22% derjenigen, die richtig geantwortet haben. Diese Frage stammt aus dem von Joshua Bloch und Neal Gafter verfassten Buch Java Puzzlers: Traps, Pitfalls und Corner Cases. Wenn Sie falsch geantwortet haben, lassen Sie sich nicht entmutigen und lesen Sie dieses Buch!
    6. JDK 8 bietet Unterstützung für Anmerkungen zu Methodenparametern. Ist es möglich, einem Methodenparameter eine Anmerkung hinzuzufügen this?

      • Es ist unmöglich
      • Vielleicht, aber nur im Bytecode
      • Möglicherweise durch thisexplizites Definieren des ersten Parameters der Methode

      Die antwort
      Als in JDK 8 die Möglichkeit zum Hinzufügen von Anmerkungen zu Methodenparametern hinzugefügt wurde, wurde der Parameter thisnicht entzogen. Zu diesem Zweck thiskönnen Sie jetzt in den Methodensignaturen explizit Folgendes angeben:

      class Foo {
          public void test(@Annotated Foo this) {}
      }

      Obwohl Sie über die praktischen Vorteile streiten können, ist es jetzt ein Merkmal der Sprache. 32% der Spieler haben die richtige Antwort erraten.
    7. In JDK 8 wirkt sich ein Parameter concurrencyLevelim Konstruktor auf ConcurrentHashMapFolgendes aus:

      • Parallelität von Lese- und Schreibzugriff verfügbar
      • Anfängliche Tabellengröße
      • Auf beiden Parametern

      Die antwort
      Wenn Sie Option 2 gewählt haben, sind Sie unter 15%, die die richtige Antwort auf diese schwierigste Frage des Spiels gegeben haben. Die Sache ist, dass das JDK 8 Segmente in aufgegeben hat ConcurrentHashMap, so dass es concurrencyLevelseine vorherige Bedeutung verloren hat. Es wirkt sich nur auf die Anfangsgröße der Tabelle aus, und auch das begrenzt nur den Wert von unten initialCapacity.

    Jetzt auch beliebt: