diff --git a/backend/src/types.d.ts b/backend/src/types.d.ts index 0ac9c89..a5b2c1f 100644 --- a/backend/src/types.d.ts +++ b/backend/src/types.d.ts @@ -1,9 +1,6 @@ -// We declare those types which are used throughout the application here. -// For types that are used only in one file, we can declare them in that file itself. - type CardType = 'number' | 'special' | 'wild'; -type CardColor = 'red' | 'blue' | 'green' | 'yellow'; +type CardColor = 'red' | 'blue' | 'green' | 'yellow' | 'wild'; type SpecialCardNames = 'skip' | 'reverse' | 'draw2' | 'draw4' | 'colchange'; type CardNumbers = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; @@ -27,10 +24,6 @@ type EventResult = { message: string; }; -declare global { - type GameEngine = import('./engine').GameEngine; -} - type GameEventType = 'DRAW_CARD' | 'THROW_CARD'; type GameEvent = diff --git a/backend/tests/deck.test.ts b/backend/tests/deck.test.ts index d54e7b3..efc6dd4 100644 --- a/backend/tests/deck.test.ts +++ b/backend/tests/deck.test.ts @@ -1,9 +1,45 @@ -import { shuffle, makeCard } from '../uno-game-engine/deck'; +import { + getShuffledCardDeck, + makeCard, + shuffle, +} from '../uno-game-engine/deck'; describe('testing deck.ts', () => { test('makeCard', () => { const card = makeCard('number', 'blue', '3'); expect(card.color).toBe('blue'); }); + test('getShuffledDeck', () => { + const deck = getShuffledCardDeck(); + console.log(deck); + }); +}); +test('validateDeckComposition', () => { + const deck = getShuffledCardDeck(); + + const colorCount = { red: 0, yellow: 0, green: 0, blue: 0 }; + const wildCount = { wild: 0 }; + let totalCards = 0; + + for (const card of deck) { + if (card.color in colorCount) { + colorCount[card.color]++; + } else if (card.color === 'wild') { + wildCount.wild++; + } + totalCards++; + } + + // Verify total number of cards + expect(totalCards).toBe(108); + + // Verify number of cards of each color + expect(colorCount.red).toBe(25); + expect(colorCount.yellow).toBe(25); + expect(colorCount.green).toBe(25); + expect(colorCount.blue).toBe(25); + + // Verify number of wild cards + expect(wildCount.wild).toBe(8); }); describe('shuffle function', () => { test('should change order of elements', () => { diff --git a/backend/uno-game-engine/deck.ts b/backend/uno-game-engine/deck.ts index 8a6c19e..f1c62ca 100644 --- a/backend/uno-game-engine/deck.ts +++ b/backend/uno-game-engine/deck.ts @@ -1,5 +1,6 @@ -const colors: Array = ['red', 'yellow', 'green', 'blue']; -const values = [ +const colors: CardColor[] = ['red', 'green', 'blue', 'yellow']; + +const values: CardValue[] = [ '0', '1', '2', @@ -14,40 +15,57 @@ const values = [ 'reverse', 'draw2', ]; -const specialCards = ['wild', 'draw4']; -const deck = []; -const sameCardCount = []; // to keep track of same cards in assigning unique id to each card -/** - * In a standard UNO deck, there are 108 cards. Here's the breakdown: +const specialCards: CardValue[] = ['colchange', 'draw4']; +const sameCardCount = []; +/** +* In a standard UNO deck, there are 108 cards. Here's the breakdown: - colors: These are the four colors of the cards in the deck: red, yellow, green, and blue. -- values: These are the values that can be on the cards. Each color has one '0' card and - two of each of the other number cards ('1' through '9'). - Each color also has two 'skip', 'reverse', and 'draw2' cards. +- values: These are the values that can be on the cards. Each color has one '0' card and +two of each of the other number cards ('1' through '9'). +Each color also has two 'skip', 'reverse', and 'draw2' cards. - specialCards: These are the black cards that can be played on any color. - There are four 'wild' cards that allow the player to choose the color that - continues play, and four 'draw4' cards that act like 'wild' cards but also - force the next player to draw four cards. +There are four 'wild' cards that allow the player to choose the color that +continues play, and four 'draw4' cards that act like 'wild' cards but also +force the next player to draw four cards. - So, in total, for each color there are 19 number cards, 2 'skip' cards, - 2 'reverse' cards, and 2 'draw2' cards, which makes 25 cards per color. - Multiply that by 4 (for the four colors) and add the 8 special cards, - and you get 108 cards. +So, in total, for each color there are 19 number cards, 2 'skip' cards, +2 'reverse' cards, and 2 'draw2' cards, which makes 25 cards per color. +Multiply that by 4 (for the four colors) and add the 8 special cards, +and you get 108 cards. - This function returns a shuffled deck of 108 UNO cards. Each card is an object with a color and a value. - The function makeCard is used to make the card objects. - @returns {Array} deck - An array of 108 UNO cards. - */ +This function returns a shuffled deck of 108 UNO cards. Each card is an object with a color and a value. +The function makeCard is used to make the card objects. +@returns {Array} deck - An array of 108 UNO cards. +*/ export function getShuffledCardDeck(): Array { - const deck = []; - // todo: Implement the card generation logic - // dummy code: - // deck.push(makeCard('special', 'wild', 'wild')) - // deck.push(makeCard('number', 'red', '0')) + const deck: Array = []; + + for (let col of colors) { + for (let val of values) { + if (!isNaN(Number(val))) { + for (let i = 0; i < 2; i++) { + deck.push(makeCard('number', col, val)); + if (val === '0') break; + } + } else { + for (let i = 0; i < 2; i++) { + deck.push(makeCard('special', col, val)); + } + } + } + } + // generating special cards + for (let sc of specialCards) { + for (let i = 0; i < 4; i++) { + deck.push(makeCard('wild', 'wild', sc)); + } + } + // shuffling the deck shuffle(deck); return deck; } @@ -66,6 +84,13 @@ export function makeCard( if (!sameCardCount[id]) sameCardCount[id] = 0; sameCardCount[id]++; // increment the count of same cards to assign unique id + const uid = `${id}-${sameCardCount[id]}`; + return { type, color, value, id: uid }; + const id = `card-${type}-${color}-${value}`; + + if (!sameCardCount[id]) sameCardCount[id] = 0; + sameCardCount[id]++; // increment the count of same cards to assign unique id + const uid = `${id}-${sameCardCount[id]}`; return { type, color, value, id: uid }; } @@ -80,4 +105,10 @@ export function shuffle(deck: Array) { const j = Math.floor(Math.random() * i); [deck[i], deck[j]] = [deck[j], deck[i]]; } +export function shuffle(deck: Array) { + // Fisher-Yates shuffle algorithm to shuffle card deck + for (let i = deck.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * i); + [deck[i], deck[j]] = [deck[j], deck[i]]; + } }