0% found this document useful (0 votes)
26 views16 pages

Make 24 Math Puzzle Game

The document describes a web-based math puzzle game called 'Make 24', where players drag numbers and operators to form equations that equal 24. It includes a start screen, game mechanics for dragging and dropping elements, and event listeners for user interactions. The game features levels with predefined number sets and checks for correct equations to advance the player through levels.

Uploaded by

dantrung18091995
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views16 pages

Make 24 Math Puzzle Game

The document describes a web-based math puzzle game called 'Make 24', where players drag numbers and operators to form equations that equal 24. It includes a start screen, game mechanics for dragging and dropping elements, and event listeners for user interactions. The game features levels with predefined number sets and checks for correct equations to advance the player through levels.

Uploaded by

dantrung18091995
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

<!

DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Make 24 - Math Puzzle Game</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
}

body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
height: 100vh;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}

#gameContainer {
width: 100vw;
height: 100vh;
max-width: 400px;
max-height: 711px;
position: relative;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}

#gameCanvas {
width: 100%;
height: 100%;
display: block;
touch-action: none;
}

.particle {
position: absolute;
pointer-events: none;
border-radius: 50%;
animation: particle-burst 1s ease-out forwards;
}

@keyframes particle-burst {
0% {
transform: scale(1) translate(0, 0);
opacity: 1;
}
100% {
transform: scale(0) translate(var(--dx), var(--dy));
opacity: 0;
}
}

@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}

.shake {
animation: shake 0.5s ease-in-out;
}

@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}

.pulse {
animation: pulse 0.3s ease-in-out;
}

#startScreen, #gameOverScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 1000;
}

.screen-title {
font-size: 3em;
font-weight: bold;
margin-bottom: 20px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}

.screen-subtitle {
font-size: 1.2em;
margin-bottom: 30px;
text-align: center;
padding: 0 20px;
}

