{"id":294661,"student_id":10,"content":"{\"html\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n \u003cmeta charset=\\\"UTF-8\\\"\u003e\\n \u003cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\"\u003e\\n \u003cmeta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"ie=edge\\\"\u003e\\n \u003ctitle\u003eDocument\u003c/title\u003e\\n \u003cscript src=\\\"https://cdn.jsdelivr.net/npm/vue/dist/vue.js\\\"\u003e\u003c/script\u003e\\n \u003clink rel=\\\"stylesheet\\\" href=\\\"index.css\\\"\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n \u003cdiv id=\\\"game\\\"\u003e\\n \u003cdiv class=\\\"grid\\\"\u003e\\n \u003cdiv v-for=\\\"(_, y) in 8\\\" class=\\\"row\\\"\u003e\\n \u003cdiv v-for=\\\"(_, x) in 8\\\" class=\\\"col\\\" :class=\\\"getClassOf(x, y)\\\" @click=\\\"place(x, y)\\\"\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003cp\u003e{{gameInfo}}\u003c/p\u003e\\n \u003c/div\u003e\\n \u003cscript src=\\\"othello.js\\\"\u003e\u003c/script\u003e\\n \u003cscript src=\\\"ai.js\\\"\u003e\u003c/script\u003e\\n \u003cscript\u003e\\n \\n \u003c/script\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\",\"css\":\"body {\\n text-align: center;\\n background-color: #ffc859;\\n font-family: monospace;\\n padding: 30px;\\n}\\n.grid {\\n display: inline-block;\\n border: 1px solid black;\\n}\\n.row {\\n display: flex;\\n}\\n.col {\\n position: relative;\\n width: 50px;\\n height: 50px;\\n text-align: center;\\n line-height: 50px;\\n box-sizing: border-box;\\n border: 1px solid black;\\n}\\n.col.black::after,\\n.col.white::after,\\n.col.hint::after {\\n content: '';\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n width: 35px;\\n height: 35px;\\n border: 1px solid black;\\n border-radius: 50%;\\n transform: translate(-50%, -50%);\\n transition: background-color 1s step-end;\\n}\\n.col.black::after {\\n background-color: black;\\n}\\n.col.white::after {\\n background-color: white;\\n}\\n.col.hint::after {\\n border-style: dashed;\\n}\",\"js\":\"class Othello {\\n\\n constructor() {\\n this.width = 8\\n this.height = 8\\n this.grid = {}\\n this.turn = 'b'\\n this.logs = []\\n this.steps = 0\\n this.offsets = [{\\n x: 1, y: 0\\n }, {\\n x: -1, y: 0\\n }, {\\n x: 0, y: 1\\n }, {\\n x: 0, y: -1\\n }, {\\n x: 1, y: 1\\n }, {\\n x: -1, y: -1\\n }, {\\n x: 1, y: -1\\n }, {\\n x: -1, y: 1\\n }]\\n\\n this.initGrid()\\n }\\n\\n initGrid() {\\n for (let y = -2; y \u003c 10; y++) {\\n this.grid[y] = {}\\n for (let x = -2; x \u003c 10; x++) {\\n this.grid[y][x] = ''\\n }\\n }\\n this.grid[3][3] = 'b'\\n this.grid[4][4] = 'b'\\n this.grid[4][3] = 'w'\\n this.grid[3][4] = 'w'\\n }\\n\\n getValidPos() {\\n const arr = []\\n for (let x = 0; x \u003c 8; x++) {\\n for (let y = 0; y \u003c 8; y++) {\\n if (this.place(x, y)) {\\n arr.push({\\n x, y\\n })\\n this.undo()\\n }\\n }\\n }\\n return arr\\n }\\n\\n place(x, y) {\\n if (this.grid[y][x] !== '') return false\\n\\n let isValid = false\\n this.offsets.forEach(o =\u003e {\\n if (this.grid[y + o.y][x + o.x] === this.turn) return\\n if (this.fillLine(x, y, o.x, o.y)) isValid = true\\n })\\n\\n if (isValid) {\\n this.logs.unshift({\\n x, y, status: this.grid[y][x], steps: this.steps\\n })\\n this.grid[y][x] = this.turn\\n this.switch()\\n this.steps++\\n }\\n\\n return isValid\\n }\\n\\n fillLine(x, y, vx, vy) {\\n\\n while (true) {\\n x += vx\\n y += vy\\n const target = this.grid[y][x]\\n if (target === '') return false\\n if (target === this.turn) break\\n }\\n\\n while (true) {\\n x -= vx\\n y -= vy\\n const target = this.grid[y][x]\\n if (target === '') return true\\n if (target === this.turn) return true\\n if (target !== this.turn) {\\n this.logs.unshift({\\n x, y, status: this.grid[y][x], steps: this.steps\\n })\\n this.grid[y][x] = this.turn\\n }\\n }\\n }\\n\\n switch () {\\n this.turn = this.turn === 'b' ? 'w': 'b'\\n }\\n\\n undo() {\\n if (this.steps \u003e 0) {\\n this.steps--\\n while (this.logs[0] \u0026\u0026 this.logs[0].steps === this.steps) {\\n const diff = this.logs.shift()\\n this.grid[diff.y][diff.x] = diff.status\\n }\\n this.switch()\\n }\\n }\\n\\n clone() {\\n const virtual = new Othello()\\n virtual.grid = JSON.parse(JSON.stringify(this.grid))\\n virtual.logs = JSON.parse(JSON.stringify(this.logs))\\n virtual.turn = this.turn\\n virtual.steps = this.steps\\n return virtual\\n }\\n}\\n\\nfunction AI(game) {\\n const startTime = Date.now()\\n const result = alphabeta(game.clone(), 4)\\n console.log(`cost: ${Date.now() - startTime}ms`)\\n return result\\n}\\n\\nfunction alphabeta(game, deep, alpha = -Infinity, beta = Infinity) {\\n\\n let best = {\\n x: undefined,\\n y: undefined,\\n score: game.turn === 'w' ? Infinity: -Infinity\\n }\\n\\n for (let x = 0; x \u003c 8; x++) {\\n for (let y = 0; y \u003c 8; y++) {\\n if (game.place(x, y)) {\\n\\n let result = deep \u003e 0 ? alphabeta(game, deep - 1, alpha, beta): (\\n {\\n x, y, score: evaluation(game.grid)\\n }\\n )\\n\\n if (game.turn === 'w' \u0026\u0026 result.score \u003e best.score) {\\n alpha = best.score = result.score\\n best.x = x\\n best.y = y\\n }\\n\\n if (game.turn === 'b' \u0026\u0026 result.score \u003c best.score) {\\n beta = best.score = result.score\\n best.x = x\\n best.y = y\\n }\\n\\n game.undo()\\n\\n if (alpha \u003e beta) return best\\n }\\n }\\n }\\n\\n return best\\n}\\n\\nfunction evaluation(grid) {\\n let score = 0\\n for (let x = 0; x \u003c 8; x++) {\\n for (let y = 0; y \u003c 8; y++) {\\n let i = 1\\n if (x === 0 || x === 7) i *= 10\\n if (y === 0 || y === 7) i *= 10\\n if (grid[y][x] === 'b') score += i\\n if (grid[y][x] === 'w') score -= i\\n }\\n }\\n return score\\n}\\n\\nconst game = new Othello()\\n\\nnew Vue({\\n el: '#game',\\n data: {\\n game,\\n validPos: game.getValidPos(),\\n },\\n methods: {\\n getClassOf(x, y) {\\n const s = this.game.grid[y][x]\\n if (this.validPos.some(pos =\u003e pos.x === x \u0026\u0026 pos.y === y)) return ['hint']\\n if (s === 'b') return ['black']\\n if (s === 'w') return ['white']\\n },\\n place(x, y) {\\n if (this.game.place(x, y)) {\\n this.validPos = this.game.getValidPos()\\n if (this.validPos.length === 0) {\\n this.game.switch()\\n } else {\\n this.runAI()\\n }\\n }\\n },\\n runAI() {\\n setTimeout(() =\u003e {\\n this.validPos = this.game.getValidPos()\\n if (this.validPos.length === 0) return\\n\\n const result = AI(this.game)\\n game.place(result.x, result.y)\\n\\n this.validPos = this.game.getValidPos()\\n if (this.validPos.length === 0) {\\n this.game.switch()\\n this.runAI()\\n }\\n }, 3000)\\n }\\n },\\n computed: {\\n gameInfo() {\\n let w = 0\\n let b = 0\\n for (let y = 0; y \u003c 8; y++) {\\n for (let x = 0; x \u003c 8; x++) {\\n if (this.game.grid[y][x] === 'w') w++\\n if (this.game.grid[y][x] === 'b') b++\\n }\\n }\\n return `${b} : ${w}`\\n }\\n }\\n})\"}","created_at":"2021-09-03T18:08:21.324+08:00","updated_at":"2021-09-03T18:18:47.389+08:00","name":"OthelloAI 副本","language":"web","screenshot":{"url":null},"parent_id":294656,"plugin":"","description":null,"note":null,"status":"public","like_student_ids":[],"is_featured":false,"views":330,"hashid":"wdks4grwg","is_content_changed":false,"review_status":"unsubmitted","submitted_at":null,"reviewed_at":null,"advise":null,"is_deleted":false}
[{"id":5905493,"file_name":"koding.png","project_id":294661,"asset_id":302342,"created_at":"2021-09-03T18:08:21.332+08:00","updated_at":"2021-09-03T18:08:21.332+08:00"}]
Orange Apple Learning Platform
My Projects
View Project Page
Export
Remix
Import
Delete
Download Android APP (APK)
Screenshot
Open Web Site
繁中
简中
English
日本語
1:1:1
1:1
Full Width
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer