Skip to content

Instantly share code, notes, and snippets.

@nyk510
Created April 20, 2020 17:38
Show Gist options
  • Save nyk510/5145a4ea58542a2b979175572e428076 to your computer and use it in GitHub Desktop.
Save nyk510/5145a4ea58542a2b979175572e428076 to your computer and use it in GitHub Desktop.
Vue.js Lifegame (220 lines)
<template>
<v-container>
<v-layout align-center>
<v-btn
:disabled="!!taskId"
depressed
class="ma-0"
@click="onClickPlay">
<v-icon>play_arrow</v-icon>
</v-btn>
<v-btn
class="ma-0"
depressed
@click="onClickPause">
<v-icon>pause</v-icon>
</v-btn>
<v-btn
class="mr-0"
icon
@click="onClickBrush">
<v-icon>brush</v-icon>
</v-btn>
<v-btn
class="ma-0"
icon
@click="onClickRefresh">
<v-icon>refresh</v-icon>
</v-btn>
<v-flex
class="ml-2"
shirk >
<v-select
v-model="initRatio"
:items="initRatioItems"
style="width: 200px"
label="初期の空白率"
width="200px"/>
</v-flex>
</v-layout>
<v-layout
class="px-2"
align-center>
生存セル数
<v-checkbox
v-model="relative"
class="ml-3 mt-0"
hide-details
label="相対表示"/>
</v-layout>
<v-layout
style="height: 80px"
class="pb-2"
align-end>
<v-flex
v-for="item in history"
:style="historyItemStyle(item)"
:key="item"
class="primary"/>
</v-layout>
<table
border="1"
style="border-collapse: collapse; width: 100%">
<tr
v-for="(row, i) in cells"
:key="i">
<td
v-for="(cell, j) in row"
:class="cell.cellClass"
:key="j"
style="height: 12px; width: 12px;"
@mouseenter="onMouseOver(cell)"
@click="onClickCell(cell)"/>
</tr>
</table>
</v-container>
</template>
<script>
class Cell {
constructor(alive = false) {
this.alive = alive
this.nextIsAlive = null
this.surrounds = []
}
add(cell) {
this.surrounds.push(cell)
}
getNextStep() {
const surroundAlives = this.surrounds.filter(v => v.alive).length
if (!this.alive) {
if (surroundAlives === 3) return true
return false
}
if (surroundAlives >= 4) return false
if (surroundAlives <= 1) return false
return true
}
setNext() {
this.nextIsAlive = this.getNextStep()
}
get cellClass() {
if (this.alive) {
return 'primary white--text'
}
return ''
}
next() {
this.alive = this.nextIsAlive
this.nextIsAlive = null
}
}
export default {
data() {
return {
cells: [],
history: [],
maxCount: null,
relative: false,
initRatio: 0.7,
initRatioItems: [0.3, 0.5, 0.7, 0.9],
rows: 100,
cols: 80,
taskId: null
}
},
computed: {
allCells() {
return this.cells.flat()
}
},
created() {
this.init()
},
methods: {
next() {
const alive = this.allCells.filter(v => v.alive).length
this.allCells.forEach(v => v.setNext())
this.allCells.forEach(v => v.next())
this.history.push(alive)
if (!this.maxCount) this.maxCount = alive
else this.maxCount = Math.max(this.maxCount, alive)
},
init() {
this.cells = []
this.history = []
this.maxCount = null
for (let i = 0; i < this.rows; i++) {
const row = []
for (let j = 0; j < this.cols; j++) {
const isAlive = Math.random() > this.initRatio
const cell = new Cell(isAlive)
row.push(cell)
}
this.cells.push(row)
}
this.registerSrounds()
},
registerSrounds() {
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
const target = this.cells[i][j]
for (let n = -1; n <= 1; n++) {
for (let m = -1; m <= 1; m++) {
if (n === 0 && m === 0) continue
target.add(
this.cells[(n + i + this.rows) % this.rows][
(m + j + this.cols) % this.cols
]
)
}
}
}
}
},
historyItemStyle(item) {
const relative = this.relative ? this.maxCount : this.rows * this.cols
return {
height: (item / relative) * 100 + '%'
}
},
onClickPause() {
if (!this.taskId) return
window.clearInterval(this.taskId)
this.taskId = null
},
onClickPlay() {
this.taskId = window.setInterval(() => {
this.next()
}, 200)
},
onClickRefresh() {
this.onClickPause()
this.init()
},
onClickBrush() {
this.allCells.forEach(v => (v.alive = false))
},
onClickCell(cell) {
if (this.taskId) return
cell.alive = true
},
onMouseOver(cell, e) {
if (this.taskId) return
cell.alive = true
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment