Mulan
Mulan

Reputation: 135377

How to design a state flow for a react/redux flashcard game?

This is my first redux project. I'm trying to make a flashcard game that teaches you hiragana/katakana. I'm getting stuck on some of the state flow...

Game state visualization

{
  // the current displayed card
  currentCard: null | {q: 'き', a: 'ki'},

  // time the game was started
  timestamp: millisecondTimestamp,

  // submitted answers
  answers: [
    {
      card: {q: 'か', a: 'ka'},
      answer: 'ka'
    },
    {
      card: {q: 'な', a: 'na'},
      answer: 'na'
    },
    ...
  ],

  // remaining cards in the deck
  deck: [
    {q: 'く', a: 'ku'},
    {q: 'け', a: 'ke'},
    {q: 'こ', a: 'ko'}
    ...
  ]
}

stores/game.js

import {BEGIN_GAME, NEXT_CARD, SUBMIT_ANSWER} from '../actions/';
import {isEmpty, first, rest} from '../utilities/';

const gameReducer = (state=null, action) => {
  switch (action.type) {

    case BEGIN_GAME:
      return Object.assign({}, state, {deck: action.deck});

    case NEXT_CARD:
      return isEmpty(state.deck)
        ? Object.assign({}, state, {
          currentCard: null
        })
        : Object.assign({}, state, {
          currentCard: first(state.deck),
          deck: rest(state.deck)
        })
      ;

    case SUBMIT_ANSWER:
      return Object.assign({}, state, {
        currentCard: null,
        answers: state.answers.concat({
          card: state.currentCard,
          answer: action.answer
        })
      });

    default:
      return state;
  }
};

export default gameReducer;

actions/index.js

import {shuffle} from '../utilities/';

export const BEGIN_GAME = 'BEGIN_GAME';
export const NEXT_CARD = 'NEXT_CARD';
export const SUBMIT_ANSWER = 'SUBMIT_ANSWER';

export const beginGame = deck => ({
  type: BEGIN_GAME,
  deck: shuffle(deck)
});

export const nextCard = () => ({
  type: NEXT_CARD
});

export const submitAnswer = answer => ({
  type: SUBMIT_ANSWER,
  answer
});

I'm thinking the game loop will work something like this:

See, I'm getting a little lost here... With redux, I don't think I can (or should) dispatch another action from within a store. But then how do I decompose these actions or state checks ?

My brain is currently thinking with a model like this:

BEGIN_GAME(deck)

LOOP(
  CHECK_END_GAME()->NEXT_CARD()->SUBMIT_ANSWER(answer)->
)

DISPLAY_RESULTS()

The problem is, I don't know how to chain actions like this, or if it's even advised. I'm open to designing the actions/store in a completely different way. I'm a noob here, so just tell me if I'm doing something wrong.

Any nudge in the proper direction will be helpful. Thanks !

Upvotes: 2

Views: 941

Answers (2)

One way to code the application is to model (or to organize) the game logic in terms of Petri Net Elements and based on this organization write the code (Chionglo, 2014). The following is an example of a game logic (based on a Flashcard game) organized in terms of Petri Nets (“How to Design”, 2016). In this game there are nine cards. One card is shown at a time then the player guesses the card. The number of correct guesses and the number of incorrect guesses are recorded and play continues until there are no more cards to display.

Figure 1 (for the PDF version of this reply) is an interactive, dynamic diagram of the game logic; it includes “graphic notations” of cards with standard Petri Net notations and some high-level notations of Petri Net elements. The demonstration mode of the game logic randomly selects a card from the deck then randomly guesses the card.

Labels and Descriptions of Petri Net Elements

Petri Net Model of the Game

References

Chionglo, J. F. (2016). A Reply to "How to design a state flow for a react/redux flashcard game?" at Stack Overflow. Stack Overflow. https://www.academia.edu/34059934/A_Reply_to_How_to_design_a_state_flow_for_a_react_redux_flashcard_game_at_Stack_Overflow.

Chionglo, J. F. (2014). Net Elements and Annotations for Computer Programming: Computations and Interactions in PDF. https://www.academia.edu/26906314/Net_Elements_and_Annotations_for_Computer_Programming_Computations_and_Interactions_in_PDF.

“How to design a state flow for a react/redux flashcard game?” (2016). Stack Exchange. Retrieved on Feb. 7, 2016 at http://stackoverflow.com/questions/35220169/how-to-design-a-state-flow-for-a-react-redux-flashcard-game.

Upvotes: 4

Ashley Coolman
Ashley Coolman

Reputation: 11585

Disclaimer: this answer will be a little rushed, I have a train to catch

Currently, I only "chain" async actions but I guess the same principle could apply.

I don't really understand this game :P, But suspect you should be thinking about it a little more like this:

BEGIN_GAME(deck)

DISPLAY_STATE
    {if END_GAME()}
        Its over!
    {else}
        <button onclick=dispatch( drawCardAndModifyStateAction )/>

In your parent reducer you might compose (as opposed to chain) your reducers:

const gameReducer = (state=null, action) => {
  switch (action.type) {
    NEXT_CARD: state.nextCard = nextCard(state);
  }
  state.checkEndGame = checkEndGame(state);
  return state;
}

Your nextCard "sub" reducer does some stuff...

const nextCard = (state=null, action) => {
  switch (action.type) {
    case NEXT_CARD:
        return Object.assign({}, state, {
          currentCard: first(state.deck),
          isEmpty: isEmpty(state.deck),
          deck: rest(state.deck)
        })
    }
  return state;
}

Followed by checkEndGame

const checkEndGame = (state=null, action) => {
  switch (action.type) {
    default:
        return Object.assign({}, state, {
          message: ...,
          winner: ...,
        })
    }
}

You might also look into middleware like redux saga, redux thunk.

Upvotes: 1

Related Questions