Skip to content

Commit

Permalink
feat: added game logic for horizontal wins
Browse files Browse the repository at this point in the history
  • Loading branch information
jnmorse committed May 20, 2019
1 parent a9e4858 commit c3bda5d
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 16 deletions.
11 changes: 9 additions & 2 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { RESET_GAME, PLAYER_MOVE } from './types'
import { RESET_GAME, PLAYER_MOVE, GAME_WON } from './types'

function resetGame() {
return {
type: RESET_GAME
}
}

function gameWon(player) {
return {
type: GAME_WON,
payload: player
}
}

function playerMove(coords) {
return { type: PLAYER_MOVE, payload: coords }
}

export { resetGame, playerMove }
export { resetGame, playerMove, gameWon }
46 changes: 44 additions & 2 deletions src/components/GameBoard/game-board.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,46 @@ function fill(player) {
}
}

const GameBoard = ({ board, playerMove }) => {
const min = num => Math.max(0, num)
const max = num => Math.min(6, num)

function checkHorizontalWin(board, turn, lastMove) {
const start = min(lastMove.x - 3)
const end = max(lastMove.x + 3)
const lastTurn = turn === 1 ? 2 : 1

let count = 0

for (let x = start; x <= end; x += 1) {
if (board[x][lastMove.y] === lastTurn) {
count += 1

if (count === 4) {
return true
}
} else {
count = 0
}
}

return false
}

/* eslint-disable max-lines-per-function */
const GameBoard = ({ board, playerMove, gameWon, lastMove, turn }) => {
const boardSize = {
width: 450,
height: 390
}

const offset = 40

if (lastMove) {
if (checkHorizontalWin(board, turn, lastMove)) {
gameWon(turn === 1 ? 2 : 1)
}
}

const showBoard = board.map((column, x) =>
column.map((cell, y) => (
<circle
Expand Down Expand Up @@ -58,10 +90,20 @@ const GameBoard = ({ board, playerMove }) => {
</svg>
)
}
/* eslint-enable max-lines-per-function */

GameBoard.propTypes = {
board: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)).isRequired,
playerMove: PropTypes.func.isRequired
playerMove: PropTypes.func.isRequired,
lastMove: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.shape({
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired
})
]).isRequired,
turn: PropTypes.number.isRequired,
gameWon: PropTypes.func.isRequired
}

export default GameBoard
4 changes: 2 additions & 2 deletions src/components/GameBoard/game-board.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
}

.cells {
fill: hsl(0, 50%, 5%);
fill: hsl(0, 50%, 97%);
}

.cell {
Expand All @@ -24,7 +24,7 @@
}

.cellPlayer1 {
fill: hsl(75, 100%, 50%);
fill: hsl(0, 0%, 8%);
}

.cellPlayer2 {
Expand Down
10 changes: 7 additions & 3 deletions src/components/GameBoard/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { connect } from 'react-redux'
import GameBoard from './game-board'

import { playerMove } from '../../actions'
import { playerMove, gameWon } from '../../actions'

const mapStateToProps = ({ game: { board } }) => ({ board })
const mapStateToProps = ({ game: { board, lastMove, turn } }) => ({
board,
lastMove,
turn
})

export default connect(
mapStateToProps,
{ playerMove }
{ playerMove, gameWon }
)(GameBoard)
28 changes: 21 additions & 7 deletions src/reducers/game-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { GAME_WON, RESET_GAME, PLAYER_MOVE } = require('../actions/types')

export const defaultState = {
turn: 1,
lastMove: false,
board: Array(7).fill(Array(6).fill(0))
}

Expand All @@ -18,17 +19,30 @@ export default function gameReducer(state = defaultState, action) {
case PLAYER_MOVE: {
const newBoard = [...state.board].map(col => [...col])

let y = false
const y = newBoard[action.payload.x].reduce((acc, cell, index) => {
switch (cell) {
case 0: {
return index
}

for (let i = newBoard[action.payload.x].length - 1; i > 0; i--) {
if (y === false && newBoard[action.payload.x][i] === 0) {
y = i
default: {
return acc
}
}
}
}, false)

newBoard[action.payload.x][y] = state.turn
if (y !== false) {
newBoard[action.payload.x][y] = state.turn

return { ...state, board: newBoard, turn: state.turn === 1 ? 2 : 1 }
return {
...state,
board: newBoard,
turn: state.turn === 1 ? 2 : 1,
lastMove: { ...action.payload, y }
}
}

return { ...state }
}

default: {
Expand Down
10 changes: 10 additions & 0 deletions src/reducers/status-reducer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { GAME_WON, RESET_GAME } from '../actions/types'

export default function statusReducer(state = false, action) {
switch (action.type) {
case RESET_GAME: {
return false
}

case GAME_WON: {
return `Player ${action.payload} won`
}

default: {
return state
}
Expand Down
1 change: 1 addition & 0 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ body {
display: flex;
align-items: center;
justify-content: center;
background-color: #ffebcd;
height: 100vh;
margin: 0;
}
Expand Down

0 comments on commit c3bda5d

Please sign in to comment.