.btn {
background: linear-gradient(45deg, #ff6b6b, #ff8e8e);
color: white;
border: none;
padding: 15px 30px;
font-size: 1.2em;
border-radius: 25px;
cursor: pointer;
margin: 10px;
min-width: 120px;
min-height: 50px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
}

.btn:hover, .btn:active {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
}

.hidden {
display: none !important;
}
</style>
</head>
<body>
<div id="gameContainer">
<div id="startScreen">
<div class="screen-title">Make 24</div>
<div class="screen-subtitle">Drag numbers and operators to create an
equation that equals 24!</div>
<button class="btn" onclick="startGame()">Start Game</button>
</div>

<div id="gameOverScreen" class="hidden">


<div class="screen-title">Level Complete!</div>
<div class="screen-subtitle" id="gameOverText"></div>
<button class="btn" onclick="nextLevel()">Next Level</button>
<button class="btn" onclick="restartGame()">Restart</button>
</div>

<canvas id="gameCanvas"></canvas>
</div>

<script>
class Make24Game {
constructor() {
[Link] = [Link]('gameCanvas');
[Link] = [Link]('2d');
[Link]();

[Link] = 'start'; // start, playing, gameover


[Link] = 1;
[Link] = 0;
[Link] = 0;
[Link] = 0;

[Link] = null;
[Link] = { x: 0, y: 0 };
[Link] = false;

[Link] = [];
[Link] = ['+', '-', '×', '÷'];
[Link] = [];
[Link] = [];
[Link] = null;

[Link]();
[Link]();
[Link]();
}

setupCanvas() {
const container = [Link]('gameContainer');
const rect = [Link]();

// Maintain 9:16 aspect ratio


[Link] = [Link] * [Link];
[Link] = [Link] * [Link];
[Link] = [Link] + 'px';
[Link] = [Link] + 'px';

[Link]([Link], [Link]);

[Link] = [Link];
[Link] = [Link];
}

setupLevel() {
// Generate random numbers that can make 24
const solutions = [
[1, 1, 8, 3], [1, 2, 3, 4], [1, 3, 4, 6], [1, 4, 5, 6],
[2, 2, 6, 2], [2, 3, 4, 4], [2, 4, 4, 3], [3, 3, 8, 1],
[4, 4, 2, 3], [6, 6, 1, 3], [8, 8, 1, 2], [9, 3, 2, 4]
];

const currentSolution = solutions[([Link] - 1) %


[Link]];
[Link] = [...currentSolution];

// Create draggable number objects


[Link] = [];
for (let i = 0; i < 4; i++) {
[Link]({
value: [Link][i],
x: 60 + (i * 80),
y: 150,
originalX: 60 + (i * 80),
originalY: 150,
width: 60,
height: 60,
isDragging: false,
type: 'number',
inSlot: false,
slotIndex: -1
});
}

// Create operator objects


[Link] = [];
for (let i = 0; i < 4; i++) {
[Link]({
value: [Link][i],
x: 60 + (i * 80),
y: 250,
originalX: 60 + (i * 80),
originalY: 250,
width: 60,
height: 60,
isDragging: false,
type: 'operator',
inSlot: false,
slotIndex: -1
});
}

// Create equation slots (make them smaller and more compact)


[Link] = [];
const slotSize = 40; // Reduced from 44
const startX = 30;
const spacing = 45; // Reduced spacing

for (let i = 0; i < 7; i++) {


[Link]({
x: startX + (i * spacing),
y: [Link] - 110,
width: slotSize,
height: slotSize,
occupied: false,
item: null,
type: i % 2 === 0 ? 'number' : 'operator'
});
}

[Link] = [];
[Link] = null;
[Link] = [Link]();
}

setupEventListeners() {
// Mouse events
[Link]('mousedown', (e) =>
[Link](e, false));
[Link]('mousemove', (e) => [Link](e,
false));
[Link]('mouseup', (e) => [Link](e,
false));

// Touch events
[Link]('touchstart', (e) => {
[Link]();
[Link]([Link][0], true);
});
[Link]('touchmove', (e) => {
[Link]();
[Link]([Link][0], true);
});
[Link]('touchend', (e) => {
[Link]();
[Link]([Link][0], true);
});
}
getEventPos(e) {
const rect = [Link]();
return {
x: [Link] - [Link],
y: [Link] - [Link]
};
}

handleStart(e, isTouch) {
if ([Link] !== 'playing') return;

const pos = [Link](e);


[Link] = isTouch;

// Check numbers
for (let item of [Link]) {
if ([Link](pos, item) && ![Link]) {
if ([Link]) {
[Link](item);
} else {
[Link](item, pos);
}
return;
}
}

// Check operators
for (let item of [Link]) {
if ([Link](pos, item) && ![Link]) {
if ([Link]) {
[Link](item);
} else {
[Link](item, pos);
}
return;
}
}
}

handleSelection(item) {
// Add visual selection feedback
[Link] = ![Link];

// Clear other selections of same type


const allItems = [...[Link], ...[Link]];
[Link](otherItem => {
if (otherItem !== item && [Link] === [Link]) {
[Link] = false;
}
});

// Update selected items array


[Link] = [Link](selectedItem =>
[Link] && selectedItem !== item);

if ([Link]) {
[Link](item);
}
// Check if we have number -> operator -> number pattern
[Link]();

// Haptic feedback
if ([Link]) {
[Link](10);
}
}

checkCalculationPreview() {
// Clear previous preview
[Link] = null;

// Need exactly 3 items: number, operator, number


if ([Link] !== 3) return;

const [first, second, third] = [Link];

// Check pattern: number -> operator -> number


if ([Link] === 'number' && [Link] === 'operator' &&
[Link] === 'number') {
try {
const result = [Link]([Link],
[Link], [Link]);
[Link] = {
value: result,
x: third.x + [Link] + 10,
y: third.y,
targetItem: third
};
} catch (e) {
// Invalid calculation
}
}
}

calculatePreview(num1, operator, num2) {


switch (operator) {
case '+': return num1 + num2;
case '-': return num1 - num2;
case '×': return num1 * num2;
case '÷':
if (num2 === 0) throw new Error('Division by zero');
return num1 / num2;
default: throw new Error('Invalid operator');
}
}

startDrag(item, pos) {
[Link] = item;
[Link] = true;
[Link].x = pos.x - item.x;
[Link].y = pos.y - item.y;

// Remove from slot if it was in one


if ([Link]) {
[Link][[Link]].occupied = false;
[Link][[Link]].item = null;
[Link] = false;
[Link] = -1;
}

// Haptic feedback
if ([Link]) {
[Link](10);
}
}

handleMove(e, isTouch) {
if (![Link] || [Link] !== 'playing' ||
[Link]) return;

const pos = [Link](e);


[Link].x = pos.x - [Link].x;
[Link].y = pos.y - [Link].y;
}

handleEnd(e, isTouch) {
if (![Link] || [Link] !== 'playing' ||
[Link]) return;

const pos = [Link](e);


const item = [Link];

// Check if dropped on equation slot


let droppedOnSlot = false;
for (let i = 0; i < [Link]; i++) {
const slot = [Link][i];
if ([Link](pos, slot) && ![Link] &&
(([Link] === 'number' && [Link] === 'number') ||
([Link] === 'operator' && [Link] === 'operator'))) {

// Snap to slot (adjust size to fit)


item.x = slot.x;
item.y = slot.y;
[Link] = [Link];
[Link] = [Link];
[Link] = true;
[Link] = i;
[Link] = true;
[Link] = item;
droppedOnSlot = true;

// Haptic feedback
if ([Link]) {
[Link](20);
}

break;
}
}

if (!droppedOnSlot) {
// Return to original position and size
item.x = [Link];
item.y = [Link];
[Link] = 60;
[Link] = 60;
}

[Link] = false;
[Link] = null;

// Check if equation is complete


[Link]();
}

isPointInRect(point, rect) {
return point.x >= rect.x && point.x <= rect.x + [Link] &&
point.y >= rect.y && point.y <= rect.y + [Link];
}

checkEquation() {
// Check if all slots are filled
let allFilled = true;
for (let slot of [Link]) {
if (![Link]) {
allFilled = false;
break;
}
}

if (!allFilled) return;

// Build equation string


let equation = '';
for (let slot of [Link]) {
if ([Link] === 'number') {
equation += [Link];
} else {
equation += [Link] === '×' ? '*' :
[Link] === '÷' ? '/' : [Link];
}
}

try {
const result = [Link](equation);
if ([Link](result - 24) < 0.0001) {
[Link]();
} else {
[Link]();
}
} catch (e) {
[Link]();
}
}

evaluateExpression(expr) {
// Simple expression evaluator with proper order of operations
const tokens = [Link](/\d+|\+|\-|\*|\//g);
const numbers = [];
const operators = [];

for (let token of tokens) {


if (!isNaN(token)) {
[Link](parseFloat(token));
} else {
[Link](token);
}
}

// Handle multiplication and division first


for (let i = 0; i < [Link]; i++) {
if (operators[i] === '*' || operators[i] === '/') {
const result = operators[i] === '*' ?
numbers[i] * numbers[i + 1] :
numbers[i] / numbers[i + 1];

[Link](i, 2, result);
[Link](i, 1);
i--;
}
}

// Handle addition and subtraction


let result = numbers[0];
for (let i = 0; i < [Link]; i++) {
if (operators[i] === '+') {
result += numbers[i + 1];
} else if (operators[i] === '-') {
result -= numbers[i + 1];
}
}

return result;
}

levelComplete() {
[Link] = ([Link]() - [Link]) / 1000;
[Link] += [Link](1000 - [Link]([Link] * 10), 100);

// Particle effects
[Link]([Link] / 2, [Link] / 2);

// Haptic feedback
if ([Link]) {
[Link]([100, 50, 100]);
}

setTimeout(() => {
[Link] = 'gameover';
[Link]('gameOverText').textContent =
`Time: ${[Link](1)}s | Score: ${[Link]}`;

[Link]('gameOverScreen').[Link]('hidden');
}, 1000);
}

showError() {
// Shake animation and error feedback
const canvas = [Link]('gameCanvas');
[Link]('shake');
setTimeout(() => [Link]('shake'), 500);

// Clear equation slots


for (let slot of [Link]) {
if ([Link] && [Link]) {
[Link].x = [Link];
[Link].y = [Link];
[Link] = 60; // Reset to original size
[Link] = 60;
[Link] = false;
[Link] = -1;
[Link] = false;
[Link] = null;
}
}

// Haptic feedback
if ([Link]) {
[Link]([50, 50, 50]);
}
}

createParticleExplosion(x, y) {
const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4',
'#feca57'];
const container = [Link]('gameContainer');

for (let i = 0; i < 20; i++) {


const particle = [Link]('div');
[Link] = 'particle';
[Link] = x + 'px';
[Link] = y + 'px';
[Link] =
colors[[Link]([Link]() * [Link])];
[Link] = [Link]() * 8 + 4 + 'px';
[Link] = [Link];

const dx = ([Link]() - 0.5) * 200;


const dy = ([Link]() - 0.5) * 200;
[Link]('--dx', dx + 'px');
[Link]('--dy', dy + 'px');

[Link](particle);

setTimeout(() => {
[Link](particle);
}, 1000);
}
}

draw() {
// Clear canvas
[Link] = 'rgba(255, 255, 255, 0.1)';
[Link](0, 0, [Link], [Link]);

if ([Link] !== 'playing') return;

// Draw header
[Link]();
// Draw numbers
for (let number of [Link]) {
[Link](number, '#4ecdc4');
}

// Draw operators
for (let op of [Link]) {
[Link](op, '#ff6b6b');
}

// Draw equation slots


[Link]();

// Draw calculation preview


[Link]();
}

drawHeader() {
[Link] = 'white';
[Link] = 'bold 24px Arial';
[Link] = 'center';
[Link](`Level ${[Link]}`, [Link] / 2, 40);

[Link] = '18px Arial';


[Link](`Score: ${[Link]}`, [Link] / 4, 70);

const currentTime = ([Link]() - [Link]) / 1000;


[Link](`Time: ${[Link](1)}s`, ([Link] *
3) / 4, 70);

// Target display
[Link] = 'bold 32px Arial';
[Link] = '#feca57';
[Link]('Make 24!', [Link] / 2, 110);
}

drawItem(item, color) {
const x = item.x;
const y = item.y;
const size = [Link];

// Selection highlight
if ([Link]) {
[Link] = 'rgba(255, 255, 255, 0.3)';
[Link]();
if ([Link] === 'number') {
[Link](x + size/2, y + size/2, size/2 + 4, 0, [Link]
* 2);
} else {
[Link](x - 4, y - 4, size + 8, size + 8, 12);
}
[Link]();
}

// Shadow
[Link] = 'rgba(0, 0, 0, 0.2)';
[Link]();
if ([Link] === 'number') {
[Link](x + size/2 + 2, y + size/2 + 2, size/2, 0, [Link]
* 2);
} else {
[Link](x + 2, y + 2, size, size, 8);
}
[Link]();

// Main shape
[Link] = [Link] ?
[Link](color, 20) : color;
[Link]();
if ([Link] === 'number') {
[Link](x + size/2, y + size/2, size/2, 0, [Link] * 2);
} else {
[Link](x, y, size, size, 8);
}
[Link]();

// Border
[Link] = [Link] ?
'rgba(255, 255, 255, 0.8)' : 'rgba(255, 255, 255, 0.3)';
[Link] = [Link] ? 3 : 2;
[Link]();

// Text
[Link] = 'white';
[Link] = 'bold 24px Arial';
[Link] = 'center';
[Link]([Link], x + size/2, y + size/2 + 8);
}

drawEquationArea() {
// Background
[Link] = 'rgba(0, 0, 0, 0.2)';
[Link](10, [Link] - 130, [Link] - 20, 70, 10);
[Link]();

// Equation label
[Link] = 'white';
[Link] = 'bold 14px Arial';
[Link] = 'left';
[Link]('Build equation:', 20, [Link] - 135);

// Draw slots
for (let i = 0; i < [Link]; i++) {
const slot = [Link][i];

[Link] = [Link] ?
'rgba(255, 255, 255, 0.8)' : 'rgba(255, 255, 255, 0.3)';
[Link] = 2;
[Link]([Link] ? [] : [4, 4]);

if ([Link] === 'number') {


[Link]();
[Link](slot.x + [Link]/2, slot.y + [Link]/2,
[Link]/2, 0, [Link] * 2);
[Link]();
} else {
[Link](slot.x, slot.y, [Link], [Link],
6);
[Link]();
}
}

// Draw equals sign and 24 (positioned to fit better)


const lastSlot = [Link][[Link] - 1];
const equalsX = lastSlot.x + [Link] + 15;

[Link] = 'white';
[Link] = 'bold 18px Arial';
[Link] = 'center';
[Link]('=', equalsX, lastSlot.y + [Link]/2 +
6);

// Draw 24 in a circle
const twentyFourX = equalsX + 25;
[Link] = '#feca57';
[Link]();
[Link](twentyFourX, lastSlot.y + [Link]/2, 18, 0,
[Link] * 2);
[Link]();

[Link] = 'rgba(255, 255, 255, 0.8)';


[Link] = 2;
[Link]();

[Link] = 'white';
[Link] = 'bold 16px Arial';
[Link]('24', twentyFourX, lastSlot.y + [Link]/2
+ 5);

[Link]([]);
}

drawCalculationPreview() {
if (![Link]) return;

const preview = [Link];


const radius = 25;

// Preview circle background


[Link] = 'rgba(252, 202, 87, 0.9)';
[Link]();
[Link](preview.x + radius, preview.y + radius, radius, 0,
[Link] * 2);
[Link]();

// Border
[Link] = 'rgba(255, 255, 255, 0.8)';
[Link] = 2;
[Link]();

// Result text
[Link] = 'white';
[Link] = 'bold 16px Arial';
[Link] = 'center';
const displayValue = [Link]([Link]) ?
[Link]() : [Link](1);
[Link](displayValue, preview.x + radius, preview.y +
radius + 5);

// Connection line
[Link] = 'rgba(252, 202, 87, 0.6)';
[Link] = 2;
[Link]([5, 5]);
[Link]();
[Link]([Link].x + [Link],
[Link].y + [Link]/2);
[Link](preview.x, preview.y + radius);
[Link]();
[Link]([]);
}

lightenColor(color, percent) {
const num = parseInt([Link]("#",""), 16);
const amt = [Link](2.55 * percent);
const R = (num >> 16) + amt;
const G = (num >> 8 & 0x00FF) + amt;
const B = (num & 0x0000FF) + amt;
return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000
+
(G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
(B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
}

gameLoop() {
[Link]();
requestAnimationFrame(() => [Link]());
}
}

// Polyfill for roundRect


if (![Link]) {
[Link] = function(x, y, width,
height, radius) {
[Link]();
[Link](x + radius, y);
[Link](x + width - radius, y);
[Link](x + width, y, x + width, y + radius);
[Link](x + width, y + height - radius);
[Link](x + width, y + height, x + width - radius, y
+ height);
[Link](x + radius, y + height);
[Link](x, y + height, x, y + height - radius);
[Link](x, y + radius);
[Link](x, y, x + radius, y);
};
}

let game;

function startGame() {
[Link]('startScreen').[Link]('hidden');
game = new Make24Game();
[Link] = 'playing';
}

function nextLevel() {
[Link]('gameOverScreen').[Link]('hidden');
[Link]++;
[Link]();
[Link] = 'playing';
}

function restartGame() {
[Link]('gameOverScreen').[Link]('hidden');
[Link] = 1;
[Link] = 0;
[Link]();
[Link] = 'playing';
}

// Handle window resize


[Link]('resize', () => {
if (game) {
[Link]();
}
});
</script>
</body>
</html>

Common questions

Powered by AI

The "Make 24" game maintains user engagement by introducing new levels with different sets of numbers that can result in 24, providing a consistent challenge. The game's scoring system adds competitiveness by rewarding faster calculations. Visuals such as animations and color schemes, coupled with interactive feedback such as haptic responses, engage users across different levels. Additionally, the game dynamically updates as levels progress, keeping players invested through increasing complexity .

The game provides visual feedback with a selection highlight and animations such as particle bursts on level completion. Interactive feedback includes haptic feedback for selection and drag actions, and a shake animation is used when errors occur. These visual and haptic cues are designed to guide the player's actions by offering immediate visual and tactile responses to their interactions .

The game uses several strategies to prevent errors in equation formation. It checks if the selected items follow a valid 'number -> operator -> number' pattern before calculating a preview of the result. The calculation is only attempted if this pattern is met. Furthermore, the game attempts to ensure that numbers and operators are correctly dragged and placed into appropriate slots, thus minimizing input errors before calculations are attempted .

The "Make 24" game incorporates user touch interactions by handling touch events like 'touchstart', 'touchmove', and 'touchend'. These events are used to manage the dragging and selection of numbers and operators, which are then used to form equations. When a player selects an item via touch, it visually highlights the item and provides haptic feedback if supported by the device, enhancing the user experience by adding a tactile layer of interaction .

The game adapts its challenges by varying the combinations of numbers on each level that can be used to make 24. Each level presents a unique solution set, requiring different mathematical approaches and strategies. This variation ensures that players encounter new challenges continually, maintaining engagement and increasing the complexity as they progress through the levels .

Visual design plays a significant role in enhancing player experience by creating an immersive and aesthetically pleasing interface. The game uses gradients, animations like particle effects, and a consistent color palette to maintain engagement. Visual design elements enhance gameplay by providing important interactive signals, like highlighting selected items and shaking animation for errors, which helps players understand their mistakes and correct their solutions .

The game design ensures that users understand the rules and objectives quickly by providing a simple, clear start screen that explains the main goal: to create an equation that equals 24 using provided numbers and operators. The interface is intuitive, with draggable numbers and operators, immediate feedback on actions, and clear visual cues that all contribute to a quick understanding of game mechanics .

Haptic feedback influences user interaction by providing physical sensations that complement visual cues, making interactions more immersive. In "Make 24," vibration feedback occurs during selections and successful placements, creating a tactile reinforcement that enhances user satisfaction and guides correct actions. This multimodal feedback ensures players receive immediate response to their input, increasing engagement and ensuring intuitive gameplay .

Timing and scoring mechanics add challenge and replayability by encouraging players to complete equations quickly for higher scores, as the scoring system is inversely proportional to time spent. Faster solutions lead to higher scores, enticing players to replay levels for better outcomes. This timed element, combined with the score-based incentives, enhances the competitive aspect, enticing players to refine their strategies and speed in equation solving .

Mathematical processing in "Make 24" involves evaluating expressions with the correct order of operations to ensure accurate outcomes. The game's algorithm parses and computes expressions by prioritizing multiplication and division before addition and subtraction. This processing is critical as it affects the correctness of the player's solutions, thereby impacting their ability to proceed and complete levels successfully .

You might also like