Skip to content

Instantly share code, notes, and snippets.

@bananaumai
Last active January 4, 2017 03:11
Show Gist options
  • Save bananaumai/ed5fd031d693d7ffe17396644887d83b to your computer and use it in GitHub Desktop.
Save bananaumai/ed5fd031d693d7ffe17396644887d83b to your computer and use it in GitHub Desktop.
オセロ用のモデル
import IM from 'immutable'
import _ from 'lodash'
export const DISC = {
WHITE_SIDE : Symbol('WHITE_SIDE'),
BLACK_SIDE : Symbol('BLACK_SIDE')
}
export const SQUARE_STATUSES = {
WHITE: Symbol('WHITE'),
BLACK: Symbol('BLACK'),
VACANT: Symbol('VACANT')
}
export const DIRECTIONS = {
TOP : Symbol('TOP'),
RIGHT_TOP : Symbol('RIGHT_TOP'),
RIGHT : Symbol('RIGHT'),
RIGHT_BOTTOM : Symbol('RIGHT_BOTTOM'),
BOTTOM : Symbol('BOTTOM'),
LEFT_BOTTOM : Symbol('LEFT_BOTTOM'),
LEFT : Symbol('LEFT'),
LEFT_TOP : Symbol('LEFT_TOP')
}
export function createBord() {
return IM.fromJS(_.fromPairs(
_.flatMap(
_.range(1, 9),
(rowNum, idx, range) => _.map(
range,
colNum => {
const coord = getCoord(rowNum, colNum)
switch (coord) {
case '44':
case '55':
return [coord, SQUARE_STATUSES.WHITE]
case '45':
case '54':
return [coord, SQUARE_STATUSES.BLACK]
default:
return [coord, SQUARE_STATUSES.VACANT]
}
}
)
)
))
}
export function getAvailableCoords(bord, disc) {
return Array.from(bord.filter((status, coord) => canPlaceDisc(bord, coord, disc)).keys())
}
export function canPlaceDisc(bord, coord, disc) {
if (getStatus(bord, coord) !== SQUARE_STATUSES.VACANT) return false
return Object.values(DIRECTIONS).reduce((acc, direction) => {
return acc || canChangeNeighborStatus(bord, coord, direction, getPossibleStatus(disc))
}, false)
}
export function canChangeNeighborStatus(bord, coord, direction, status) {
const neighborStatus = getNeighborStatus(bord, coord, direction)
switch(neighborStatus) {
case null:
case SQUARE_STATUSES.VACANT:
case status:
return false
default:
return statusExists(bord, getNeighborCoord(coord, direction), direction, status)
}
}
export function statusExists(bord, coord, direction, status) {
const neighborStatus = getNeighborStatus(bord, coord, direction)
switch(neighborStatus) {
case null:
case SQUARE_STATUSES.VACANT:
return false
case status:
return true
default:
return statusExists(bord, getNeighborCoord(coord, direction), direction, status)
}
}
export function changeNeighborStatus(bord, coord, direction, status) {
if (getStatus(bord, coord) !== status) throw new Error('Invalid status')
if (!canChangeNeighborStatus(bord, coord, direction, status)) return bord
const neighborCoord = getNeighborCoord(coord, direction)
const newBord = changeStatus(bord, neighborCoord, status)
return changeNeighborStatus(newBord, neighborCoord, direction, status)
}
export function placeDisc(bord, coord, disc) {
if (!canPlaceDisc(bord, coord, disc)) return bord
const status = getPossibleStatus(disc)
return Object.values(DIRECTIONS).reduce((prevBord, direction) => {
return changeNeighborStatus(prevBord, coord, direction, status)
}, changeStatus(bord, coord, status))
}
function getNeighborStatus(bord, coord, direction) {
const neighborStatus = getNeighborCoord(coord, direction)
if (!neighborStatus) return null
return getStatus(bord, neighborStatus)
}
function getNeighborCoord(coord, direction) {
const rowNum = getRow(coord),
colNum = getCol(coord)
switch(direction) {
case DIRECTIONS.TOP:
return getCoord(rowNum - 1, colNum )
case DIRECTIONS.RIGHT_TOP:
return getCoord(rowNum - 1, colNum + 1)
case DIRECTIONS.RIGHT:
return getCoord(rowNum , colNum + 1)
case DIRECTIONS.RIGHT_BOTTOM:
return getCoord(rowNum + 1, colNum + 1)
case DIRECTIONS.BOTTOM:
return getCoord(rowNum + 1, colNum )
case DIRECTIONS.LEFT_BOTTOM:
return getCoord(rowNum + 1, colNum - 1)
case DIRECTIONS.LEFT:
return getCoord(rowNum , colNum - 1)
case DIRECTIONS.LEFT_TOP:
return getCoord(rowNum - 1, colNum - 1)
default:
throw new Error()
}
}
function getCoord(row, col) {
return `${row}${col}`
}
function getRow(coord) {
return Number(coord[0])
}
function getCol(coord) {
return Number(coord[1])
}
function getRowCol(coord) {
return _.map(coord, c => Number(c))
}
export function getStatus(bord, coord) {
const status = bord.get(coord)
if (!status) return null
return status
}
import _ from 'lodash'
export const discs = {
WHITE_DISC: Symbol('WHITE_DISC'),
BLACK_DISC: Symbol('BLACK_DISC')
}
export class Square {
constructor(coord) {
this.coord = coord
this.disc = null
const nullSquare = new NullSquare()
this.neighborSquares = {
top: nullSquare,
rightTop: nullSquare,
right: nullSquare,
rightBottom: nullSquare,
bottom: nullSquare,
leftBottom: nullSquare,
left: nullSquare,
leftTop: nullSquare
}
}
setDisc(disc) {
this.disc = disc
Object.values(Object.keys(this.neighborSquares)).forEach((direction) => {
this.neighborSquares[direction].reverse(disc, direction)
})
}
canSetDisc(disc) {
Object.keys(this.neighborSquares).reduce((acc, direction) => {
return acc || this.neighborSquares[direction].reversible(disc, direction)
}, false)
}
discExists(disc, direction) {
if (this.disc === null) return false
if (this.disc === disc) return true
return this.neighborSquares[direction].discExists(disc, direction)
}
reverse(prevDisc, direction) {
if (!this.reversible(prevDisc, direction)) return
console.log(this.coord, prevDisc, direction)
this.disc = prevDisc
this.neighborSquares[direction].reverse(prevDisc, direction)
}
reversible(prevDisc, direction) {
if (this.disc === null || this.disc === prevDisc) return false
return this.neighborSquares[direction].discExists(prevDisc, direction)
}
}
class NullSquare {
canSetDisc() { return false }
discExists() { return false }
reverse() {}
}
export class Bord {
constructor() {
this.squares = _.fromPairs(
_.flatMap(
_.range(1,9),
(rowNum, idx, range) => _.map(
range,
colNum => [this.getSquareKey(rowNum, colNum), new Square([rowNum, colNum])]
)
)
)
this.findSquare(4, 4).setDisc(discs.WHITE_DISC)
this.findSquare(4, 5).setDisc(discs.BLACK_DISC)
this.findSquare(5, 4).setDisc(discs.BLACK_DISC)
this.findSquare(5, 5).setDisc(discs.WHITE_DISC)
Object.values(this.squares).forEach((square) => {
const [rowNum, colNum] = square.coord
if (rowNum === 1 && colNum === 1) {
this.setNeighborSquare(square, 'right')
this.setNeighborSquare(square, 'rightBottom')
this.setNeighborSquare(square, 'bottom')
} else if (rowNum === 1 && colNum === 8) {
this.setNeighborSquare(square, 'bottom')
this.setNeighborSquare(square, 'leftBottom')
this.setNeighborSquare(square, 'left')
} else if (rowNum === 8 && colNum === 1) {
this.setNeighborSquare(square, 'top')
this.setNeighborSquare(square, 'rightTop')
this.setNeighborSquare(square, 'right')
} else if (rowNum === 8 && colNum === 8) {
this.setNeighborSquare(square, 'left')
this.setNeighborSquare(square, 'leftTop')
this.setNeighborSquare(square, 'top')
} else if (rowNum === 1) {
this.setNeighborSquare(square, 'right')
this.setNeighborSquare(square, 'rightBottom')
this.setNeighborSquare(square, 'bottom')
this.setNeighborSquare(square, 'leftBottom')
this.setNeighborSquare(square, 'left')
} else if (rowNum === 8) {
this.setNeighborSquare(square, 'left')
this.setNeighborSquare(square, 'leftTop')
this.setNeighborSquare(square, 'top')
this.setNeighborSquare(square, 'rightTop')
this.setNeighborSquare(square, 'right')
} else if (colNum === 1) {
this.setNeighborSquare(square, 'top')
this.setNeighborSquare(square, 'rightTop')
this.setNeighborSquare(square, 'right')
this.setNeighborSquare(square, 'rightBottom')
this.setNeighborSquare(square, 'bottom')
} else if (colNum === 8) {
this.setNeighborSquare(square, 'bottom')
this.setNeighborSquare(square, 'leftBottom')
this.setNeighborSquare(square, 'left')
this.setNeighborSquare(square, 'leftTop')
this.setNeighborSquare(square, 'top')
} else {
this.setNeighborSquare(square, 'top')
this.setNeighborSquare(square, 'rightTop')
this.setNeighborSquare(square, 'right')
this.setNeighborSquare(square, 'rightBottom')
this.setNeighborSquare(square, 'bottom')
this.setNeighborSquare(square, 'leftBottom')
this.setNeighborSquare(square, 'left')
this.setNeighborSquare(square, 'leftTop')
}
})
}
getSquareKey(rowNum, colNum) {
return rowNum.toString().concat(colNum)
}
findSquare(rowNum, colNum) {
return this.squares[this.getSquareKey(rowNum, colNum)]
}
setNeighborSquare(square, direction) {
const [rowNum, colNum] = square.coord
let neighborSquare = null
switch (direction) {
case 'top':
neighborSquare = this.findSquare(rowNum-1, colNum)
break
case 'rightTop':
neighborSquare = this.findSquare(rowNum-1, colNum+1)
break
case 'right':
neighborSquare = this.findSquare(rowNum, colNum+1)
break
case 'rightBottom':
neighborSquare = this.findSquare(rowNum+1, colNum+1)
break
case 'bottom':
neighborSquare = this.findSquare(rowNum+1, colNum)
break
case 'leftBottom':
neighborSquare = this.findSquare(rowNum+1, colNum-1)
break
case 'left':
neighborSquare = this.findSquare(rowNum, colNum-1)
break
case 'leftTop':
neighborSquare = this.findSquare(rowNum-1, colNum-1)
break
}
if (neighborSquare) square.neighborSquares[direction] = neighborSquare
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment