ผู้เขียนบทความ : นายณัฐชนนท์ หัชบูรณ์ รหัส 16740410056
คณะวิศวกรรมศาสตร์ : สาขาวิศวกรรมไฟฟ้
วิชา : 04000104 การโปรแกรมคอมพิวเตอร์ 1/2567
1. ความเป็นมา
เกมบิงโกมีต้นกำเนิดจากอิตาลีในศตวรรษที่ 16 โดยมีชื่อว่า “Il Gioco del Lotto d’Italia” ซึ่งคล้ายกับการเล่นลอตเตอรี่ ต่อมาในศตวรรษที่ 18 เกมนี้ได้รับความนิยมในฝรั่งเศสในชื่อ “Le Lotto”
ในปี 1929 เกมบิงโกในรูปแบบที่รู้จักในปัจจุบันถูกพัฒนาขึ้นในสหรัฐอเมริกา โดยใช้ตาราง 5×5 ที่มีตัวเลขสุ่ม ผู้เล่นจะทำเครื่องหมายหมายเลขที่ถูกเรียก และเป้าหมายคือการสร้างแถวหรือแนวตั้งที่เต็มไปด้วยหมายเลขที่ทำเครื่องหมาย
ในช่วงปี 1930 เกมบิงโกเริ่มถูกใช้ในงานการกุศล และต่อมาแพร่หลายไปทั่วโลกในคาสิโนและห้องเล่นเกมต่างๆ ปัจจุบัน เกมบิงโกมีรูปแบบทั้งที่เล่นในที่จริงและแบบออนไลน์ ทำให้ยังคงเป็นที่นิยมในกลุ่มผู้เล่นทุกเพศทุกวัย
2.วัตถุประสงค์
- เพื่อความบันเทิง : เกมบิงโกเป็นกิจกรรมที่สนุกสนานและสามารถเล่นได้หลายคน
- ส่งเสริมการมีส่วนร่วม : เกมช่วยให้ผู้เล่นมีปฏิสัมพันธ์และสร้างสัมพันธ์กับผู้คนรอบข้าง
- ส่งเสริมการมีส่วนร่วม : เกมนี้ช่วยให้ผู้เล่นมีปฏิสัมพันธ์และสื่อสารกับผู้อื่น ซึ่งสามารถสร้างความสัมพันธ์ใหม่ๆ และส่งเสริมการทำงานเป็นทีม
- การแข่งขัน : สำหรับบางกลุ่ม เกมบิงโกเป็นการแข่งขันที่มีรางวัล ทำให้ผู้เล่นมีแรงจูงใจในการเล่นและสร้างความตื่นเต้น
3. ขอบเขต
- จำนวนผู้เล่น : เกมบิงโกสามารถเล่นได้ตั้งแต่ 2 คนขึ้นไป โดยทั่วไปแล้วมักเล่นในกลุ่มขนาดใหญ่ เช่น 10-100 คน
- รูปแบบของเกม : บิงโกคลาสสิก: การเล่นด้วยการ์ดที่มีหมายเลขและการเรียกหมายเลขบิงโก 75 ลูก: ใช้การ์ด 5×5 และหมายเลข 1-75 บิงโก 90 ลูก: การเล่นที่นิยมในสหราชอาณาจักร ใช้การ์ด 3 แถว 9 คอลัมน์ บิงโก
- กฎและเงื่อนไขการเล่น : กฎของเกมสามารถปรับเปลี่ยนได้ตามกลุ่มผู้เล่นหรือประเภทของบิงโกที่เล่น เช่น วิธีการชนะอาจมีความแตกต่างกัน เช่น การชนะในแถว, คอลัมน์ หรือรูปแบบต่างๆ (เช่น รูปตัว X หรือเส้นทแยงมุม)
4. ประโยชน์ที่คาดว่าจะได้รับ
• การฝึกทักษะการสังเกต : ผู้เล่นต้องมีความสามารถในการจดจำหมายเลขและสังเกตหมายเลขที่ถูกเรียก
• การเสริมสร้างความสัมพันธ์ : เป็นกิจกรรมที่สามารถรวมกลุ่มคนและสร้างความสัมพันธ์ได้ดี
• การสนับสนุนการทำงานเป็นที ม: ผู้เล่นสามารถเล่นเป็นทีมและช่วยกันเพื่อชนะ
5. ความรู้ที่เกี่ยวข้อง
- ความรู้พื้นฐานเกี่ยวกับ HTML โครงสร้าง HTML: เข้าใจการใช้แท็กต่างๆ เช่น <html>,<head>,<tr>,<td>อื่นๆ เพื่อสร้างโครงสร้างของหน้าเว็บ
- ความรู้พื้นฐานเกี่ยวกับ CSS : การออกแบบสไตล์: ใช้ CSS ในการตกแต่งหน้าเว็บ เช่น การกำหนดสีพื้นหลัง, สีของข้อความ, ขนาดตัวอักษร, และการจัดตำแหน่งของเนื้อหา
- ความรู้เกี่ยวกับ JavaScript : การจัดการเหตุการณ์ (Event Handling): เข้าใจการใช้ addEventListener เพื่อเชื่อมต่อการกระทำของผู้ใช้กับฟังก์ชันที่กำหนด
6. การดำเนินงาน
- โครงสร้าง HTML • HTML Boilerplate: ส่วนแรกของโค้ดเป็นโครงสร้างพื้นฐานของเอกสาร HTML โดยมีการกำหนด สำหรับข้อมูลเมตาและสไตล์ และ สำหรับเนื้อหาหลักของหน้าเว็บ
• ส่วนหัว (Heading): มี สำหรับชื่อเกมและ สำหรับชื่อการ์ดบิงโกแต่ละใบ
• การ์ดบิงโก: มี สำหรับการ์ดบิงโกสองใบ พร้อมตารางที่ใช้ สำหรับแสดงหมายเลขบิงโก
- สไตล์ (CSS) • การออกแบบ: สไตล์ถูกกำหนดเพื่อให้เกมมีความน่าสนใจ โดยใช้ CSS เพื่อปรับแต่งสีพื้นหลัง, ขอบ, และการจัดวางองค์ประกอบ
• การเปลี่ยนแปลงสี: CSS ยังทำให้มีการเปลี่ยนแปลงสีของเซลล์เมื่อมีการเลือกหรือหมายเลขที่ยังไม่ออก
3.JavaScript ตัวแปรและสถานะเกม ตัวแปร:
• bingoNumbers: เก็บหมายเลขที่ถูกสุ่มแล้ว
• drawnNumbers: เก็บหมายเลขที่ถูกสุ่มออกมาแล้วเพื่อให้สามารถตรวจสอบได้
• gameOver: ตัวแปรที่ใช้ตรวจสอบว่าเกมจบหรือยัง
• Draw Number : จะสุ่มหมายเลขใหม่และอัปเดตสถานะของเกม
• ปุ่ม Reset Game : จะคืนค่าทุกอย่างและเริ่มเกมใหม่
3.1 generateBingoCard(cardId):
• สร้างบัตรบิงโกใหม่ โดยสุ่มหมายเลข 1-75 สำหรับแต่ละเซลล์ในตาราง 5×5
• ทำเครื่องหมายช่องกลางว่าเป็น “FREE” และทำให้เซลล์ที่ยังไม่ได้สุ่มเป็น “disabled”
• เพิ่มเหตุการณ์คลิกให้แต่ละเซลล์เพื่อตรวจสอบการคลิกและการเลือกหมายเลข
3.2 drawNumber():
• สุ่มหมายเลขใหม่จาก 1-75 และเพิ่มหมายเลขนั้นไปยัง bingoNumbers และ drawnNumbers
• แสดงหมายเลขที่ถูกสุ่มในหน้าเว็บ
• เปลี่ยนสถานะของเซลล์ในบัตรบิงโกให้สามารถคลิกได้หากหมายเลขนั้นถูกสุ่ม
3.3 checkWin():
• ตรวจสอบว่าผู้เล่นชนะหรือไม่ โดยการตรวจสอบแถว, คอลัมน์, และเส้นทแยงมุม ว่ามีหมายเลขที่ถูกเลือก
• หากมีการชนะ จะทำการแสดงข้อความยืนยันในหน้าเว็บ
3.4 resetGame():
• รีเซ็ตตัวแปรทั้งหมดกลับไปสู่สถานะเริ่มต้น และสร้างบัตรบิงโกใหม่สำหรับการเริ่มเกมใหม่
- การดำเนินการเมื่อโหลดหน้า • window.onload: เมื่อหน้าโหลด จะสร้างบัตรบิงโกสองใบให้ผู้เล่น
- การโต้ตอบของผู้ใช้ • ผู้เล่นสามารถคลิกที่เซลล์ในบัตรบิงโกเพื่อทำเครื่องหมายหมายเลขที่ถูกสุ่มออกมา และปุ่ม “Draw Number” จะสุ่มหมายเลขใหม่และอัปเดตสถานะของเกม
• ปุ่ม “Reset Game” จะคืนค่าทุกอย่างและเริ่มเกมใหม่
8. การทดลอง (Testing)
- ลองเล่นเกมหลายรอบเพื่อตรวจสอบว่าฟังก์ชันสุ่มหมายเลขและการเลือกหมายเลขทำงานได้ตามที่คาดหวัง
- ตรวจสอบว่าการกดปุ่มรีเซ็ตสามารถเริ่มเกมใหม่ได้โดยไม่มีปัญหา
- ทดสอบหลายๆ การ์ดบิงโกพร้อมกันเพื่อดูว่าระบบสามารถตรวจสอบการชนะได้อย่างแม่นยำในทุกการ์ด
9.เทคนิคการประยุกต์เพื่อเพิ่มประสิทธิภาพ
9.1ปรับปรุงการสุ่มหมายเลขและการทำงานของเกม
• การสุ่มหมายเลขแบบจัดลำดับล่วงหน้า (Pre-shuffle Numbers):
• แทนที่จะสุ่มหมายเลขทุกครั้งที่กดปุ่ม Draw Number คุณสามารถทำการสุ่มหมายเลขทั้งหมด 1-75 ล่วงหน้าแล้วจัดเก็บไว้ในอาร์เรย์ และดึงตัวเลขจากอาร์เรย์นั้นทีละตัว วิธีนี้จะช่วยลดการทำงานของฟังก์ชันสุ่มทุกครั้งที่กดปุ่ม
9.2ลดการใช้งานทรัพยากร DOM
• การใช้ Event Delegation:
• แทนที่จะกำหนด event listener สำหรับทุก td ของบิงโกการ์ด คุณสามารถใช้ Event Delegation โดยติดตั้ง event listener ไว้ที่ระดับ table และตรวจสอบว่าเซลล์ใดถูกคลิกโดยดูจาก event.target ซึ่งจะช่วยลดจำนวน event listeners ที่สร้างขึ้นและเพิ่มประสิทธิภาพ
การเพิ่มประสิทธิภาพการตรวจสอบการชนะ
• ลดการคำนวณซ้ำซ้อนในฟังก์ชัน checkWin:
• แทนที่จะตรวจสอบการชนะของแถว คอลัมน์ และเส้นทแยงมุมทุกครั้งที่ทำเครื่องหมายช่อง คุณสามารถเก็บข้อมูลสถานะของแถว/คอลัมน์ในตัวแปร เช่น นับจำนวนของเซลล์ที่ถูกทำเครื่องหมายในแต่ละแถวหรือคอลัมน์ และอัปเดตตัวแปรนั้นทุกครั้งที่มีการทำเครื่องหมายใหม่ ซึ่งจะช่วยลดการตรวจสอบที่ไม่จำเป็น
10.สรุปผลและข้อเสนอแนะ
สรุปผล
การสร้างเกมบิงโกในโค้ดที่ได้เสนอมีการทำงานพื้นฐานที่ดี โดยรองรับการสุ่มหมายเลข การเลือกหมายเลขในบิงโกการ์ด และการตรวจสอบการชนะในแถว คอลัมน์ และเส้นทแยงมุม โค้ดมีการใช้งาน DOM อย่างเหมาะสม และมีองค์ประกอบการแสดงผลที่ดูง่ายและเป็นมิตรกับผู้ใช้ (User-Friendly)
อย่างไรก็ตาม มีบางจุดที่สามารถปรับปรุงเพื่อเพิ่มประสิทธิภาพของเกมให้ดียิ่งขึ้น เช่น การลดการคำนวณที่ซ้ำซ้อน การปรับปรุงการทำงานของ DOM และการจัดการหน่วยความจำอย่างมีประสิทธิภาพ รวมถึงการจัดการการสุ่มหมายเลขและการตรวจสอบการชนะในเกมอย่างมีประสิทธิผล
ข้อเสนอแนะ
- ปรับปรุงการสุ่มหมายเลขล่วงหน้า: ทำการสุ่มหมายเลข 1-75 ล่วงหน้าแล้วเก็บไว้ในอาร์เรย์ ช่วยลดการทำงานของฟังก์ชันสุ่มเมื่อกดปุ่มดึงหมายเลข
- ลดจำนวน Event Listeners: ใช้เทคนิค Event Delegation เพื่อลดการสร้าง event listeners สำหรับทุกๆ เซลล์ของบิงโกการ์ด ช่วยลดการใช้งานหน่วยความจำและปรับปรุงประสิทธิภาพการทำงานของหน้าเว็บ
- เพิ่มประสิทธิภาพการตรวจสอบการชนะ: แทนที่จะตรวจสอบทุกแถว คอลัมน์ และเส้นทแยงมุมทุกครั้งที่ทำเครื่องหมาย ให้เก็บสถานะของแถวและคอลัมน์ในตัวแปรแล้วอัปเดตทุกครั้งที่มีการทำเครื่องหมายใหม่ เพื่อลดการคำนวณที่ไม่จำเป็น
11. ข้อมูลอ้างอิง
https://th.theasianparent.com/bingo-game-for-kids
Code ของโปรแกรม
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bingo Game</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
background-color: #f0f8ff; /* สีพื้นหลัง */
padding: 20px;
}
h1 {
color: #333;
}
.bingo-card {
display: inline-block;
margin: 20px;
}
table {
margin: 0 auto;
border-collapse: collapse;
border-radius: 10px; /* มุมโค้ง */
overflow: hidden; /* ซ่อนขอบของตาราง */
}
table, th, td {
border: 2px solid #4CAF50; /* ขอบตาราง */
}
td {
width: 60px;
height: 60px;
text-align: center;
vertical-align: middle;
font-size: 24px;
font-weight: bold;
color: #333;
transition: background-color 0.3s; /* เพิ่มการเปลี่ยนแปลงสี */
background-color: #e0f7fa; /* สีพื้นหลังของเซลล์ */
cursor: pointer;
}
td.marked {
background-color: #4CAF50; /* สีเซลล์ที่ถูกเลือก */
color: white; /* เปลี่ยนสีตัวอักษรเมื่อเลือก */
}
td.disabled {
background-color: #ddd; /* สีเซลล์ที่ยังไม่สามารถคลิก */
cursor: not-allowed;
}
td.not-drawn {
background-color: #ffcccb; /* สีสำหรับหมายเลขที่ยังไม่ออก */
}
button {
margin-top: 20px;
padding: 10px 20px;
font-size: 18px;
background-color: #4CAF50; /* สีปุ่ม */
color: white; /* สีตัวอักษรในปุ่ม */
border: none;
border-radius: 5px; /* มุมโค้งของปุ่ม */
cursor: pointer;
transition: background-color 0.3s; /* เพิ่มการเปลี่ยนแปลงสีของปุ่ม */
}
button:hover {
background-color: #45a049; /* สีของปุ่มเมื่อเอาเมาส์ไปวาง */
}
#bingo-status {
color: #d32f2f; /* สีสถานะการชนะ */
font-size: 24px;
font-weight: bold;
}
#drawn-number {
font-size: 20px;
margin-top: 10px;
}
</style>
</head>
<body>
<h1>Bingo Game</h1>
<div class="bingo-card" id="bingo-card-1">
<h2>Bingo Card 1</h2>
<table id="bingoTable1"></table>
</div>
<div class="bingo-card" id="bingo-card-2">
<h2>Bingo Card 2</h2>
<table id="bingoTable2"></table>
</div>
<p id="drawn-number"></p>
<p id="bingo-status"></p>
<button onclick="drawNumber()">Draw Number</button>
<button onclick="resetGame()">Reset Game</button>
<script>
let bingoNumbers = [];
let drawnNumbers = [];
let gameOver = false;
function generateBingoCard(cardId) {
const bingoTable = document.getElementById(cardId);
bingoTable.innerHTML = ''; // ลบข้อมูลเก่าในตารางก่อน
const usedNumbers = new Set();
for (let row = 0; row < 5; row++) {
const tr = document.createElement('tr');
for (let col = 0; col < 5; col++) {
const td = document.createElement('td');
if (row === 2 && col === 2) {
td.textContent = 'FREE';
td.classList.add('marked'); // ทำให้ช่องกลางถูกเลือก
} else {
let randomNumber;
do {
randomNumber = Math.floor(Math.random() * 75) + 1;
} while (usedNumbers.has(randomNumber));
usedNumbers.add(randomNumber);
td.textContent = randomNumber;
}
td.classList.add('disabled');
td.addEventListener('click', () => {
// เช็คว่าเกมยังไม่จบและหมายเลขถูกสุ่มแล้ว
if (!gameOver) {
if (drawnNumbers.includes(parseInt(td.textContent))) {
// หากหมายเลขถูกสุ่มแล้ว
if (!td.classList.contains('marked')) {
td.classList.add('marked');
checkWin();
}
} else {
// หากหมายเลขยังไม่ถูกสุ่มออก
td.classList.add('not-drawn'); // เปลี่ยนสีเมื่อหมายเลขยังไม่ออก
alert("This number hasn't been drawn yet!");
}
}
});
tr.appendChild(td);
}
bingoTable.appendChild(tr);
}
}
function drawNumber() {
if (bingoNumbers.length === 75) {
alert('All numbers have been drawn!');
return;
}
let randomNumber;
do {
randomNumber = Math.floor(Math.random() * 75) + 1;
} while (bingoNumbers.includes(randomNumber));
bingoNumbers.push(randomNumber);
drawnNumbers.push(randomNumber);
document.getElementById('drawn-number').textContent = 'Number drawn: ' + randomNumber;
for (let cardId = 1; cardId <= 2; cardId++) {
const table = document.getElementById('bingoTable' + cardId);
for (let row = 0; row < 5; row++) {
for (let col = 0; col < 5; col++) {
const cell = table.rows[row].cells[col];
if (parseInt(cell.textContent) === randomNumber) {
cell.classList.remove('disabled');
}
}
}
}
}
function checkWin() {
for (let cardId = 1; cardId <= 2; cardId++) {
const table = document.getElementById('bingoTable' + cardId);
const size = 5;
let win = false;
// ตรวจสอบแถว
for (let row = 0; row < size; row++) {
let rowMarked = true;
for (let col = 0; col < size; col++) {
if (!table.rows[row].cells[col].classList.contains('marked')) {
rowMarked = false;
break;
}
}
if (rowMarked) {
win = true;
break;
}
}
// ตรวจสอบคอลัมน์
for (let col = 0; col < size; col++) {
let colMarked = true;
for (let row = 0; row < size; row++) {
if (!table.rows[row].cells[col].classList.contains('marked')) {
colMarked = false;
break;
}
}
if (colMarked) {
win = true;
break;
}
}
// ตรวจสอบเส้นทแยงมุม
let diag1Marked = true;
for (let i = 0; i < size; i++) {
if (!table.rows[i].cells[i].classList.contains('marked')) {
diag1Marked = false;
break;
}
}
if (diag1Marked) win = true;
let diag2Marked = true;
for (let i = 0; i < size; i++) {
if (!table.rows[i].cells[size - 1 - i].classList.contains('marked')) {
diag2Marked = false;
break;
}
}
if (diag2Marked) win = true;
if (win) {
document.getElementById('bingo-status').textContent = 'Bingo on Card ' + cardId + '!';
gameOver = true;
}
}
}
function resetGame() {
// รีเซ็ตค่าต่าง ๆ
bingoNumbers = [];
drawnNumbers = [];
gameOver = false;
document.getElementById('bingo-status').textContent = '';
document.getElementById('drawn-number').textContent = '';
// สร้างบิงโกการ์ดใหม่
generateBingoCard('bingoTable1');
generateBingoCard('bingoTable2');
}
window.onload = function() {
generateBingoCard('bingoTable1');
generateBingoCard('bingoTable2');
};
</script>
</body>
</html>