Code Monkey home page Code Monkey logo

blackjack's People

Contributors

codegard1 avatar dependabot[bot] avatar ramsagit avatar

Watchers

 avatar

blackjack's Issues

Implement Flux for all Game state methods

Move all Game state methods to GameStore, but do not call them in Components yet.

For each method in the below list, do:

  • create constant in AppConstants
  • create action creator in AppActions
  • port method from Table to GameStore
  • add method reference to AppDispatcher.register()
  • port state variables from Table to GameStore

Game state methods

  • _showMessageBar
  • _evaluateHand
  • _evaluateGame
  • _newPlayer
  • _newGame
  • _getPlayerById
  • _getHighestHandValue
  • _payout
  • _evaluatePlayers
  • _resetGame
  • _newRound
  • _hideOptionsPane

Hit causes the app to crash

Clicking the Hit button in CommandBar causes the following error:

TypeError: __WEBPACK_IMPORTED_MODULE_3__DeckStore__.a.draw is not a function
_hit
C:\Users\n5014\Documents\git\blackjack\src\stores\GameStore.js:425
  422 | 
  423 | function _hit(ev, target, index = currentPlayer) {
  424 |   /* todo: fix this so that the call goes directly to DeckStore from Table */
> 425 |   const ret = DeckStore.draw(1);
  426 |   players[index].hand.push(ret);
  427 | 
  428 |   _evaluateGame(1);

wire up _reset

Update components to use GameStore _reset

  • OptionsPanel
  • Player
  • Table

Hand class

Create a new Class PlayerHand and privately implement evaluating methods

Implement

class PlayerHand {
  constructor ( playerId ) {
    this.id = id
    this.value = { aceAsTen: 0, aceAsEleven: 0 }
    this.cards = [ ]
  }
  evaluate ( ) {
    // determine value based on current cards
    return this.value
  }
}

Implement "New Game" menu

Create a menu of game options on a Panel. Include

  • New Game
  • Deck Display options (remove from CommandBar
  • Restart Game

Implement New Game as an action to test

Implement the New Game method from Table as a way to test if Flux is working correctly

  • Add GAME_NEWGAME to AppConstants
  • Implement newGame handler in AppActions
  • Implement _newGame in GameStore
  • Import GameStore to Table
  • Import AppActions to Table
  • Add method _onNewGame to Table to pass params to AppActions.deal()
  • Bind _onNewGame to Table

Migrate Game methods from Table to GameStore

Move all deck methods out of Table and into DeckStore

For each method:

  • add key to AppConstants

  • add action in AppActions

  • register action with dispatcher in Store

  • add method definition to Store

  • refactor method definition in store

  • update reference in Table

  • clearHand

  • resetGame

  • newRound

  • deal

  • hit

  • stay

  • getHighestHandValue

  • evaluateGame

  • endGameTrap

  • evaluatePlayers

  • bet

  • ante

  • payout

Implement NewPlayer to test Flux

Implement _newPlayer in GameStore as a second test that Flux is working properly

  • add constant GAME_NEWPLAYER in AppConstants
  • implement newPlayer handler in AppActions
  • implement _newPlayer in GameStore
  • add method _onNewPlayer in Table to pass params to AppActions.newPlayer()
  • bind _onNewPlayer to Table

Subscribe Table to listen for changes from GameStore

Subscribe Table to listen for onChange events from GameStore.

  • Use GameStore to set Table's state
  • Use the following as a model
componentDidMount: () {
        GameStore.addChangeListener(this.onChange);
    }
    componentWillUnmount () {
        GameStore.removeChangeListener(this.onChange);
    }
    onChange: function () {
        this.setState({
            Players: GameStore.getAllPlayers(),
            // etc.
        });
    }
    getInitialState: function () {
        return {
            Players: GameStore.getAll(),
            // etc.
        };
    },

Award money to winner at the end of each round

In _exitTrap(), evaluate whether any player is the winner of the round, and award that player the pot.

Once a winner is determined, run _evaluateGame() with the appropriate status code to end the game.

Determining a winner after each action:

  • If all players but one are busted, that player is the winner
    • if that player has BlackJack then evaluate status 5
  • if not all players are busted, compare handValue of each player
    • whichever player has the highest handValue is the winner
    • if the winning player is id 0 (human player) then evaluate status 3
  • if the human player (id 0) is busted and the Dealer (id 1) is not, evaluate status 4
  • if all non-busted players have the same handValue, the human player (id 0) wins
    • evaluate status 3

Refactor to BaseComponent

Re: Refactoring React Components to ES6 Classes

Implement BaseComponent globally:

  • create BaseComponent.js as in the example (see below) 7a42ac7
  • import BaseComponent into all existing components that use private methods 2e3731d
    • CardContainer
    • DeckContainer
    • Table
  • set components to extend BaseComponent f58636e
    • CardContainer
    • DeckContainer
    • Table
  • implement constructor() for each component and include a call to _bind(), passing all private method names (for Table this is going to be a very long list) 8592a47
    • CardContainer
    • DeckContainer
    • Table

Example:

class BaseComponent extends React.Component {
_bind(...methods) {
methods.forEach( (method) => this[method] = this[method].bind(this) );
}
}

class ExampleComponent extends BaseComponent {
constructor() {
super();
this._bind('_handleClick', '_handleFoo');
}
// ...
}

Implement Betting mechanism per player

Each player has a bank prop that is the amount of money they have left to play with.

  • Each time _bet() is called, subtract the bet amount from player's bank and add it to Table state's pot
  • When a new round starts, automatically 'bet' for each player (_ante())
  • notify the player when _ante()occurs
  • Replace the New Game option in CommandBar with "New Round"
  • add roundCount to Table state
  • increment roundCount like turnCount, but don't reset turnCount when _resetGame() is called

Implement StatusPanel as a Callout

Instead of framing the StatusPanel in a plain

under each Player's ControlBar, implement a a callout that appears when an icon/link after the Player's name is clicked

Add Bet button to CommandBar

Implement a Bet button in the CommandBar:

  • add handler method _bet() to Table & bind it
  • add _bet() to controlPanelMethods
  • add reference in blackJackItems
  • create bettingDisplay in DeckContainer
  • indicate amount of current bet on Bet button
  • add minimumBet: 25 to Table state, set that as default value for _bet()

_bet( amount ) { this.setState({ pot: pot + amount )};

const bettingDisplay = () => { return <span>{ $ ${this.props.pot} }</span>; }

Implement currentplayer as a property of Players class

Treat Players more as a single module by implementing a Players class to hold and manipulate individual Player objects

?? Should this be re-cast as a Store? (Probably)

class Players {
  constructor {
    this.players = [ ]
    this.currentPlayer = -1
    this.stayingPlayers = [ ]
    this.bustedPlayers = [ ] 
 }

nextPlayer () {
  this.currentPlayer = this.currentPlayer +1 > this.players.length ? 0 : this.currentPlayer + 1
  this.players.forEach( (player, index) => { player.turn = index === this.currentPlayer } )
}

newPlayer (title) {
  this.players.push( new Player(title) );
}

resetPlayer ( id, ...keys ) {
  // pass names of keys to reset to Player.reset( ...keys )
}
//etc. 

Caveats:

  • newPlayer and reset are already being handled by existing App Actions; these methods and their dependencies will need to be re-routed into the Players object, which should really be a Store
  • Since each player's Deck is stored in DeckStore, it may also be necessary to re-wire any methods that interact with both players and their decks
  • There is already a Component called Player, and it is terminologically confusing to have both in the same project when they have totally different functions. Again, this should be a Store and not just a class

Fix 'aceAsTen' typo

the variable aceAsTen is a typo. Change it to aceAsEleven across all files

Create DeckStore

Create DeckStore and add the following state variables to it:

  • deck
  • selected
  • drawn

as well as getter methods described in #19

getter methods for Stores

Determine what getters to implement in gameStore

All of Table's children can still use the same props they're using now if all of Table's state is retrieved from stores, and Table can update itself every time an App Action causes a change to a variable in GameStore.

The question is: when to use App Actions and when to use GameStore methods? And how to organize the state in GameStore?

From what I understand, in flux you get state from the store only in container components, which then pass their state down to children as props. Children can then use App Actions to indirectly modify state, which cascades back down to them from the top.

Table contains everything so it is a good place to start. On mounting, Table should get its state according to the three domains I've already decided on: Game, ControlPanel, and Deck. All actions belong to one of the three domains, and ideally no action should use props from a domain to which it does not belong.

How to determine if a getter is necessary: when a container component needs to have certain state variables available from the time at it mounts, that is a good opportunity to fetch from the stores. App Actions, by contrast, are ad hoc setters and should not be implemented inside the stores themselves.

GameStore

  • getPlayers
    • returns an array of all Player records
  • getPlayer( Id )
    • returns a single player record
  • getState
    • returns an object containing state variables such as isOptionsPanelVisible, MessageBar text & type, etc.

ControlStore

  • getState
    • returns a collection of state variables such as deck visibility

DeckStore

  • getSelected
    • returns an array of selected cards from the store
  • getDrawn
    • returns an array of drawn cards from the store
  • getDeck
    • returns a fresh deck from Shuffle

Migrate deck methods from Table to DeckStore

Move all deck methods out of Table and into DeckStore

For each method:

  • add key to AppConstants

  • add action in AppActions

  • register action with dispatcher in Store

  • add method definition to Store

  • refactor method definition in store

  • update reference in Table

  • draw

  • drawRandom

  • drawFromBottomOfDeck

  • reset

  • shuffle

  • putOnBottomOfDeck

  • putOnTopOfDeck

  • select

  • deselect

End round after all players have stayed

If all players stay (status code 2) then the round ends and a winner is determined.

  • Each time _evaluateGame(2) is called, check if all players have stayed
    • if not then update currentPlayer and set player.turn for the next player
      • also add the id of the player who last stayed to state.stayedPlayers before updating currentPlayer and player.turn
    • if so then a check function in exitTrap will catch the situation and evaluate the appropriate status code depending on who the winning player is

Add missing dependent methods to GameStore

Add methods to GameStore that are called by other methods in GameStore but which are not currently available.

  • _ante
  • _endgameTrap
    • do not add to AppActions or constants, because this is only used within GameStore and is never directly called by an interface element
  • NewDeck
    • this method should eventually move to DeckStore, once it exists
  • clearHand
    • don't add this to AppConstants / AppActions

Move player hands to DeckStore

Track player hands in DeckStore instead of GameStore.

  • associate each hand with a player id upon player creation
    • create a new state variable in DeckStore called playerHands
    • return as part of DeckStore's getState method

Getter Methods

  • getHand ( playerId )
  • getSelected( playerId )
  • getDrawn( playerId )

Setter methods ( AppActions )

  • newHand ( playerId )
  • ante
  • draw ( playerId, num )

Then modify the flow data for functions that modify both GameStore and DeckStore simultaneously.

  • newPlayer
  • draw
  • evaluateHand

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.