Skip to content

Commit

Permalink
server : Added wild into the CardColors
Browse files Browse the repository at this point in the history
 Added wild color for wild cards like colchange and draw4 cards

 these changes are made in types.d.ts
  • Loading branch information
kuv2707 authored and Abhishek committed Jun 2, 2024
1 parent 57413d6 commit 9cc34c4
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 43 deletions.
8 changes: 7 additions & 1 deletion backend/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
},
"plugins": ["@typescript-eslint"],
"rules": {
"indent": ["error", 4],
"indent": [
"error",
4,
{
"SwitchCase": 1
}
],
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
Expand Down
2 changes: 1 addition & 1 deletion backend/.prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"endOfLine": "crlf"
"endOfLine": "lf"
}
18 changes: 18 additions & 0 deletions backend/eventRecipients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// this module is responsible for handling the clients currently connected to the server.
// It stores the clients in a Map object, where the key is the client's user_id and the value is the client's http response object.

import { Response } from 'express';

const clients = new Map<string, Response>();

export function addClient(userId: string, res: Response) {
clients.set(userId, res);
}

export function removeClient(userId: string) {
clients.delete(userId);
}

export function getClient(userId: string) {
return clients.get(userId);
}
10 changes: 10 additions & 0 deletions backend/routes/gameRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import express from 'express';
import { addClient } from '../eventRecipients';
const router = express.Router();

router.get('/events', (req, res) => {
addClient('user_id', res);
});

// the post handler should retrieve the game the user is currently in, and update the game state.
// The request body contains the event data, as described in ARCHITECTURE.md
11 changes: 2 additions & 9 deletions backend/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -14,7 +11,7 @@ type UNOCard = {
type: CardType;
color: CardColor;
value: CardValue;
id: undefined;
id: string;
};

type Player = {
Expand All @@ -27,10 +24,6 @@ type EventResult = {
message: string;
};

declare global {
type GameEngine = import('./engine').GameEngine;
}

type GameEventType = 'DRAW_CARD' | 'THROW_CARD';

type GameEvent =
Expand Down
23 changes: 22 additions & 1 deletion backend/tests/deck.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import { makeCard } from '../uno-game-engine/deck';
import { shuffle, makeCard } from '../uno-game-engine/deck';
describe('testing deck.ts', () => {
test('makeCard', () => {
const card = makeCard('number', 'blue', '3');
expect(card.color).toBe('blue');
});
});
describe('shuffle function', () => {
test('should change order of elements', () => {
// Create a mock deck
const deck = [
makeCard('number', 'red', '1'),
makeCard('number', 'blue', '2'),
makeCard('number', 'red', '1'),
makeCard('number', 'yellow', '1'),
];

// Create a copy of the deck for comparison
const originalDeck = [...deck];
shuffle(deck);

// Check that the order of elements has changed
const orderChanged = deck.some(
(card, index) => card !== originalDeck[index]
);
expect(orderChanged).toBe(true);
});
});
88 changes: 57 additions & 31 deletions backend/uno-game-engine/deck.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const colors: Array<CardColor> = ['red', 'yellow', 'green', 'blue'];
const values = [
const colors: CardColor[] = ['red', 'green', 'blue', 'yellow'];

const values: CardValue[] = [
'0',
'1',
'2',
Expand All @@ -14,39 +15,56 @@ const values = [
'reverse',
'draw2',
];
const specialCards = ['wild', 'draw4'];
const deck = [];

/**
* 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<UNOCard> {
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<UNOCard> = [];

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;
}
Expand All @@ -60,15 +78,23 @@ export function makeCard(
color: CardColor,
value: CardValue
): UNOCard {
//todo: Implement unique identification of cards by assigning an id to each card
return { type, color, value, id: undefined };
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 };
}

/**
* This function shuffles the elements of the given array *in place* . The function behaves in a type-agnostic way.
* Time complexity: O(n)
*/
export function shuffle(deck: Array<any>) {
//todo: Implement a generic shuffling algorithm
[deck[0], deck[1]] = [deck[1], deck[0]];
export function shuffle(deck: Array<UNOCard>) {
// 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]];
}
}
5 changes: 5 additions & 0 deletions backend/uno-game-engine/engine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getShuffledCardDeck } from './deck';
import { handleEvent } from './gameEvents';

const NUM_CARDS_PER_PLAYER = 7;

Expand Down Expand Up @@ -52,4 +53,8 @@ export class GameEngine {
.find((p: Player) => p.id === player.id)
.cards.push(this.cardDeck.pop());
}
dispatchEvent(event: GameEvent) {
// handle different types of events based on event.type
handleEvent(this, event);
}
}
22 changes: 22 additions & 0 deletions backend/uno-game-engine/gameEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// this module houses the handlers for various game events.

import { type GameEngine } from './engine';

type GameEventHandler = (game: GameEngine, event: GameEvent) => EventResult;

const map = new Map<GameEventType, GameEventHandler>();

export function registerEventHandler(
eventType: GameEventType,
handler: GameEventHandler
) {
map.set(eventType, handler);
}

export function handleEvent(game: GameEngine, event: GameEvent): EventResult {
const handler = map.get(event.type);
if (!handler) {
return { type: 'ERROR', message: 'Invalid event type' };
}
return handler(game, event);
}

0 comments on commit 9cc34c4

Please sign in to comment.