codegard1 / blackjack Goto Github PK
View Code? Open in Web Editor NEWNonstandard blackjack game implemented with React and Fluent UI 1
Home Page: https://ciaervo-blackjack.netlify.app/
Nonstandard blackjack game implemented with React and Fluent UI 1
Home Page: https://ciaervo-blackjack.netlify.app/
Update components so they use GameStore methods instead of Table's
If all players stay (status code 2) then the round ends and a winner is determined.
_evaluateGame(2)
is called, check if all players have stayed
currentPlayer
and set player.turn
for the next player
state.stayedPlayers
before updating currentPlayer
and player.turn
Implement a color change in the DeckContainer associated with the player who's turn it is.
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.
getPlayers
getPlayer( Id )
getState
isOptionsPanelVisible
, MessageBar text & type, etc.getState
getSelected
getDrawn
getDeck
Implement a Callout that appears on hover to show the point value(s) of each Player hand
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 the New Game method from Table as a way to test if Flux is working correctly
GAME_NEWGAME
to AppConstantsnewGame
handler in AppActions_newGame
in GameStore_onNewGame
to Table to pass params to AppActions.deal()
_onNewGame
to TableCreate DeckStore and add the following state variables to it:
deck
selected
drawn
as well as getter methods described in #19
Each player has a bank
prop that is the amount of money they have left to play with.
_bet()
is called, subtract the bet amount from player's bank
and add it to Table state's pot
_ante()
)_ante()
occursroundCount
to Table state_resetGame()
is calledimport animate.css into DeckDisplay and Table
pulse
class when it changesflash
Use TypeScript for the benefit of compatibility with Microsoft Fluent UI components
Move all Game state methods to GameStore, but do not call them in Components yet.
For each method in the below list, do:
AppDispatcher.register()
See When should I use curly braces for ES6 import?
Go through all files and implement a consistent approach.
Instead of framing the StatusPanel in a plain
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:
handValue
of each player
handValue
is the winnerhandValue
, the human player (id 0) wins
Implement a Bet button in the CommandBar:
_bet()
to Table & bind it_bet()
to controlPanelMethods
blackJackItems
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>; }
Fix the CSS of the card container so that the card numbers are always in the corner
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
PlayerHand
and privately implement evaluating methodsImplement
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
}
}
add new properties to player object
bank: 1000, bet: 0,
add to Table.state:
pot: 0
Create a menu of game options on a Panel. Include
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.
PlayerStore is over-engineered for what it needs to do. We use it as a class because then we can call methods directly from instances of Player, but this overlaps too much with GameContext and DeckContext, which is where all of the effort in game logic has gone so far. It would be better to reduce PlayerStore to a type and to manage players directly as plain objects in the gameState, so that there is no confusion about where player hands are being managed and evaluated.
Update components to use GameStore _reset
Implement _newPlayer
in GameStore as a second test that Flux is working properly
GAME_NEWPLAYER
in AppConstantsnewPlayer
handler in AppActions_newPlayer
in GameStore_onNewPlayer
in Table to pass params to AppActions.newPlayer()
_onNewPlayer
to Tablethe variable aceAsTen is a typo. Change it to aceAsEleven across all files
Re: Refactoring React Components to ES6 Classes
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
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');
}
// ...
}
onChange
events from GameStore.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.
};
},
Refactor GameStore to be a class that extends FluxReduceStore instead of whatever it is currently.
For reference: FluxReduceStore source
The ActivityLogStore class is the only one that has not been converted to TypeScript after the entire codebase was switched over.
Add methods to GameStore that are called by other methods in GameStore but which are not currently available.
_ante
_endgameTrap
NewDeck
clearHand
Currently we have two variables in gameState that have the same purpose, but which are each used in separate domains, causing confusion and duplication of effort.
One or the other should be deprecated and all instances of the one replaced with the other, such that there is always only one state variable tracking the key of the player who currently has control in the game.
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);
getState
methodGetter 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
Instead of using bare functions in a switch statement to govern gameplay, create a StateMachine class to encapsulate all code related to the state of play.
For reference see: State Machines in Games
Also, instead of writing this from scratch, how about using javascript-state-machine ( also on npm )
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.