]> git.cworth.org Git - lmno.games/commitdiff
Add a shuffle button for arranging all tiles in the play area
authorCarl Worth <cworth@cworth.org>
Sun, 8 Mar 2026 13:47:43 +0000 (09:47 -0400)
committerCarl Worth <cworth@cworth.org>
Sun, 8 Mar 2026 13:47:43 +0000 (09:47 -0400)
If the user wants to move them around, they can. But for cleaning up,
(or changing the order randomly), the player can click this shuffle
button.

anagrams/anagrams.css
anagrams/anagrams.jsx

index a9e2c2c7cbe9885e778bf4f59182f6d944fb311d..2c7304f3dd94543a7906046c2d80fb57f85c2d94 100644 (file)
   border-radius: 8px;
   margin-bottom: 1em;
   padding: 1em;
-  overflow: hidden;
+}
+
+.center-pool .shuffle-btn {
+  position: absolute;
+  top: -8px;
+  left: -8px;
+  z-index: 20;
+  cursor: pointer;
+  color: var(--accent-color);
+  opacity: 0.5;
+}
+
+.center-pool .shuffle-btn:hover {
+  opacity: 1;
 }
 
 .center-pool .tile {
index 58dc96488620106e82bd7b6c48fad433c83c7262..67091051f258f9ccdbe9c674013f1155393b637d 100644 (file)
@@ -534,6 +534,37 @@ class Game extends React.Component {
     return best || { x: 5 + Math.random() * 80, y: 5 + Math.random() * 75 };
   }
 
+  shuffle_tiles() {
+    const pool = document.querySelector(".center-pool");
+    if (!pool) return;
+
+    const rect = pool.getBoundingClientRect();
+    const tile_size = 48; /* tile width + gap */
+    const pad = 16;       /* padding in px */
+    const usable_w = rect.width - 2 * pad;
+    const usable_h = rect.height - 2 * pad;
+    const cols = Math.max(1, Math.floor(usable_w / tile_size));
+
+    /* Shuffle the tile IDs. */
+    const ids = this.state.center.map(t => t.id);
+    for (let i = ids.length - 1; i > 0; i--) {
+      const j = Math.floor(Math.random() * (i + 1));
+      [ids[i], ids[j]] = [ids[j], ids[i]];
+    }
+
+    const positions = { ...this.state.tile_positions };
+    ids.forEach((id, i) => {
+      const col = i % cols;
+      const row = Math.floor(i / cols);
+      positions[id] = {
+        x: (pad + col * tile_size) / rect.width * 100,
+        y: (pad + row * tile_size) / rect.height * 100
+      };
+    });
+
+    this.setState({ tile_positions: positions });
+  }
+
   /*****************************************************
    * Keyboard input during claiming                    *
    *****************************************************/
@@ -840,6 +871,28 @@ class Game extends React.Component {
            onTouchMove={(e) => this.on_center_touch_move(e)}
            onTouchEnd={(e) => this.on_center_touch_end(e)}
            onTouchCancel={(e) => this.on_center_touch_end(e)}>
+        {center.length > 0 ? (
+          <svg className="shuffle-btn"
+               onClick={() => this.shuffle_tiles()}
+               viewBox="0 0 24 24" width="24" height="24">
+            <title>Shuffle tiles</title>
+            <defs>
+              <marker id="arr" viewBox="0 0 6 6" refX="3" refY="3"
+                      markerWidth="4" markerHeight="4" orient="auto-start-reverse">
+                <path d="M0,0 L6,3 L0,6 Z" fill="currentColor"/>
+              </marker>
+            </defs>
+            <polyline points="2,7 8,7 16,17 22,17"
+                      fill="none" stroke="currentColor" strokeWidth="2"
+                      strokeLinecap="round" strokeLinejoin="round"
+                      markerEnd="url(#arr)"/>
+            <line x1="8.5" y1="16" x2="2" y2="16" fill="none"
+                  stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
+            <line x1="15.5" y1="8" x2="22" y2="8" fill="none"
+                  stroke="currentColor" strokeWidth="2" strokeLinecap="round"
+                  markerEnd="url(#arr)"/>
+          </svg>
+        ) : null}
         {center.length === 0 ? (
           <div className="status">
             No letters yet. Press the bag to request one.