반응형
알겠습니다. 사용자가 게임의 크기를 선택할 수 있도록 크기 선택 기능을 추가하고, 총 카드 개수를 짝수 개로 유지하도록 하겠습니다.
HTML (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Memory Matching Game</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>Memory Matching Game</h1>
</header>
<main>
<div class="game-container">
<label for="boardSize">Select Board Size:</label>
<select id="boardSize">
<option value="4">4x4</option>
<option value="6">6x6</option>
<option value="8">8x8</option>
</select>
<div class="board" id="board"></div>
<button id="resetButton">Reset Game</button>
</div>
</main>
<script src="script.js"></script>
</body>
</html>
CSS (styles.css)
/* 기본 스타일 설정 */
body {
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
margin: 0;
background-color: #f4f4f9;
}
header {
margin-top: 20px;
}
h1 {
font-size: 2em;
}
main {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding: 20px;
}
.game-container {
background: #fff;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
padding: 20px;
text-align: center;
}
.board {
display: grid;
grid-gap: 10px;
margin-top: 20px;
}
.card {
width: 100px;
height: 100px;
background-color: #333;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 5px;
font-size: 2em;
transition: transform 0.5s;
}
.card.flipped {
background-color: #fff;
color: black;
transform: rotateY(180deg);
}
button {
margin-top: 20px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 5px;
background-color: #6200ea;
color: white;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #3700b3;
}
label, select {
margin-top: 10px;
margin-bottom: 20px;
font-size: 1em;
}
JavaScript (script.js)
document.addEventListener('DOMContentLoaded', () => {
const board = document.getElementById('board');
const resetButton = document.getElementById('resetButton');
const boardSizeSelect = document.getElementById('boardSize');
let firstCard = null;
let secondCard = null;
let lockBoard = false;
let cards = [];
function initializeGame() {
board.innerHTML = '';
const boardSize = parseInt(boardSizeSelect.value);
const totalCards = boardSize * boardSize;
if (totalCards % 2 !== 0) {
alert('The total number of cards must be even.');
return;
}
cards = generateCards(totalCards);
shuffle(cards);
createBoard(boardSize);
}
function generateCards(totalCards) {
const cardValues = [];
const pairCount = totalCards / 2;
for (let i = 0; i < pairCount; i++) {
const value = String.fromCharCode(65 + i); // A, B, C, ...
cardValues.push(value, value);
}
return cardValues;
}
function createBoard(boardSize) {
board.style.gridTemplateColumns = `repeat(${boardSize}, 100px)`;
board.style.gridTemplateRows = `repeat(${boardSize}, 100px)`;
cards.forEach(createCard);
}
function createCard(cardValue) {
const cardElement = document.createElement('div');
cardElement.classList.add('card');
cardElement.dataset.value = cardValue;
cardElement.addEventListener('click', handleCardClick);
board.appendChild(cardElement);
}
function handleCardClick(event) {
if (lockBoard) return;
const clickedCard = event.target;
if (clickedCard === firstCard) return;
clickedCard.classList.add('flipped');
clickedCard.textContent = clickedCard.dataset.value;
if (!firstCard) {
firstCard = clickedCard;
} else {
secondCard = clickedCard;
checkForMatch();
}
}
function checkForMatch() {
const isMatch = firstCard.dataset.value === secondCard.dataset.value;
isMatch ? disableCards() : unflipCards();
}
function disableCards() {
firstCard.removeEventListener('click', handleCardClick);
secondCard.removeEventListener('click', handleCardClick);
resetBoard();
}
function unflipCards() {
lockBoard = true;
setTimeout(() => {
firstCard.classList.remove('flipped');
secondCard.classList.remove('flipped');
firstCard.textContent = '';
secondCard.textContent = '';
resetBoard();
}, 1500);
}
function resetBoard() {
[firstCard, secondCard, lockBoard] = [null, null, false];
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
resetButton.addEventListener('click', initializeGame);
boardSizeSelect.addEventListener('change', initializeGame);
initializeGame();
});
설명
HTML (index.html)
- HTML 기본 구조: 문서 타입 선언 및 기본 설정.
- 헤더: 페이지 제목을 표시합니다.
- 메인 콘텐츠: 게임 컨테이너와 게임 보드, 크기 선택 드롭다운 및 리셋 버튼을 포함합니다.
- 스크립트 파일 연결: JavaScript 파일을 포함합니다.
CSS (styles.css)
- 기본 스타일 설정: 페이지의 기본 폰트, 레이아웃, 배경색 등을 설정합니다.
- header: 상단 헤더 스타일을 설정합니다.
- h1: 제목의 폰트 크기를 설정합니다.
- main: 메인 콘텐츠를 중앙에 배치합니다.
- game-container: 게임 컨테이너의 스타일을 설정합니다.
- board: 그리드 레이아웃을 사용하여 카드들을 배치합니다.
- card: 각 카드의 기본 스타일을 설정합니다. 카드가 뒤집힐 때의 애니메이션도 설정합니다.
- card.flipped: 뒤집힌 카드의 스타일을 설정합니다.
- button: 리셋 버튼의 스타일을 설정합니다.
- button:hover: 리셋 버튼에 마우스를 올렸을 때의 스타일을 설정합니다.
- label, select: 크기 선택 드롭다운의 스타일을 설정합니다.
JavaScript (script.js)
- DOMContentLoaded 이벤트 리스너: DOM이 완전히 로드되었을 때 초기화 작업을 수행합니다.
- 게임 초기화 함수 (initializeGame): 보드를 초기화하고, 카드를 생성하여 셔플 후 보드를 구성합니다.
- 카드 생성 함수 (generateCards): 짝을 이루는 카드 값을 생성합니다.
- 보드 생성 함수 (createBoard): 보드의 그리드 레이아웃을 설정하고 카드를 추가합니다.
- 카드 생성 함수 (createCard): 각 카드를 생성하여 보드에 추가합니다.
- 카드 클릭 처리 함수 (handleCardClick): 카드 클릭 시 처리 작업을 수행합니다.
- 매칭 확인 함수 (checkForMatch): 두 카드의 매칭 여부를 확인합니다.
- 카드 비활성화 함수 (disableCards): 매칭된 카드를 비활성화합니다.
- 카드 뒤집기 함수 (unflipCards): 매칭되지 않은 카드를 다시 뒤집습니다.
- 보드 리셋 함수 (resetBoard): 보드 상태를 초기화합니다.
- 카드 셔플 함수 (shuffle): 카드 배열을 랜덤하게 섞습니다.
- 리셋 버튼 및 크기 선택 이벤트 리스너: 리셋 버튼 및 크기 선택 드롭다운 변경 시 게임을 초기화합니다.
이 코드는 사용자가 게임 보드의 크기를
선택할 수 있으며, 선택한 크기에 따라 적절한 짝수 개수의 카드를 생성하여 메모리 매칭 게임을 할 수 있도록 합니다.
반응형
'Javascript 프로젝트 > 기능별 페이지' 카테고리의 다른 글
[기능별 페이지] lotto (0) | 2024.06.11 |
---|---|
[기능별 페이지] memory matching game2 (0) | 2024.06.10 |
[기능별 페이지] omok (0) | 2024.06.10 |
[기능별 페이지] - number guessing game (1) | 2024.06.10 |
[기능별 페이지] 게임 - tictactoe (1) | 2024.06.10 |