Skip to content

Commit

Permalink
Merge pull request #3 from vmolero/develop
Browse files Browse the repository at this point in the history
Add all the minimum functionality as original game
  • Loading branch information
vmolero authored Mar 9, 2018
2 parents 1ba8740 + c006b64 commit 416b31d
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 62 deletions.
12 changes: 8 additions & 4 deletions src/CardDeck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export default class CardDeck {
public readonly RANKS = 13;
private deck: Array<Card>;

public get cards(): Array<Card> {
return this.deck;
}

public static createStandard52CardDeck() {
let deck: Array<Card> = new Array<Card>();
for (let suit: Suit = Suit.Clubs; suit <= Suit.Diamonds; suit++) {
Expand All @@ -14,23 +18,23 @@ export default class CardDeck {
}
}

return new CardDeck(deck);
return this.shuffle(new CardDeck(deck));
}

/**
* Fisher-Yates shuffle algorithm
*
* @see https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
*/
public shuffle() {
public static shuffle(deck: CardDeck) {
let randomizedDeck: Array<Card> = [];
let array: Array<Card> = this.deck.slice();
let array: Array<Card> = deck.cards.slice();
while (array.length !== 0) {
let rIndex = Math.floor(array.length * Math.random());
randomizedDeck.push(array[rIndex]);
array.splice(rIndex, 1);
}
this.deck = randomizedDeck;
return new CardDeck(randomizedDeck);
}

public getLength(): number {
Expand Down
1 change: 0 additions & 1 deletion src/Deal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export default class Deal {

public constructor(cardDeck?: CardDeck) {
this.cardDeck = cardDeck || CardDeck.createStandard52CardDeck();
this.cardDeck.shuffle();
}

public pullCard(): Card {
Expand Down
26 changes: 0 additions & 26 deletions src/SimpleBlackJack.tsx

This file was deleted.

114 changes: 99 additions & 15 deletions src/components/BoardComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,69 @@ import * as React from 'react';
import DealComponent from './DealComponent';
import Board from '../Board';

interface BoardStateInterface {
export interface BoardStateInterface {
board: Board;
handNumber: number;
playerScore: number;
houseScore: number;
btnDealerClass: string;
btnPlayerClass: string;
btnHitClass: string;
btnStandClass: string;
message: string;
}

export default class BoardComponent extends React.Component<{}, BoardStateInterface> {
interface BoardPropsInterface {
jsonState: JsonStateInterface;
onSaveGameClick: Function;
onResetGameClick: Function;
}

export interface JsonStateInterface {
handNumber: number;
playerScore: number;
houseScore: number;
}

export class BoardComponent extends React.Component<BoardPropsInterface, BoardStateInterface> {

constructor(props: {}) {
constructor(props: BoardPropsInterface) {
super(props);
this.state = {
this.state = this.resetState();
if (Object.keys(this.props.jsonState).length > 0 &&
this.props.jsonState.constructor === Object) {
try {
this.state = this.fromSavedState(this.props.jsonState);
} catch (invalidJson) {
alert('Cannot parse json');
}
}
}

public fromSavedState(stateObject: JsonStateInterface): BoardStateInterface {
let state: BoardStateInterface = {
board: Board.newGame(),
handNumber: stateObject.handNumber,
playerScore: stateObject.playerScore,
houseScore: stateObject.houseScore,
btnDealerClass: '',
btnHitClass: 'invisible',
btnStandClass: 'invisible',
message: 'Welcome to vmolero\'s BlackJack Game. Press \'Deal!\' to start playing.'
};

return state;
}

public resetState(): BoardStateInterface {
return {
board: Board.newGame(),
handNumber: 0,
playerScore: 0,
houseScore: 0,
btnDealerClass: '',
btnPlayerClass: 'invisible'
btnHitClass: 'invisible',
btnStandClass: 'invisible',
message: 'Welcome to vmolero\'s BlackJack Game. Press \'Deal!\' to start playing.'
};
}

Expand All @@ -31,7 +74,9 @@ export default class BoardComponent extends React.Component<{}, BoardStateInterf
board: this.state.board.newDeal(),
handNumber: this.state.handNumber + 1,
btnDealerClass: 'invisible',
btnPlayerClass: ''
btnHitClass: '',
btnStandClass: '',
message: 'Game ON!'
}
);
}
Expand All @@ -42,23 +87,51 @@ export default class BoardComponent extends React.Component<{}, BoardStateInterf
this.setNewState(newState);
}

public handleStandClick() {
public sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

public async handleStandClick() {
let newState: BoardStateInterface = this.state;
let board: Board = this.state.board;
newState.btnHitClass = 'invisible';
this.setNewState(newState);
while (!board.isGameOver()) {
board = board.dealHouse();
newState.board = board;
this.setNewState(newState);
await this.sleep(1000);
}
}

public handleSaveGame() {
return this.props.onSaveGameClick(this.state);
}

public handleResetGame() {
if (confirm('Are you sure?')) {
this.setState(this.resetState());
return this.props.onResetGameClick();
}
newState.board = board;
this.setNewState(newState);
}

public render() {
return (
<div id="table">
<aside id="subheader">
<div id="localstoragebuttons">
<input type="button" id="btnSave" value="Save globals" />
<input type="button" id="btnReset" value="Reset Counters" />
<input
type="button"
id="btnSave"
value="Save globals"
onClick={() => this.handleSaveGame()}
/>
<input
type="button"
id="btnReset"
value="Reset Counters"
onClick={() => this.handleResetGame()}
/>
</div>
<div id="globalinfopanel">
<p>
Expand All @@ -74,11 +147,19 @@ export default class BoardComponent extends React.Component<{}, BoardStateInterf
<DealComponent
board={this.state.board}
btnDealerClass={this.state.btnDealerClass}
btnPlayerClass={this.state.btnPlayerClass}
btnHitClass={this.state.btnHitClass}
btnStandClass={this.state.btnStandClass}
onDealClick={() => this.handleDealClick()}
onHitClick={() => this.handleHitClick()}
onStandClick={() => this.handleStandClick()}
/>
/>
<footer id="footer">
<div id="gameinfo">
<p id="txtMessage">
{this.state.message}
</p>
</div>
</footer>
</div>
);
}
Expand All @@ -87,11 +168,14 @@ export default class BoardComponent extends React.Component<{}, BoardStateInterf
if (newState.board.isGameOver()) {
if (newState.board.isHouseWinning()) {
newState.houseScore += 1;
newState.message = 'Aww, you lose, press \'Deal!\' to play another hand.';
} else {
newState.playerScore += 1;
newState.message = 'YOU WIN !! Press \'Deal!\' to play another hand.';
}
newState.btnDealerClass = '';
newState.btnPlayerClass = 'invisible';
newState.btnHitClass = 'invisible';
newState.btnStandClass = 'invisible';
}
this.setState(newState);
}
Expand Down
9 changes: 4 additions & 5 deletions src/components/DealComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import Board from '../Board';
interface DealPropsInterface {
board: Board;
btnDealerClass: string;
btnPlayerClass: string;
btnHitClass: string;
btnStandClass: string;
onDealClick: Function;
onHitClick: Function;
onStandClick: Function;
Expand All @@ -14,10 +15,8 @@ interface DealPropsInterface {
export default class DealComponent extends React.Component<DealPropsInterface> {
public render() {
let board: Board = this.props.board;
let gameOver: string = board.isGameOver() ? 'Deal Over' : 'Deal On';
return (
<div id="gamezone">
<div>{gameOver}</div>
<div id="gamebuttons">
<span id="playeramount"><span id="player">{board.getPlayerScore()}</span> </span>
<input
Expand All @@ -28,14 +27,14 @@ export default class DealComponent extends React.Component<DealPropsInterface> {
onClick={() => this.props.onDealClick()}
/>
<input
className={this.props.btnPlayerClass}
className={this.props.btnHitClass}
type="button"
id="btnHit"
value="Hit"
onClick={() => this.props.onHitClick()}
/>
<input
className={this.props.btnPlayerClass}
className={this.props.btnStandClass}
type="button"
id="btnStand"
value="Stand"
Expand Down
72 changes: 72 additions & 0 deletions src/components/SimpleBlackJack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import * as React from 'react';
import { BoardComponent, BoardStateInterface, JsonStateInterface } from './BoardComponent';

class SimpleBlackJack extends React.Component {
private readonly KEY: string = 'blackjack';

setItem(key: string, data: string) {
localStorage.setItem(key, data);
}

getItem(key: string): JsonStateInterface {
const jsonState: string | null = localStorage.getItem(key);
if (jsonState !== null) {
return JSON.parse(jsonState);
}
return {
handNumber: 0,
playerScore: 0,
houseScore: 0,
};
}

saveGame(state: BoardStateInterface) {
let jsonSate: JsonStateInterface = {
handNumber: state.handNumber,
playerScore: state.playerScore,
houseScore: state.houseScore,
};
this.setItem(this.KEY, JSON.stringify(jsonSate));
}

loadGame(): JsonStateInterface {
return this.getItem(this.KEY);
}

handleSaveGame(state: BoardStateInterface): boolean {
try {
this.saveGame(state);
} catch (errorOnSave) {
return false;
}
return true;
}

handleResetGame(): boolean {
try {
localStorage.clear();
} catch (errorOnSave) {
return false;
}
return true;
}

render() {
return (
<div className="container">
<header id="header">
<h1>
<span>simple</span>BlackJack
</h1>
</header>
<BoardComponent
jsonState={this.loadGame()}
onSaveGameClick={(state: BoardStateInterface) => this.handleSaveGame(state)}
onResetGameClick={() => this.handleResetGame()}
/>
</div>
);
}
}

export default SimpleBlackJack;
4 changes: 2 additions & 2 deletions src/css/enhanced.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
@media all and (min-width: 600px)
{
#player:before {
content: "Player ";
content: "You ";
}

#bank:after {
content: " Dealer";
content: " House";
}

#table {
Expand Down
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import SimpleBlackJack from './SimpleBlackJack';
import SimpleBlackJack from './components/SimpleBlackJack';
import registerServiceWorker from './registerServiceWorker';
import './css/base.css';
import './css/enhanced.css';
Expand Down
Loading

0 comments on commit 416b31d

Please sign in to comment.