จัดทำโดย นาย ก้องภพ มณีสิทธิ์
รหัสวิชา 04-000-104 การโปรแกรมคอมพิวเตอร์
1. ความเป็นมา
เกม XO เป็นเกมที่มีต้นกำเนิดมาจากการเล่นบนกระดาษ ใช้อุปกรณ์ง่ายๆ แต่สามารถสร้างความสนุกและความคิดสร้างสรรค์ได้เสมอ แต่ในยุคปัจจุบันที่เทคโนโลยีและการเขียนโปรแกรมเข้ามามีบทบาทในชีวิตประจำวัน การนำเกมนี้มาอยู่ในรูปแบบดิจิทัลสามารถทำให้การเล่นสะดวกและเข้าถึงง่ายมากยิ่งขึ้นนอกจากนี้ แนวคิดการสร้างเกม XO ยังสามารถนำไปประยุกต์ใช้ในวิศวกรรมไฟฟ้าได้เช่นกัน ตัวอย่างเช่น การเขียนโปรแกรมควบคุมวงจร หรือ ระบบฝังตัว (embedded system) โดยการสร้างตรรกะที่ใช้ในเกมนี้คล้ายคลึงกับการออกแบบ วงจรลอจิก ที่ใช้ในการควบคุมการทำงานของอุปกรณ์อิเล็กทรอนิกส์ต่างๆ เช่น การออกแบบระบบควบคุมที่ต้องให้เงื่อนไขตรงตามที่กำหนด เช่นเดียวกับการตรวจสอบผู้ชนะในเกม XO ที่ต้องตรวจเงื่อนไขต่างๆ ในการเรียงแถว การออกแบบเหล่านี้สามารถช่วยสร้างความเข้าใจเบื้องต้นเกี่ยวกับการออกแบบระบบควบคุมในทางวิศวกรรมไฟฟ้านอกจากนี้ การออกแบบ UI/UX ที่ใช้งานง่ายในเกม XO ยังเป็นแนวคิดที่วิศวกรไฟฟ้าอาจนำไปประยุกต์ใช้กับ แผงควบคุมอุปกรณ์ไฟฟ้า หรือ ระบบอัตโนมัติ ให้ผู้ใช้งานสามารถควบคุมและติดตามผลการทำงานของระบบต่างๆ ได้อย่างชัดเจนและสะดวก
2.วัตถุประสงค์
วัตถุประสงค์หลักของการสร้างเกม XO บนเว็บนี้คือเพื่อจำลองการเล่นเกม XO แบบดั้งเดิมให้มาอยู่ในรูปแบบดิจิทัล เพื่อให้ผู้เล่นสามารถเพลิดเพลินไปกับการเล่นเกมได้ทุกที่ทุกเวลา นอกจากนี้ โปรแกรมนี้ยังช่วยพัฒนาทักษะการคิดวิเคราะห์และการวางแผนล่วงหน้า เป็นการฝึกสมองเล็กๆ น้อยๆ ที่สนุกและไม่ยุ่งยาก
3. ขอบเขต
โปรแกรมเกม XO ที่เราออกแบบมานี้เหมาะสำหรับการเล่นระหว่างผู้เล่นสองคน โดยตัวเกมจะมีกริด 3×3 ที่ให้ผู้เล่นผลัดกันใส่ตัวอักษร “X” และ “O” จนกว่าจะมีผู้ชนะ หรือเกมเสมอกัน หากมีผู้ชนะ โปรแกรมจะสร้างกระดาษสีตกลงมาเพื่อฉลองชัยชนะ และจะแสดงคะแนนของผู้เล่นแต่ละฝั่ง ไม่ได้มีการเล่นกับคอมพิวเตอร์ (AI) หรือการออนไลน์แข่งกับผู้เล่นอื่น แต่ก็เหมาะกับการเล่นในหมู่เพื่อนๆ ได้อย่างดี
4.ประโยชน์ที่คาดว่าจะได้รับ
• ช่วยสร้างความเพลิดเพลินในเวลาว่าง
• ฝึกการคิดวิเคราะห์ วางแผน และการสังเกต
• กระตุ้นสมองในรูปแบบเกมเบาๆ โดยไม่ต้องมีความซับซ้อน
• พัฒนาทักษะการเขียนโปรแกรมด้านการจัดการเหตุการณ์ (event-driven programming) และการจัดการ DOM สำหรับนักพัฒนา
• เป็นตัวอย่างที่ดีสำหรับการศึกษาการสร้างเกมด้วย HTML, CSS และ JavaScript
5. ความรู้ที่เกี่ยวข่้อง
โปรแกรมนี้ใช้ HTML เป็นโครงสร้างของหน้าเว็บ, CSS ในการจัดแต่งรูปแบบและการเคลื่อนไหว และ JavaScript ในการควบคุมการทำงานของเกม ตั้งแต่การตรวจสอบผู้ชนะ การสลับเทิร์น การคำนวณคะแนน ไปจนถึงการสร้างเอฟเฟกต์กระดาษตกเมื่อชนะ นอกจากนี้ยังมีการใช้การออกแบบที่เรียกว่า grid layout สำหรับการจัดวางตำแหน่งกล่องต่างๆ ในเกม รวมถึงการใช้ event listeners ในการจัดการการคลิกของผู้เล่น
6.สรุปวิธีการใช้โปรแกรม
- เปิดเกม XO ผ่านเบราว์เซอร์ใดก็ได้
- จะมีกริด 3×3 แสดงบนหน้าจอ ผู้เล่นสองคนสามารถผลัดกันคลิกที่ช่องว่างในกริดเพื่อวาง “X” หรือ “O”
- หากผู้เล่นคนใดคนหนึ่งเรียงตัวอักษรครบ 3 ตัวตามเงื่อนไขชนะ (แนวนอน แนวตั้ง หรือแนวทแยง) โปรแกรมจะแสดงผลว่าผู้เล่นคนนั้นชนะ
- หลังจากที่มีผู้ชนะหรือเกมเสมอ ปุ่มเล่นอีกครั้งจะปรากฏขึ้น เพื่อให้เริ่มเกมใหม่
- โปรแกรมจะนับคะแนนของผู้เล่นแต่ละฝั่งตามจำนวนครั้งที่ชนะ
7. บทสรุปผลการทดลอง
หลังจากทดลองเล่นแล้ว พบว่าเกม XO นี้ทำงานได้ดี ไม่มีปัญหาในการเล่น ข้อมูลการสลับเทิร์นและการตรวจสอบผู้ชนะสามารถทำได้อย่างถูกต้อง เอฟเฟกต์กระดาษตกเมื่อมีผู้ชนะทำให้เกมดูสนุกและมีชีวิตชีวามากขึ้น การใช้งานง่าย ผู้เล่นไม่ต้องมีทักษะพิเศษในการเล่น เพราะทุกอย่างถูกจัดการด้วยการคลิกเพียงอย่างเดียว
8. การทำงานของโปรแกรม
1. การตั้งค่าเริ่มต้น (HTML + CSS)
1.1 HTML
- โค้ดสร้างโครงสร้างพื้นฐานของหน้าเว็บโดยใช้แท็ก HTML ต่างๆ เช่น
<div>
สำหรับกล่องตาราง 3×3 และ<button>
สำหรับปุ่ม “เล่นใหม่” - ตัวอย่างการใช้งาน:
<div class="turn-container">
ใช้แสดงข้อความ “Turn For” และบอกว่าตอนนี้เป็นตาของผู้เล่นคนใด (X หรือ O)<div class="main-grid">
ใช้สร้างตารางเกม 3×3 (9 กล่อง) ซึ่งเป็นพื้นที่ที่ผู้เล่นจะคลิกเพื่อใส่สัญลักษณ์ X หรือ O<div id="score-container">
ใช้แสดงคะแนนของผู้เล่นทั้งสองคน โดยเริ่มต้นจาก 0
1.2 CSS
- การออกแบบและจัดสไตล์หน้าเว็บ เช่น ขนาดกล่องในตาราง สีพื้นหลัง ฟอนต์ และการจัดวางองค์ประกอบต่างๆ ในหน้าจอ
- CSS กำหนดสีสันของแต่ละองค์ประกอบ เช่น สีของผู้เล่นที่ชนะ (
#08D9D6
) สีพื้นหลัง (#252A34
) และการเปลี่ยนสีเมื่อเมาส์วางเหนือกล่อง (เปลี่ยนเป็นสีแดง) - มีการใช้แอนิเมชันสำหรับการสร้าง “กระดาษตก” เพื่อเฉลิมฉลองเมื่อมีผู้ชนะ
- CSS กำหนดสีสันของแต่ละองค์ประกอบ เช่น สีของผู้เล่นที่ชนะ (
2. การจัดการการเล่นเกม (JavaScript)
2.1 ตัวแปรและสถานะ
- ตัวแปรที่สำคัญมีดังนี้:
boxes
: เก็บกล่องทั้งหมดในตารางเกมturn
: เก็บข้อมูลว่าผู้เล่นคนใดกำลังเล่น (เริ่มต้นเป็น “X”)isGameOver
: ใช้ตรวจสอบว่าเกมสิ้นสุดแล้วหรือยังxScore
และoScore
: เก็บคะแนนของผู้เล่น X และ O ตามลำดับ
2.2 การคลิกและการเปลี่ยนผู้เล่น
- เมื่อผู้เล่นคลิกที่กล่องใดๆ จะทำการตรวจสอบว่า:
- กล่องนั้นว่างอยู่หรือไม่
- เกมสิ้นสุดแล้วหรือยัง
- ถ้ากล่องว่างและเกมยังไม่จบ จะทำการใส่สัญลักษณ์ของผู้เล่นปัจจุบัน (X หรือ O) ลงในกล่อง
- จากนั้นจะสลับตาไปยังผู้เล่นคนถัดไปโดยการเรียกฟังก์ชัน
changeTurn()
ซึ่งจะเปลี่ยนตัวแปรturn
และย้ายแถบสีบอกสถานะผู้เล่น
2.3 ฟังก์ชันตรวจสอบผู้ชนะ (checkWin)
- มีเงื่อนไขการชนะทั้งหมด 8 รูปแบบ (3 แนวนอน, 3 แนวตั้ง, 2 แนวทแยง) ซึ่งจะถูกตรวจสอบโดยฟังก์ชัน
checkWin()
- ฟังก์ชันจะตรวจสอบว่าในกล่องที่กำหนดมีสัญลักษณ์ X หรือ O ที่เรียงกันครบสามตัวหรือไม่ ถ้าพบผู้ชนะจะทำการ:
- แสดงข้อความบอกผู้ชนะ
- เพิ่มคะแนนให้กับผู้เล่นที่ชนะ
- เรียกแอนิเมชัน “กระดาษตก” เพื่อเฉลิมฉลอง
- เปลี่ยนสีพื้นหลังของกล่องที่ทำให้ชนะ
- ฟังก์ชันจะตรวจสอบว่าในกล่องที่กำหนดมีสัญลักษณ์ X หรือ O ที่เรียงกันครบสามตัวหรือไม่ ถ้าพบผู้ชนะจะทำการ:
2.4 ฟังก์ชันตรวจสอบว่าเสมอหรือไม่ (checkDraw)
- ถ้าทุกกล่องเต็มและไม่มีผู้ชนะ ฟังก์ชันนี้จะตั้งค่าว่าเกมจบลงด้วยผลเสมอ และแสดงข้อความบอกผู้เล่นว่าเกมเสมอแล้ว
2.5 การเล่นเกมใหม่ (play again)
- เมื่อเกมจบลง (ไม่ว่าจะชนะหรือเสมอ) จะมีการแสดงปุ่ม “เล่นใหม่” ซึ่งเมื่อผู้เล่นคลิก ระบบจะทำการรีเซ็ตตารางเกมทั้งหมดและเริ่มเกมใหม่ทันที
3. สรุปการทำงานโดยรวม
- เมื่อผู้เล่นคลิกบนกล่องในตาราง 3×3 ระบบจะ:
- ใส่สัญลักษณ์ X หรือ O ลงในกล่องนั้น
- ตรวจสอบว่ามีผู้ชนะหรือไม่
- ถ้าผู้เล่นชนะ ระบบจะเพิ่มคะแนนและฉลองด้วยการแสดง “กระดาษตก”
- ถ้าทุกกล่องเต็มและไม่มีผู้ชนะ ระบบจะถือว่าเกมเสมอ
- ผู้เล่นสามารถเริ่มเกมใหม่ได้โดยการกดปุ่ม “เล่นใหม่”
ภาพรวมของโค้ด
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ดวลกันป่าวจ๊ะ</title>
<style>
* {
color: white;
font-family: sans-serif;
transition: 0.2s ease-in-out;
user-select: none;
}
.align {
display: flex;
justify-content: center;
align-items: center;
}
body {
background-color: #252A34;
margin: 0;
padding: 0;
width: 100vw;
text-align: center;
padding-top: 5vh;
overflow: hidden; /* Prevent scrollbar from appearing */
position: relative;
}
.turn-container {
width: 170px;
height: 80px;
margin: auto;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
position: relative;
}
.turn-container h3 {
margin: 0;
grid-column-start: 1;
grid-column-end: 3;
}
.turn-container .turn-box {
border: 3px solid #000;
font-size: 1.6rem;
font-weight: 700;
}
.turn-container .turn-box:nth-child(even) {
border-right: none;
}
.bg {
position: absolute;
bottom: 0;
left: 0;
width: 85px;
height: 40px;
background-color: #FF2E63;
z-index: -1;
}
.main-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
height: 250px;
width: 250px;
margin: 30px auto;
border: 2px solid #000;
}
.box {
cursor: pointer;
font-size: 2rem;
font-weight: 700;
border: 2px solid #000;
}
.box:hover {
background-color: #FF2E63;
}
#play-again {
background-color: #FF2E63;
padding: 10px 25px;
border: none;
font-size: 1.2rem;
border-radius: 5px;
cursor: pointer;
display: none;
}
#play-again:hover {
padding: 10px 40px;
background-color: #08D9D6;
color: #000;
}
@keyframes fall {
0% {
transform: translateY(0);
opacity: 1;
}
100% {
transform: translateY(100vh);
opacity: 0;
}
}
.paper {
position: absolute;
width: 10px; /* Adjust paper size */
height: 10px; /* Adjust paper size */
background-color: red; /* Default color */
opacity: 0.8;
animation: fall linear forwards;
}
#score-container {
position: absolute;
right: 20px; /* Adjust position */
top: 20px; /* Adjust position */
text-align: left;
}
</style>
</head>
<body>
<div class="turn-container">
<h3>Turn For</h3>
<div class="turn-box align">X</div>
<div class="turn-box align">O</div>
<div class="bg"></div>
</div>
<div id="score-container">
<h2>Score</h2>
<p>X: <span id="x-score">0</span></p>
<p>O: <span id="o-score">0</span></p>
</div>
<div class="main-grid">
<div class="box align">0</div>
<div class="box align">1</div>
<div class="box align">2</div>
<div class="box align">3</div>
<div class="box align">4</div>
<div class="box align">5</div>
<div class="box align">6</div>
<div class="box align">7</div>
<div class="box align">8</div>
</div>
<h2 id="results"></h2>
<button id="play-again">ไหวป่าวอีกสักทีไหม</button>
<script>
let boxes = document.querySelectorAll(".box");
let turn = "X";
let isGameOver = false;
let xScore = 0;
let oScore = 0;
boxes.forEach(e => {
e.innerHTML = "";
e.addEventListener("click", () => {
if (!isGameOver && e.innerHTML === "") {
e.innerHTML = turn;
checkWin();
checkDraw();
changeTurn();
}
});
});
function changeTurn() {
if (turn === "X") {
turn = "O";
document.querySelector(".bg").style.left = "85px";
} else {
turn = "X";
document.querySelector(".bg").style.left = "0";
}
}
function createPapers(count) {
const colors = ["red", "blue", "green", "yellow", "orange", "purple"]; // Define colors for papers
for (let i = 0; i < count; i++) {
const paper = document.createElement("div");
paper.classList.add("paper");
paper.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; // Random color
paper.style.left = Math.random() * 100 + "vw"; // Random horizontal position
paper.style.top = "80px"; // Start falling from below the "Turn For" bar
paper.style.animationDuration = Math.random() * 4 + 3 + "s"; // Random duration between 3s to 7s
document.body.appendChild(paper);
// Remove paper after falling
setTimeout(() => {
paper.remove();
}, 7000); // Should match the max duration in animation
}
}
function checkWin() {
let winConditions = [
[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6]
];
for (let i = 0; i < winConditions.length; i++) {
let v0 = boxes[winConditions[i][0]].innerHTML;
let v1 = boxes[winConditions[i][1]].innerHTML;
let v2 = boxes[winConditions[i][2]].innerHTML;
if (v0 !== "" && v0 === v1 && v0 === v2) {
isGameOver = true;
createPapers(500); // Create 500 papers when someone wins
if (turn === "X") {
xScore++;
document.querySelector("#x-score").innerHTML = xScore;
} else {
oScore++;
document.querySelector("#o-score").innerHTML = oScore;
}
document.querySelector("#results").innerHTML = turn + " ชนะใสๆ ง่ายไปป่าว";
document.querySelector("#play-again").style.display = "inline";
for (let j = 0; j < 3; j++) {
boxes[winConditions[i][j]].style.backgroundColor = "#08D9D6";
boxes[winConditions[i][j]].style.color = "#000";
}
}
}
}
function checkDraw() {
if (!isGameOver) {
let isDraw = true;
boxes.forEach(e => {
if (e.innerHTML === "") isDraw = false;
});
if (isDraw) {
isGameOver = true;
document.querySelector("#results").innerHTML = "เสมอเอาใหม่ป่ะ";
document.querySelector("#play-again").style.display = "inline";
}
}
}
document.querySelector("#play-again").addEventListener("click", () => {
isGameOver = false;
turn = "X";
document.querySelector(".bg").style.left = "0";
document.querySelector("#results").innerHTML = "";
document.querySelector("#play-again").style.display = "none";
boxes.forEach(e => {
e.innerHTML = "";
e.style.removeProperty("background-color");
e.style.color = "#fff";
});
});
</script>
</body>
</html>