解决从两个数组随机生成图片时重复对比的问题
Fixing Self-Comparison Issue in 2AFC Experiment Image Pairs
I get it, dealing with those accidental self-comparisons in your 2AFC setup is frustrating—your current check tries to catch duplicates, but it doesn't actually guarantee a valid pair every time. Let's break down what's going wrong and fix it step by step.
What's Wrong with the Current Logic?
- When you hit a duplicate, you generate new random indices
random1andrandom2, but you don't re-check if those new indices still point to the same image. So you might still end up with a self-comparison. - You're modifying the original
rndandrnd_2variables after setting the image sources, but then you splice the original indices from the arrays, not the new ones you just generated. That leads to incorrect elements being removed from your image arrays. - There's an accidental double increment of the
countervariable inside the non-practice block, which will throw off your progress tracking. - You're using identical arrays (
myImagesandsecondImages) which is redundant and increases the chance of sync issues.
Fixed Solution
Let's rewrite the core logic to ensure we never get a self-comparison, plus fix counter tracking and array management. Here's the updated code with key improvements:
<!DOCTYPE html> <html> <head> <title> App Icons? </title> <link rel="stylesheet" type="text/css" href="css/mainstyle.css"> <script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-analytics.js"></script> <script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-database.js"></script> <script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script> <script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-storage.js"></script> </head> <body class=body onload="start2AFC()"> <div> <div> <hr> <div class=topbar> <h1> Which app icon is more beautiful?</h1> </div> <hr> <div class=imageContainer> <div class=image> <img onclick="store2AFC(this.id)" id="image" alt="Experimental Image" width="400px" height="200px"> </div> <div class=image> <img onclick="store2AFC(this.id)" type="image" id="image2" alt="Experiment Image" width="400px" height="200px"> </div> </div> </div> <hr> <div class=counter id=counter> </div> </div> <script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script> <script type="text/javascript"> function start2AFC() { var answers = {}; window.sessionStorage.setItem("answers", JSON.stringify(answers)) var testImages = [ ["images/images/practice/practice1.jpg","images/images/practice/practice2.jpg"], ["images/images/practice/practice2.jpg", "images/images/practice/practice4.jpg"] ]; // Use a single array instead of two identical ones var myImages = [ "images/images/icon1.jpg", "images/images/icon2.jpg", "images/images/icon3.jpg", "images/images/icon4.jpg", "images/images/icon5.jpg", "images/images/icon6.jpg", "images/images/icon7.jpg", "images/images/icon8.jpg", "images/images/icon9.jpg", "images/images/icon10.jpg", "images/images/icon11.jpg","images/images/icon12.jpg", "images/images/icon13.jpg", "images/images/icon14.jpg", "images/images/icon15.jpg", "images/images/icon16.jpg", "images/images/icon17.jpg", "images/images/icon18.jpg", "images/images/icon19.jpg", "images/images/icon20.jpg", "images/images/icon21.jpg", "images/images/icon22.jpg", "images/images/icon23.jpg","images/images/icon24.jpg", "images/images/icon25.jpg", "images/images/icon26.jpg", "images/images/icon27.jpg", "images/images/icon28.jpg", "images/images/icon29.jpg", "images/images/icon30.jpg", "images/images/icon31.jpg", "images/images/icon32.jpg", "images/images/icon33.jpg", "images/images/icon34.jpg", "images/images/icon35.jpg", "images/images/icon36.jpg", "images/images/icon37.jpg", "images/images/icon38.jpg", "images/images/icon39.jpg", "images/images/icon40.jpg" ]; window.sessionStorage.setItem("practiceImages", JSON.stringify(testImages)) window.sessionStorage.setItem("images", JSON.stringify(myImages)) var counter = 0; window.sessionStorage.setItem("counter", counter); const total = testImages.length + myImages.length / 2; // Each trial uses 2 images window.sessionStorage.setItem("total", total) document.getElementById("counter").innerHTML = "You are on trial " + (counter + 1) + " of " + total random2AFC(); } function random2AFC() { var practiceImages = JSON.parse(window.sessionStorage.getItem("practiceImages")); var counter = JSON.parse(window.sessionStorage.getItem("counter")) var image = document.getElementById("image"); var image2 = document.getElementById("image2"); var images = JSON.parse(window.sessionStorage.getItem("images")); // Handle practice trials if (practiceImages.length > 0) { const [img1, img2] = practiceImages[0]; image.src = img1; image2.src = img2; practiceImages.splice(0, 1); window.sessionStorage.setItem("practiceImages", JSON.stringify(practiceImages)); counter += 1; window.sessionStorage.setItem("counter", counter); } else { // Handle break every 15 trials if (counter % 15 === 0) { image.src = "images/images/break_2afc.png" image2.src = "images/images/break_2afc2.png" counter += 1; window.sessionStorage.setItem("counter", counter); } else { // Stop when no more valid pairs can be formed if (images.length < 2) { send2AFC(); return; } // Generate two distinct, non-matching indices let idx1, idx2; do { idx1 = Math.floor(Math.random() * images.length); idx2 = Math.floor(Math.random() * images.length); } while (idx1 === idx2 || images[idx1] === images[idx2]); // Set image sources image.src = images[idx1]; image2.src = images[idx2]; // Remove used images (delete higher index first to avoid shifting issues) if (idx1 > idx2) { images.splice(idx1, 1); images.splice(idx2, 1); } else { images.splice(idx2, 1); images.splice(idx1, 1); } window.sessionStorage.setItem("images", JSON.stringify(images)); counter += 1; window.sessionStorage.setItem("counter", counter); } } } function store2AFC(id) { const total = window.sessionStorage.getItem("total") const counter = JSON.parse(window.sessionStorage.getItem("counter")); document.getElementById("counter").innerHTML = "You are on trial " + counter + " of " + total; var answers = JSON.parse(window.sessionStorage.getItem("answers")) const img = document.getElementById("image"); const img2 = document.getElementById("image2"); const img_file = img.src.slice(-9); const img_file2 = img2.src.slice(-9); const selected = id; // Stringify question array to use as valid object key const question = JSON.stringify([img_file, img_file2]); answers[question] = selected === "image" ? [img_file] : [img_file2]; window.sessionStorage.setItem("answers", JSON.stringify(answers)); random2AFC(); } // Placeholder for your send2AFC function function send2AFC() { console.log("All trials completed, sending data..."); // Add your Firebase submission logic here } </script> </body> </html>
Key Improvements:
- Guaranteed valid pairs: The
do...whileloop keeps generating indices until we get two distinct values pointing to different images—no more self-comparisons. - Simplified array management: Removed the redundant
secondImagesarray; we now pull two unique items from a single source array. - Fixed counter tracking: Eliminated double-increment errors and simplified progress display to match trial counts.
- Proper answer storage: Stringified the question array to use as a valid object key (raw arrays can't be used as keys in JavaScript objects).
- Cleaner practice trial handling: Simplified practice array slicing and value extraction.
内容的提问来源于stack exchange,提问作者user14578710
相关产品推荐
相关产品推荐

