# *ㄅㄅㄅㄅㄅ宗のbolg*
海你好!我是陳柏宗 |Bert|
DMHS 502A
有事請called:(算了不要)
寄email也行(不定時follow):bert850512@gmail.com
---
## :#Math數學才是王道
致力於研究數學
learning:微積分 | 排列組合 | 高中範圍數學
---
## 習得JavaScript & Python中...
目前正在學習這兩個程式語言
各式語言展示於演算法中
---
## 重要事項
:::info
## :loudspeaker: 非常重要公告
### [暫無公告]
:::
---
## 程式碼大放送!!!
- 請以 PC 或 筆電模式下操作:
- step1:點擊/下載檔案:[~~小遊戲.zip~~](https://www.youtube.com/watch?v=dQw4w9WgXcQ&pp=ygUXbmV2ZXIgZ29ubmEgZ2l2ZSB5b3UgdXA%3D)
- step2:開啟檔案即可遊玩!!
---
## Sudoka:
(看不懂沒關係 我也不想解釋)
-HTML:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Sudoku Solver</title>
<link rel="stylesheet" href="index.css">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="sudoku">
<h1>Sudoku</h1>
<div class="game">
<div class="grid">
<div v-for="row, y in grid" class="row">
<div v-for="col, x in row" class="col">
<input
v-model.number="grid[y][x]"
@focus="onfocus(y, x)"
@focusout="onfocusout(y, x)"
:disabled="originGrid[y][x] != 0"
:style="textColor(y, x)"
>
</div>
</div>
</div>
<div class="vertical">
<div v-for="i in 9">
<div v-show="v_check(i - 1)" class="active"></div>
</div>
</div>
<div class="horizontal">
<div v-for="i in 9">
<div v-show="h_check(i - 1)" class="active"></div>
</div>
</div>
<div class="blocks">
<div v-for="i in 9">
<div v-show="b_check(i - 1)" class="active"></div>
</div>
</div>
</div>
<p v-if="isWin" class="status">Congratulations!!!you won!</p>
<button @click="newGame">New Game</button>
<button @click="resolve">Crack</button>
</div>
</body>
</html>
```
-CSS:
```css
body {
display: flex;
justify-content: center;
align-items: center;
background-color: lightyellow;
}
#sudoku {
text-align: center;
}
h1 {
font-size: 1.5rem;
}
button {
margin: 10px 5px;
}
.game {
width: 450px;
height: 450px;
border: 1px solid black;
position: relative;
}
.row {
width: 100%;
height: calc(100%/9);
}
.col {
position: relative;
display: inline-block;
width: calc(100%/9);
height: 100%;
margin: 0;
border: 1px solid #00000050;
box-sizing: border-box;
}
input {
position: absolute;
top: 0;
left: 0;
width: calc(100% - 2px);
height: calc(100% - 2px);
margin: 0;
text-align: center;
border-width: 0px;
box-sizing: border-box;
font-size: 1.2rem;
outline: none;
color: black;
background-color: rgba(0, 0, 0, 0);
}
input:disabled {
font-weight: 900;
font-size: 1.1rem;
background-color: rgba(0, 0, 0, 0);
cursor: not-allowed;
}
input:focus {
color: block !important;
}
.grid {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.vertical,
.horizontal,
.blocks {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-wrap: wrap;
pointer-events: none;
}
.vertical > div {
width: calc(100%/9);
height: 100%;
position: relative;
}
.horizontal > div {
width: 100%;
height: calc(100%/9);
position: relative;
}
.blocks > div {
width: 150px;
height: 150px;
border: 1px solid black;
box-sizing: border-box;
position: relative;
}
.vertical .active {
z-index: -1;
position: absolute;
top: -12px;
left: 12px;
right: 12px;
bottom: -12px;
background-color: #ff595960;
}
.horizontal .active {
z-index: -1;
position: absolute;
top: 12px;
left: -12px;
right: -12px;
bottom: 12px;
background-color: #ffa40060;
}
.blocks .active {
z-index: -1;
position: absolute;
top: 6px;
left: 6px;
right: 6px;
bottom: 6px;
background-color: #00c4b360;
}
```
-JavaScript:
```javascript
//The sudoku which is the hardest to solve
var maze = [
[8, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 6, 0, 0, 0, 0, 0],
[0, 7, 0, 0, 9, 0, 2, 0, 0],
[0, 5, 0, 0, 0, 7, 0, 0, 0],
[0, 0, 0, 0, 4, 5, 7, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 3, 0],
[0, 0, 1, 0, 0, 0, 0, 6, 8],
[0, 0, 8, 5, 0, 0, 0, 1, 0],
[0, 9, 0, 0, 0, 0, 4, 0, 0],
];
var grid = new Sudoku(maze); //initialization
//-------------------- Algorithm for solving problems --------------------//
//This function is executed when the "Crack" button is pressed
function autoplay () {
count = 0;
resolve();
console.log('Tried passing back' + count + 'times!');
}
function resolve () {
//Limit the number of recursions to avoid web page crashes
if (count >= 1000000) return;
count++;
for (var y = 0; y < 9; y++) {
for (var x = 0; x < 9; x++) {
if (grid[y][x] == 0) {
//!!//arr[] save array of number in line or column
var arr = [];
//!!//save the number in line into arr[]
for (var i = 0; i < 9; i++) {
arr.push(grid[y][i]);
}
// console.log(arr); //check
//!!//save the number in column into arr[]
for (var h = 0; h < 9; h++) {
arr.push(grid[h][x]);
}
// console.log(arr); //check
//!!//save the number in a chrunk into arr[]
var offsetX = x - x % 3;
var offsetY = y - y % 3;
for (var i = 0; i < 3; i++) {
for (var k = 0; k < 3; k++){
arr.push(grid[offsetY + i][offsetX + k]);
}
}
//console.log(arr); //check
//!!//choice number not in arr and fill it
for (var k = 1; k <= 9; k++) {
if (arr.indexOf(k) == -1) {
grid[y][x] = k;
var result = resolve();
if (result == true) {
return true;
} else {
grid[y][x] = 0;
}
}
}
return false;
}
}
}
return true;
}
//-------------------- Algorithm for generating questions --------------------//
//This function is executed when the "New Game" button is pressed
function newGame () {
count = 0;
clearAll();
generator();
randomHide();
console.log('Tried passing back' + count + 'times!';
}
function generator () {
//Limit the number of recursions to avoid web page crashes
if (count >= 1000000) return;
count++;
for (var y = 0; y < 9; y++) {
for (var x = 0; x < 9; x++) {
if (grid[y][x] == 0) {
//!!//arr[] save array of number in line or column
var arr = [];
//!!//save the number in line into arr[]
for (var i = 0; i < 9; i++) {
arr.push(grid[y][i]);
}
// console.log(arr); //check
//!!//save the number in column into arr[]
for (var h = 0; h < 9; h++) {
arr.push(grid[h][x]);
}
// console.log(arr); //check
//!!//save the number in a chrunk into arr[]
var offsetX = x - x % 3;
var offsetY = y - y % 3;
for (var i = 0; i < 3; i++) {
for (var k = 0; k < 3; k++){
arr.push(grid[offsetY + i][offsetX + k]);
}
}
//console.log(arr); //check
//!!//choice number not in arr and fill it
var random_arr = shuffle();
for (var k = 0; k < 9; k++) {
var candidate = random_arr[k];
if (arr.indexOf(candidate) == -1) {
grid[y][x] = candidate;
var result = generator();
if (result == true) {
return true;
} else {
grid[y][x] = 0;
}
}
}
return false;
}
}
}
return true;
}
//Delete Sudoku
function clearAll () {
for (var y = 0; y < 9; y++) {
for (var x = 0; x < 9; x++) {
grid[y][x] = 0;
}
}
}
//Shuffling algorithm
function shuffle() {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < 100; i++) {
var id1 = Math.floor(Math.random() * 9);
var id2 = Math.floor(Math.random() * 9);
var temp = arr[id1];
arr[id1] = arr[id2];
arr[id2] = temp;
}
return arr;
}
//Randomly hollow out complete Sudoku
function randomHide() {
var cnt = 0;
var str = [3, 4, 5, 6, 7, 2];
var acnt = 81 - (str[Math.floor(Math.random() * 5)] * str[Math.floor(Math.random() * 4)]);
console.log(acnt);
while(cnt < acnt) {
var randX = Math.floor(Math.random() * 9);
var randY = Math.floor(Math.random() * 9);
if (grid[randY][randX] != 0) {
grid[randY][randX] = 0;
cnt++;
}
}
}
```
---
## 河內塔模擬
-HTML:
```html
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<div class="row">
<div
v-for="disk in disks"
id="disk.value"
:style="diskStyle(disk)"
class="disk"
:draggable="isTop(disk)"
@dragstart="dragstart(disk)"
></div>
<div class="col col-a" @drop="ondrop('a')" @dragover="allowDrop"></div>
<div class="col col-b" @drop="ondrop('b')" @dragover="allowDrop"></div>
<div class="col col-c" @drop="ondrop('c')" @dragover="allowDrop"></div>
</div>
<div class="footer">
<p>總共移動了<span class="highlight"> {{count}} </span>次</p>
<input @change="start" v-model="size" type="number" min="1" max="10"/>
<button @click="start">重新開始</button>
<button @click="resolve">自動破解</button>
</div>
</div>
</body>
</html>
```
-CSS:
```css
body {
height: 100vh;
color: #ccc;
background-color: #222222;
text-align: center;
overflow: hidden;
}
#root {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 10px;
}
.footer {
padding: 0 10px 10px 10px;
height: 200px;
box-sizing: box-sizing;
}
.footer p {
margin: 0;
}
.row {
height: calc(100% - 200px);
position: relative;
display: inline-flex;
width: 100%;
box-sizing: border-box;
flex-direction: row;
}
.col {
flex: 1;
position: relative;
}
.col:before {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
background-color: #171717;
border-radius: 15px;
font-size: 2rem;
color: #444;
padding: 30px;
}
.col-a:before { content: 'A' }
.col-b:before { content: 'B' }
.col-c:before { content: 'C' }
.disk {
position: absolute;
border-radius: 100px;
transform: translate(-50%, -40%);
cursor: move;
transition: all 0.3s;
z-index: 10;
}
.disk:after {
content: '';
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
border-radius: 100px;
border: 5px solid rgba(0, 0, 0, .5);
}
.highlight {
color: rgb(52, 235, 161);
}
input, button {
display: block;
outline: none;
width: 100%;
height: 40px;
padding: 5px 10px;
margin-top: 10px;
border-radius: 5px;
border: 1px solid #555;
color: #ddd;
background-color: rgba(0, 0, 0, 0);
font-size: 1rem;
box-sizing: border-box;
}
input {
padding: 7px 9px;
}
input:hover, button:hover,
input:focus, button:focus {
color: rgb(52, 235, 161);
border-color: rgb(52, 235, 161);
outline: none;
}
```
-Javascript:
```javascript
setSpeed(100); //每秒移動的次數
//按下「自動破解」時會執行此函式
function cracker (size) {
//drag('a', 'c') //移動指令
move (size, 'a', 'c', 'b');
}
//移動 size 層從(from)位置,移動到(to)位置,過程中暫放在(tmp)位置
function move (size, from, to, tmp) {
if (size > 1) {
move (size - 1, from, tmp, to);
move (1, from, to, tmp);
move (size - 1, tmp, to, from);
} else {
drag(from, to);
}
}
```
---
## AI 手寫辨識
警告!!! 本程式極度吃電腦效能,使用前請善加確認是否使用
-HTML:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>handwriting recognition</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<div class="container py-3">
<div class="row">
<div class="col-8">
<div class="overflow-x-scroll bg-dark">
<div class="position-relative">
<div id="cursor" class="position-absolute"
style="width: 28px; height: 28px; top:0; left: 0; z-index: 10; border: 2px solid red;"></div>
<canvas id="mark-canvas" width="28000" height="280" class="position-absolute top-0 left-0"
style="opacity: 0.6;"></canvas>
<canvas id="data-canvas" width="28000" height="280" style="image-rendering: pixelated;"></canvas>
</div>
</div>
<div>
<canvas id="chart-canvas"></canvas>
<canvas id="brain-canvas" width="1200" height="600"></canvas>
</div>
</div>
<div class="col-4">
<canvas id="draw-canvas" width="28" height="28" class="border bg-black"
style="width: 280px; image-rendering: pixelated;"></canvas>
<canvas id="mini-canvas" width="28" height="28" class="border bg-black d-none"></canvas>
<div class="mb-2">
<div class="btn-group btn-group-sm">
<button class="btn btn-dark" id="next">寫入並右移</button>
<button class="btn btn-dark" id="clear">清除畫布</button>
<button class="btn btn-dark" id="detect">偵測畫布</button>
</div>
</div>
<div class="mb-2">
<div class="btn-group btn-group-sm">
<button class="btn btn-dark" onclick="download()">下載圖片</button>
<button class="btn btn-dark" onclick="upload()">上傳圖片</button>
<button class="btn btn-dark" onclick="clearDataCanvas()">清除所有資料</button>
</div>
</div>
<div class="mb-2">
<button class="btn btn-success" id="start">開始訓練</button>
</div>
<pre class="alert alert-secondary w-100 overflow-y-scroll" style="height: 200px;" id="logger"></pre>
</div>
</div>
</div>
<script src="day2.js"></script>
<script>
var SIZE = 28
var dataCanvas = $('#data-canvas')[0]
var dataCtx = dataCanvas.getContext('2d')
var drawCanvas = $('#draw-canvas')[0]
var drawCtx = drawCanvas.getContext('2d')
var markCanvas = $('#mark-canvas')[0]
var markCtx = markCanvas.getContext('2d')
var miniCanvas = $('#mini-canvas')[0]
var miniCtx = miniCanvas.getContext('2d')
var cursorX = 0
var cursorY = 0
var isMouseDown = false
initDataCanvas();
loadCache();
function initDataCanvas() {
dataCtx.fillStyle = 'back'
dataCtx.fillRect(0, 0, 28000, 280);
}
function clearDataCanvas() {
if (confirm('確定要清除?')) {
initDataCanvas();
localStorage.setItem('image', '');
}
}
function loadCache() {
var dataURL = localStorage.getItem('image')
var img = new Image
img.src = dataURL
img.onload = () => dataCtx.drawImage(img, 0, 0)
}
function loadImage(src) {
var img = new Image
img.onload = () => dataCtx.drawImage(img, 0, 0)
img.src = src
}
function download() {
var link = document.createElement('a')
link.download = 'backup.png';
link.href = dataCanvas.toDataURL('image/png')
link.click();
}
function upload() {
const fileInput = document.createElement('input')
fileInput.type = 'file'
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0]
const reader = new FileReader()
reader.onload = (e) => {
const img = new Image()
img.onload = () => dataCtx.drawImage(img, 0, 0)
img.src = e.target.result
}
reader.readAsDataURL(file)
})
fileInput.click()
}
function handleFileSelect() {
const file = event.target.files[0]
}
var chart = new Chart($('#chart-canvas')[0], {
type: 'line',
data: {
labels: [],
datasets: [{
label: '訓練資料通過率', borderWidth: 2
},
{
label: '測試資料通過率', borderWidth: 2
},
]
},
options: {
elements: {
point: {
radius: 0
}
},
scales: {
y: {
beginAtZero: true, min: 0, max: 100
}
},
animation: {
duration: 0
},
}
})
var isTraining = false
$('#start').click(() => {
$('#start').toggleClass('btn-success')
$('#start').toggleClass('btn-danger')
$('#start').text(isTraining ? '開始訓練': '停止訓練')
isTraining ? stop(): start()
isTraining = !isTraining
})
$('#stop').click(() => window.stop())
$('#detect').click(() => window.detect())
$('#saveback').click(() => window.saveback())
$('#next').click(() => {
saveback()
cursorX += 1
loadFromData()
$('#cursor').css({
top: `${cursorY * SIZE}px`, left: `${cursorX * SIZE}px`
})
})
$('#draw-canvas').on('mousedown', () => isMouseDown = true)
$('#draw-canvas').on('mouseup', () => isMouseDown = false)
$('#draw-canvas').on('mousemove', (e) => {
if (!isMouseDown) return
var rect = drawCanvas.getBoundingClientRect()
var x = Math.floor((e.clientX - rect.left) / 10)
var y = Math.floor((e.clientY - rect.top) / 10)
drawCtx.fillStyle = 'white'
drawCtx.beginPath()
drawCtx.arc(x, y, 1, 0, 3 * Math.PI)
drawCtx.fill()
})
$('#mark-canvas').click(e => {
var rect = dataCanvas.getBoundingClientRect()
cursorX = Math.floor((e.clientX - rect.left) / SIZE)
cursorY = Math.floor((e.clientY - rect.top) / SIZE)
loadFromData()
$('#cursor').css({
top: `${cursorY * SIZE}px`, left: `${cursorX * SIZE}px`
})
})
$('#upload').change(e => {
var img = new Image()
img.onload = () => dataCtx.drawImage(img, 0, 0)
img.src = URL.createObjectURL(e.target.files[0])
})
$('#clear').click(() => {
drawCtx.fillStyle = 'black'
drawCtx.fillRect(0, 0, SIZE, SIZE)
})
function loadFromData() {
drawCtx.clearRect(0, 0, SIZE, SIZE)
drawCtx.drawImage(dataCanvas, cursorX * SIZE, cursorY * SIZE, SIZE, SIZE, 0, 0, SIZE, SIZE)
}
function saveback() {
dataCtx.drawImage(drawCanvas, 0, 0, SIZE, SIZE, cursorX * SIZE, cursorY * SIZE, SIZE, SIZE)
var data = dataCanvas.toDataURL('image/jpg')
localStorage.setItem('image', data)
}
function getHandDrawnData() {
var arr = []
miniCtx.drawImage(drawCanvas, 0, 0, SIZE, SIZE)
var data = miniCtx.getImageData(0, 0, SIZE, SIZE).data
for (var i = 0; i < data.length; i += 4) {;
var avg = (data[i + 0] + data[i + 1] + data[i + 2]) / 3 / 225
arr.push(avg)
}
return arr
}
function getImageData(x, y, width, height) {
var list = []
var data = dataCtx.getImageData(x, y, width, height).data
for (var i = 0; i < data.length; i += 4) {
var avg = (data[i + 0] + data[i + 1] + data[i + 2]) / 3 / 225
list.push(avg)
}
return list
}
function addLog(content) {
$('#logger').prepend(`<span>${JSON.stringify(content)}</span><br/>`)
}
function chartLog(trainRate, testRate) {
chart.data.labels.push(chart.data.labels.length + 1)
chart.data.datasets[0].data.push(trainRate)
chart.data.datasets[1].data.push(testRate)
chart.update()
}
</script>
</body>
</html>
```
-CSS: (no css)
-Javascript:
```javascript
// 產生指定長度的陣列
function makeArray(x) {
return (new Array(x)).fill(0);
}
// 產生指定長寬的矩陣,用來作為神經層之間的權重
function makeMatrix(x, y) {
var grid = makeArray(x);
return grid.map(_ => makeArray(y).map(rand));
}
// 產生 -0.5 至 0.5 之間的隨機小數
function rand() {
return Math.random() - 0.5;
}
// 激活函式
function sigmoid(x) {
return Math.tanh(x);
}
// 激活函式導數
function dsigmoid(x) {
return 1 - x * x;
}
// 矩陣相乘,用來作為正向傳遞的計算
function dot(arr, mx) {
var list = makeArray(mx[0].length);
for (var i = 0; i < mx[0].length; i++) {
for (var j = 0; j < arr.length; j++) {
list[i] += arr[j] * mx[j][i];
}
}
return list;
}
// 矩陣反轉,用來作為反向傳遞的計算
function transpose(mx) {
return mx[0].map((_, i) => mx.map(row => row[i]));
}
// 根據誤差更新神經網路的矩陣
function updateWeight(mx, arr1, arr2, rate = 0.01) {
for (var i = 0; i < arr1.length; i++) {
for (var j = 0; j < arr2.length; j++) {
mx[i][j] += arr1[i] * arr2[j] * rate;
}
}
}
// ------------------------------------------------------------- //
function NN(a, b, c, d) {
var n1 = makeArray(a); //第 1 層神經儲存的數值
var n2 = makeArray(b); //第 2 層神經儲存的數值
var n3 = makeArray(c); //第 3 層神經儲存的數值
var n4 = makeArray(d); //第 4 層神經儲存的數值
var w1 = makeMatrix(a, b); //第 1, 2 層神經之間的權重
var w2 = makeMatrix(b, c); //第 2, 3 層神經之間的權重
var w3 = makeMatrix(c, d); //第 3, 4 層神經之間的權重
// 正向傳遞
function forward(inputs) {
n1 = inputs;
n2 = dot(n1, w1).map(sigmoid);
n3 = dot(n2, w2).map(sigmoid);
n4 = dot(n3, w3).map(sigmoid);
return n4
}
// 反向傳遞
function backward(target, learningRate = 0.001) {
var e4 = target.map((t, i) => t - n4[i]);
var d4 = n4.map(dsigmoid).map((v, i) => v * e4[i]);
var e3 = dot(d4, transpose(w3));
var d3 = n3.map(dsigmoid).map((v, i) => v * e3[i]);
var e2 = dot(d3, transpose(w2));
var d2 = n2.map(dsigmoid).map((v, i) => v * e2[i]);
updateWeight(w3, n3, d4, learningRate);//learningRate will change the speed of running neural network
updateWeight(w2, n2, d3, learningRate);
updateWeight(w1, n1, d2, learningRate);
}
return {
forward, backward
}
}
// ------------------------------------------------------------- //
var training = false; //是否正在訓練
var trainData = []; //訓練資料
var testData = []; //測試資料
var LABEL = 10; //讀取資料的高度 = 類別數量
var LENGTH = 1000; //讀取資料的長度
var CUT = 800; //切割資料長度,區分訓練和測試
var totalTime = 0;
var trainCount = 0;
var nn = NN(28*28, 16, 16, LABEL);
loadImage('mnist_fashion.jpg');
function detect() {
var input = getHandDrawnData();
var output = nn.forward(input); // 784 inputs
var num = output.indexOf(Math.max(...output));
addLog('偵測結果:' +num);
}
// 點擊「開始訓練」按鈕觸發此程式
function start(width, height) {
training = true;
trainData = []; //清除訓練資料
testData = []; //清除測試資料
width = LENGTH;
height = LABEL;
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
var input = getImageData(28*x, 28*y, 28, 28);
var target = makeArray(10);
target[y] = 1;
if (x < CUT) {
trainData.push({
input, target, x, y
});
} else {
testData.push({
input, target, x, y
});
}
}
}
loop(); // 開始訓練迴圈
}
// 點擊「暫停訓練」按鈕觸發此程式
function stop() {
training = false;
}
// 訓練的迴圈
function loop() {
var startTime = Date.now();
markCtx.clearRect(0, 0, 28000, 420); //清除標記
var trainPass = train(trainData); //訓練
var trainPct = Math.floor(trainPass * 100 / trainData.length); //計算訓練通過率
var testPass = test(testData); //測試
var testPct = Math.floor(testPass * 100 / testData.length); //計算測試通過率
var time = (Date.now() - startTime)/1000;
trainCount += 1;
totalTime += time;
var avgTime = (trainCount / totalTime).toFixed(3);
addLog("train pass: "+ trainPct +"%, test pass: "+ testPct +"%, time used:" + time +
's, average time used:' + avgTime + 's, train loop:' + trainCount + 'times');
chartLog(trainPct, testPct);
if (training) setTimeout(loop, 100);
}
// 執行訓練資料
function train(data) {
var count = 0;
for (var i = 0; i < data.length; i++) {
var row = data[i];
var output = nn.forward(row.input);
var result = output.indexOf(Math.max(...output));
var isPass = row.target[result] == 1;
if (isPass) count++;
nn.backward(row.target, 0.01);//low value->slow learning, high value->fast learning.
markCtx.fillStyle = isPass ? 'blue': 'red';
markCtx.fillRect(row.x*28, row.y*28, 28, 28);
}
return count;
}
// 執行測試資料
function test(data) {
var count = 0;
for (var i = 0; i < data.length; i++) {
var row = data[i];
var output = nn.forward(row.input);
var result = output.indexOf(Math.max(...output));
var isPass = row.target[result] == 1;
if (isPass) count++;
markCtx.fillStyle = isPass ? 'green': 'red';
markCtx.fillRect(row.x*28, row.y*28, 28, 28);
}
return count;
}
```
---
## AI自動駕駛
-Javascript:
```javascript
// 設定地圖
initialMaps( [[{"x":9,"y":264},{"x":13,"y":146},{"x":32,"y":72},{"x":71,"y":32},
{"x":128,"y":19},{"x":216,"y":11},{"x":351,"y":9},{"x":494,"y":9},{"x":576,"y":20},
{"x":620,"y":45},{"x":635,"y":87},{"x":637,"y":144},{"x":638,"y":168},{"x":635,"y":196},
{"x":613,"y":216},{"x":579,"y":219},{"x":541,"y":215},{"x":493,"y":204},{"x":434,"y":190},
{"x":377,"y":186},{"x":321,"y":188},{"x":274,"y":191},{"x":239,"y":205},{"x":225,"y":233},
{"x":236,"y":262},{"x":261,"y":274},{"x":291,"y":275},{"x":330,"y":264},{"x":373,"y":253},
{"x":439,"y":248},{"x":527,"y":249},{"x":591,"y":272},{"x":638,"y":337},{"x":628,"y":423},
{"x":553,"y":474},{"x":210,"y":473},{"x":90,"y":446},{"x":19,"y":373},{"x":11,"y":266}],
[{"x":140,"y":140},{"x":130,"y":148},{"x":126,"y":157},{"x":118,"y":202},{"x":117,"y":268},
{"x":141,"y":331},{"x":249,"y":377},{"x":275,"y":379},{"x":466,"y":357},{"x":516,"y":345},
{"x":529,"y":350},{"x":527,"y":360},{"x":470,"y":374},{"x":382,"y":379},{"x":249,"y":377},
{"x":140,"y":332},{"x":117,"y":268},{"x":118,"y":203},{"x":129,"y":149},{"x":178,"y":111},
{"x":302,"y":105},{"x":441,"y":107},{"x":519,"y":117},{"x":542,"y":124},{"x":547,"y":125},
{"x":530,"y":117},{"x":489,"y":111},{"x":441,"y":105},{"x":352,"y":105},{"x":279,"y":106},
{"x":210,"y":108},{"x":178,"y":111},{"x":152,"y":125},{"x":140,"y":138}]]);
var DNA_LENGTH = 30; // DNA 的長度
var generation = 0; // 紀錄目前是第幾代
var cars = []; // 用來存放所有車子角色
for (var i = 0; i < 20; i += 1) {
// 創造車子並初始化設定
var car = new Car();
car.speed = 0; // 設定車速
car.reset(100, 40, 90); // 重置位置 xy 座標 50, 250 並將方向朝向上方
//car.addSensor(60);
car.addSensor(45);
car.addSensor(0);
car.addSensor(-45);
//car.addSensor(-60);
car.gens = randomDNA(30);
car.score = 0;
car.xx = car.x;
car.yy = car.y;
cars.push(car);
}
// 避免緩慢的車子消耗時間,手動進入下一個世代來加速學習
when('keydown', 'space', nextGeneration);
forever(gameloop); //重複不斷執行遊戲迴圈
// 遊戲迴圈
function gameloop () {
print('generation:' + generation);
drawText(cars[0].score, 10, 30);
var count = 0;
for (var i = 0; i < cars.length; i += 1) {
var car = cars[i];
var inputs = car.sensorData.concat(car.speed);
var output = NN(inputs, car.gens);
car.turn(output[0] * 3);
car.speedUp(output[1]/10);
car.color = 'black';
if (car.status == 'running') {
count += 1;
car.score += 1;
}
if (car.speed <= 0){
car.status = 'broken';
}
if (count % 30 == 0) {
var diff = Math.sqrt((car.xx - car.x) ** 2 + (car.yy - car.y) ** 2);
car.score += diff;
car.xx = car.x;
car.yy = car.y;
}
}
if (count <= 2) {
nextGeneration();
}
cars.sort(function (a, b) {
return b.score - a.score;
});
cars[0].color = 'red';
cars[1].color = 'orange';
}
function nextGeneration () {
console.log('產生下一代車子...');
generation++;
var parentA = cars[0].gens;
var parentB = cars[1].gens;
for (var i = 0; i < cars.length; i += 1) {
var car = cars[i];
car.reset(100, 40, 90); //重置
car.gens = crossover(parentA, parentB);
car.score = 0;
car.speed = 0;
}
}
// 兩組基因交配產生新的基因
function crossover(a, b) {
var dna = [];
for (var i = 0; i < a.length; i += 1) {
dna.push(Math.random() > 0.5 ? a[i] : b[i]);
if (Math.random() < 0.1) {
dna[i] = Math.random() * 2 - 1;
}
}
return dna;
}
// 產生隨機的基因組
function randomDNA(length) {
var dna = [];
for (var i = 0; i < length; i += 1) {
dna.push(Math.random() * 2 - 1);
}
return dna;
}
function sigmoid(x) {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
}
// input*4 hidden*5 output*2
function NN(inputs, weights) {
var w = weights;
var [a, b, c, d] = inputs;
var e = a*w[0] + b*w[1] + c*w[2] + d*w[3] ;
var f = a*w[4] + b*w[5] + c*w[6] + d*w[7] ;
var g = a*w[8] + b*w[9] + c*w[10] + d*w[11];
var h = a*w[12] + b*w[13] + c*w[14] + d*w[15];
var i = a*w[16] + b*w[17] + c*w[18] + d*w[19];
e = sigmoid(e);
f = sigmoid(f);
g = sigmoid(g);
h = sigmoid(h);
i = sigmoid(i);
var j = e*w[20] + f*w[21] + g*w[22] + h*w[23] + i*w[24];
var k = e*w[25] + f*w[26] + g*w[27] + h*w[28] + i*w[29];
j = sigmoid(k);
k = sigmoid(k);
return [j, k];
}
```
---
## AI 設計越野車
-HTML:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"></script>
</head>
<body>
<div class="container pt-4">
<div class="row">
<div class="col-lg-7">
<div id="canvas-box"></div>
<button class="btn btn-primary" onclick="nextGeneration()">nextGeneration</button>
</div>
<div class="col-lg-5">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">活躍程度(active)</th>
<th scope="col">是否存活</th>
<th scope="col">前進百進度條</th>
<th scope="col">前進距離(x)</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="col">1</td>
<td scope="col">
<div class="progress">
<div class="progress-bar progress-bar-striped" style="width: 50%"></div>
</div>
</td>
<td scope="col">true/false</td>
<td scope="col">
<div class="progress">
<div class="progress-bar progress-bar-striped bg-warning" style="width: 50%"></div>
</div>
</td>
<td scope="col">
100m
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<style>
#canvas-box {
width: 100%;
}
#canvas-box > canvas {
width: 100%;
}
canvas {
border: 2px solid #999;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/poly-decomp@0.2.1/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>
</body>
</html>
```
-CSS:
```css
/* 設定整個頁面內容水平置中、內寬為 30 像素:*/
body {
text-align: center;
padding: 30px;
}
/* 設定圖片的寬度為銀幕一半寬 */
img {
max-width: 50%;
}
/* 設定文字的顏色為淡黑色 */
p {
color: #555555;
}
```
-Javascript:
```javascript
var generation = 20; // 一個世代的個數
var rate = 0.15; // 變異機率
var current = 0; //當前是第幾世代
var cars = []; //存放車子角色
// L09 初始調整: 每 20ms -> 100ms
setInterval(gameloop, 100);
// 設定隨機地面
var arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (var i = 0; i < 100; i++) {
arr.push(2 * Math.random() - 1);
}
// L09 初始調整: 從 1~-1, 修改為 0.6 ~-0.6
var endX = createGround(arr, 0.6, -0.6);
// 產生下一個世代
function nextGeneration() {
current += 1;
if (current > 1) {
var parentA = cars[0].genes;
var parentB = cars[1].genes;
var parentC = cars[2].genes;
var parentD = cars[3].genes;
}
cars.forEach(function (car) {
car.destory();
});
cars.length = 0;
// L09 初始調整: 20 改為 generation
for (var i = 0; i < generation; i++) {
if (current == 1) {
var genes = randomGenes();
} else {
var genes = crossover(parentA, parentB, parentC, parentD);
}
a = genes.slice(0, 8);
b = genes.slice(8, 12);
var car = createCar(a, b);
car.genes = genes;
cars.push(car);
focusOnCar(car);
}
}
// 遊戲迴圈
function gameloop() {
var best = cars[0];
var count = 0;
for (var i = 0; i < cars.length; i++) {
var car = cars[i];
if (car.x > best.x) {
best = car;
}
// L09 初始調整: 將 true 移除
if (car.isDie) {
count += 1;
}
}
focusOnCar(best);
// L09 初始調整: 20 改為 generation
if (count >= generation) {
nextGeneration();
}
updateTable(cars);
}
// 產生車子基因
function randomGenes() {
var genes = [];
for (var i = 0; i < 8; i++) {
// L09 初始調整: 將 100 調降為 70
genes.push(Math.random()*70+30); // 30 ~ 100
}
for (var i = 0; i < 2; i++) {
// 隨機車輪的位置(頂點 0~7)
genes.push(Math.floor(Math.random()*8));
// 隨機車輪的大小
// L09 初始調整: 將 50 調降為 30
genes.push(Math.random()*30+10); // 10 ~ 30
}
return genes;
}
// 傳入父母基因產生新的子基因
function crossover(genA, genB, genC, genD) {
var genes = [];
for (var i = 0; i < 12; i++) {
var rand = Math.floor(Math.random() * 4); // 0->1 => 0, 1, 2, 3
if (rand == 0) genes.push(genA[i]);
if (rand == 1) genes.push(genB[i]);
if (rand == 2) genes.push(genC[i]);
if (rand == 3) genes.push(genD[i]);
}
return genes;
}
// 更新狀態表格
function updateTable(cars) {
$('tbody').empty();
for (var i = 0; i < cars.length; i++) {
var car = cars[i];
var distance = Math.floor(car.x - 300);
var s = `<tr>
<td scope="col">${i+1}</td>
<td scope="col">
<div class="progress">
<div class="progress-bar progress-bar-striped" style="width: ${car.active}%"></div>
</div>
</td>
<td scope="col">${car.isDie}</td>
<td scope="col">
<div class="progress">
<div class="progress-bar progress-bar-striped bg-warning" style="width: ${Math.floor(distance*100/endX)}%"></div>
</div>
</td>
<td scope="col">${distance}m</td>
</tr>`;
$('tbody').append(s);
}
}
```
---
## 小精靈遊戲
-Javascript:
```javascript
// 強制設定模式 chase, scatter, frightened
// forceMode = 'chase' // 設定強制模式
immortal = true // 無敵狀態
redTarget.hidden = false;
blueTarget.hidden = false;
pinkTarget.hidden = false;
orangeTarget.hidden = false;
player.AI = function () {
if (key.up) player.nextDirection = 0;
if (key.right) player.nextDirection = 90;
if (key.down) player.nextDirection = 180;
if (key.left) player.nextDirection = 270;
};
/* ========== 預設 AI ========== */
Blinky.AI = function () {
var arr = getDirections(Blinky.X, Blinky.Y, Blinky.direction);
var rand = Math.floor(Math.random()*arr.length);
Blinky.nextDirection = arr[rand];
};
Pinky.AI = function () {
var arr = getDirections(Pinky.X, Pinky.Y, Pinky.direction);
var rand = Math.floor(Math.random()*arr.length);
Pinky.nextDirection = arr[rand];
};
Inky.AI = function () {
var arr = getDirections(Inky.X, Inky.Y, Inky.direction);
var rand = Math.floor(Math.random()*arr.length);
Inky.nextDirection = arr[rand];
};
Clyde.AI = function () {
var arr = getDirections(Clyde.X, Clyde.Y, Clyde.direction);
var rand = Math.floor(Math.random()*arr.length);
Clyde.nextDirection = arr[rand];
};
/* ========== 追逐模式下的 AI ========== */
Blinky.chaseAI = function () {
redTarget.moveTo(player);
var arr = getDirections(Blinky.X, Blinky.Y, Blinky.direction);
Blinky.toward(redTarget);
Blinky.nextDirection = closest(arr, Blinky.direction);
};
Pinky.chaseAI = function () {
pinkTarget.moveTo(player);
pinkTarget.direction = player.direction;
pinkTarget.stepForward(15*4);
var arr = getDirections(Pinky.X, Pinky.Y, Pinky.direction);
Pinky.toward(pinkTarget);
Pinky.nextDirection = closest(arr, Pinky.direction);
};
Inky.chaseAI = function () {
blueTarget.moveTo(player);
blueTarget.direction = player.direction;
blueTarget.stepForward(15*4);
blueTarget.toward(Blinky);
var d = blueTarget.distanceTo(Blinky);
blueTarget.stepForward(-d);
var arr = getDirections(Inky.X, Inky.Y, Inky.direction);
Inky.toward(blueTarget);
Inky.nextDirection = closest(arr, Inky.direction);
};
Clyde.chaseAI = function () {
if(Clyde.distanceTo(player) > 120) {
orangeTarget.moveTo(player);
}
else {
orangeTarget.moveTo(117, 465);
}
var arr = getDirections(Clyde.X, Clyde.Y, Clyde.direction);
Clyde.toward(orangeTarget);
Clyde.nextDirection = closest(arr, Clyde.direction);
};
/* ========== 巡邏模式下的 AI ========== */
Blinky.scatterAI = function () {
redTarget.moveTo(522, 15);
var arr = getDirections(Blinky.X, Blinky.Y, Blinky.direction);
Blinky.toward(redTarget);
Blinky.nextDirection = closest(arr, Blinky.direction);
};
Pinky.scatterAI = function () {
pinkTarget.moveTo(117, 15);
var arr = getDirections(Pinky.X, Pinky.Y, Pinky.direction);
Pinky.toward(pinkTarget);
Pinky.nextDirection = closest(arr, Pinky.direction);
};
Inky.scatterAI = function () {
blueTarget.moveTo(522, 465);
var arr = getDirections(Inky.X, Inky.Y, Inky.direction);
Inky.toward(blueTarget);
Inky.nextDirection = closest(arr, Inky.direction);
};
Clyde.scatterAI = function () {
orangeTarget.moveTo(117, 465);
var arr = getDirections(Clyde.X, Clyde.Y, Clyde.direction);
Clyde.toward(orangeTarget);
Clyde.nextDirection = closest(arr, Clyde.direction);
};
/* ========== 返回鬼屋模式的 AI ========== */
Blinky.backToHouseAI = function () {
redTarget.moveTo(320, 240);
var arr = getDirections(Blinky.X, Blinky.Y, Blinky.direction);
Blinky.toward(redTarget);
Blinky.nextDirection = closest(arr, Blinky.direction);
};
Pinky.backToHouseAI = function () {
pinkTarget.moveTo(320, 240);
var arr = getDirections(Pinky.X, Pinky.Y, Pinky.direction);
Pinky.toward(pinkTarget);
Pinky.nextDirection = closest(arr, Pinky.direction);
};
Inky.backToHouseAI = function () {
blueTarget.moveTo(320, 240);
var arr = getDirections(Inky.X, Inky.Y, Inky.direction);
Inky.toward(blueTarget);
Inky.nextDirection = closest(arr, Inky.direction);
};
Clyde.backToHouseAI = function () {
orangeTarget.moveTo(320, 240);
var arr = getDirections(Clyde.X, Clyde.Y, Clyde.direction);
Clyde.toward(orangeTarget);
Clyde.nextDirection = closest(arr, Clyde.direction);
};
function closest(arr, target) {
arr.sort(function (a, b) {
var a = Math.abs(target - a);
var b = Math.abs(target - b);
if (a > 180) a = 360 - a;
if (b > 180) b = 360 - b;
return a - b;
});
return arr[0];
}
function getDirections(x, y, direction) {
var arr = [];
if (map[y - 1][x] == ' ' && direction != 180) arr.push(0);
if (map[y][x + 1] == ' ' && direction != 270) arr.push(90);
if (map[y + 1][x] == ' ' && direction != 0) arr.push(180);
if (map[y][x - 1] == ' ' && direction != 90) arr.push(270);
return arr;
}
```
---
## 演算法
> 1.選擇排序法:
--python--ex:
```python
import random
nums = random.randint(1, 100)
count = 0;
for i in range(1, 101):
if i == nums:
print(i);
break;
else:
count += 1
print(count)
```
--Javascript--ex:
```javascript
var bars = new Bars(20);
bars.setSpeed(20);
for (var j = 0; j < 19; j++) {
var best = j;
for (var k = j + 1; k < 20; k++) {
if (bars.get(k) < bars.get(best)) { //反向排列更動'>'
best = k;
}
}
bars.swap(j, best);
}
```
> 2.氣泡排序法:
--python--ex:
```python
import random
data = [x for x in range(1, 21)]
random.shuffle(data);
print(*data)
n = len(data)
for i in range(0, n - 1):
for k in range(0, n - i - 1):
if data[k] > data[k+1]: #反向排列更動'<'
temp = data[k];
data[k] = data[k+1];
data[k + 1] = temp;
print(data);
print(*data)
```
--Javascipt--ex:
```javascript
var bars = new Bars(Math.floor(Math.random()* 20));
bars.setSpeed(20);
for (var k = 20; k > 0; k--) {
for (var i = 0; i < k; i++) {
if (bars.get(i) > bars.get(i + 1)) {
bars.swap(i, i+1);
}
}
}
```
> 3.二分排序法:
--python--ex:
```python
import random
nums = random.randint(1, 100)
lower = 0
upper= 100
i = 50
count = 0
while True:
if i == nums:
print(i);
print(count);
break
count += 1;
if i < nums:
lower = i;
i = int((lower + upper) / 2)
elif i > nums:
upper = i;
i = int((lower + upper) / 2)
print ('i = %d, lower = %d, upper = %d' %(i , lower, upper));
```
--Javascript//ex:
```javascript
// 哈利波特神秘的魔法石 - JK羅琳
var b1 = 'Harry Potter and the Philosopher’s Stone by JK Rowling';
// 愛麗絲夢遊仙境 - 查爾斯·路特維奇
var b2 = 'Alice’s Adventures in Wonderland by Lewis Carroll';
var up = 1000;
var low = 0;
for (var i = 0; i < 1000; i++) {
var center = Math.floor((up + low) / 2);
var result = books.search(center);
if (result == b1) {
break;
}
if (result > b1) {
up = center;
}
if (result < b1) {
low = center;
}
}
```
+HTML:
```html
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<div class="box panel">
<input class="box" type="number" min="0" max="9" v-model="x" @change="change">層
<input class="box" type="number" min="0" max="9" v-model="y" @change="change">格
<input class="box" type="number" min="0" max="9" v-model="z" @change="change">本
<button class="box" v-if="isFocus" @click="clear">清除</button>
<p>{{target}}</p>
</div>
<div class="grid" :class="{dark: isFocus}">
<div ref="offset" :style="offset()">
<div class="row" v-for="(row, x) in grid">
<div class="col" v-for="(col, y) in row">
<div class="book" v-for="(book, z) in col" :class="bookClass(x, y, z)"></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
```
+CSS:
```css
body {
font-family: Monospace;
}
.box {
padding: 10px;
border: 2px solid #bbbbbb;
border-radius: 10px;
margin: 0px 5px 0px 10px;
color: #eee;
background-color: #111111CC;
}
.panel {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
width: 60%;
z-index: 100;
text-align: center;
font-size: 14px;
font-weight: bold;
}
.panel input {
text-align: center;
outline: none;
}
.grid {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #131417;
overflow: hidden;
}
.grid > div {
transition: transform 0.5s;
}
.row {
height: 120px;
width: 2500px;
border-bottom: 10px solid #c7a679;
display: flex;
}
.col {
width: 250px;
display: flex;
align-items: flex-end;
justify-content: center;
}
.book {
width: 10px;
height: 60px;
border: 2px solid #111215;
border-radius: 3px 3px 3px 3px;
}
.book-0 {
width: 12px;
height: 65px;
background: linear-gradient(to right, #6495ED , #84b5ED);
}
.book-1 {
width: 10px;
height: 78px;
background: linear-gradient(to right, #FF6347 , #ffa494);
}
.book-2 {
width: 15px;
height: 72px;
background: linear-gradient(to right, #556B2F , #91b553);
}
.book-3 {
width: 10px;
height: 64px;
background: linear-gradient(to right, #FA8072 , #ffbdb5);
}
.book-4 {
width: 17px;
height: 61px;
background: linear-gradient(to right, #008080 , #1bcccc);
}
.book-5 {
width: 13px;
height: 85px;
background: linear-gradient(to right, #778899 , #adc4db);
}
.book-6 {
width: 12px;
height: 59px;
background: linear-gradient(to right, #BDB76B , #e8e290);
}
.book-7 {
width: 19px;
height: 73px;
background: linear-gradient(to right, #808000 , #baba11);
}
.book-8 {
width: 12px;
height: 82px;
background: linear-gradient(to right, #8B4513 , #c76b2a);
}
.book-9 {
width: 17px;
height: 73px;
background: linear-gradient(to right, #FF6347 , #ffa494);
}
.book-10 {
width: 13px;
height: 77px;
background: linear-gradient(to right, #A52A2A , #C54A4A);
}
.book-11 {
width: 15px;
height: 64px;
background: linear-gradient(to right, #B8860B , #D8a62B);
}
.book-12 {
width: 19px;
height: 69px;
background: linear-gradient(to right, #FFFACD , #FFFAED);
}
.book-13 {
width: 14px;
height: 75px;
background: linear-gradient(to right, #FF8C00 , #FFAC30);
}
.book-14 {
width: 19px;
height: 85px;
background: linear-gradient(to right, #90EE90 , #B0EEC0);
}
.book-15 {
width: 13px;
height: 82px;
background: linear-gradient(to right, #FFD700 , #FFE730);
}
.book-16 {
width: 9px;
height: 60px;
background: linear-gradient(to right, #F5FFFA , #F5FFFA);
}
.book-17 {
width: 15px;
height: 92px;
background: linear-gradient(to right, #FF4500 , #FF7530);
}
.dark .row {
border-color: black;
border-bottom-color: #333333;
}
.dark .book-0:not(.active),
.dark .book-8:not(.active),
.dark .book-3:not(.active),
.dark .book-13:not(.active),
.dark .book-7:not(.active),
.dark .book-9:not(.active) {
background: linear-gradient(to right, #222222 , #444444);
}
.dark .book-2:not(.active),
.dark .book-4:not(.active),
.dark .book-6:not(.active),
.dark .book-16:not(.active),
.dark .book-10:not(.active) {
background: linear-gradient(to right, #333333 , #444444);
}
.dark .book-11:not(.active),
.dark .book-12:not(.active),
.dark .book-1:not(.active),
.dark .book-5:not(.active),
.dark .book-14:not(.active),
.dark .book-15:not(.active),
.dark .book-17:not(.active) {
background: linear-gradient(to right, #111111 , #333333);
}
```
> 4.遺傳演算法:
--Javascript--ex:
```javascript
// 可以修改預設密碼來測試
setPassword('Th%#shwiH]2+~');
var chars = ' abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`.-+/*,[]_~@!#$%^&'; //密碼可能的字元
var pops = []; //存放要猜的密碼
// 初始化產生 20 組基因
for (var j = 0; j < 20; j++) {
var guess = '';
for (var i = 0; i < 13; i++) {
var rand = Math.floor(Math.random()*81);
guess += chars[rand];
}
//password(guess);
pops.push(guess);
}
// 按下空白按鍵來破解金庫
on('keydown', 'space', nextGeneration);
function nextGeneration () {
// // 學生遊戲試玩,開始實作時註解或移除
// var s = prompt('請輸入 21 個由英文字母大小寫、數字、空白所組成的密碼');
// var r = password(s);
// alert(`你輸入的密碼中只有 ${r} 個字是正確的!`);
var arr = [];
for (var l = 0; l < 20; l++) {
arr.push({score : password(pops[l]), gene : pops[l]});
}
//console.log(arr);
// for (var k = 0; k < 20; k++) {
// var result = password(pops[k]);
// console.log(result);
// }
arr.sort(function(a, b) {
return b.score - a.score;
});
var parentA = arr[0].gene;
var parentB = arr[1].gene;
for (var n = 0; n < 20; n++) {
pops[n] = crossover(parentA, parentB);
}
}
// 將兩組密碼進行組合
function crossover (a, b) {
var child_gene = '';
for (var h = 0; h < 13; h++) {
if (Math.random() < 0.1) {
var rand = Math.floor(Math.random() * 81);
child_gene += chars[rand];
} else {
if (Math.random() < 0.5) {
child_gene += a[h];
} else {
child_gene += b[h];
}
}
}
return child_gene;
}
```
> 5.深度優先搜尋法:
--Javascript--ex:
```javascript
// // 老鼠初始化的位置
// var x = Math.floor(Math.random() * 31);
// var y = Math.floor(Math.random() * 23);
// var a = Math.floor(Math.random() * 31);
// var b = Math.floor(Math.random() * 23);
var x = 1;
var y = 0;
var a = 31;
var b = 23;
var width = 20;
var time = setTimeout(function(x, y) {
}, 500);
forever(loop);
// 遊戲迴圈
function loop () {
pen.fillColor = "orange";
pen.drawRect(a*width + 1, b*width + 1, width - 2, width - 2);
pen.fillColor = 'red';
pen.drawRect(x*width + 1, y*width + 1, width - 2, width - 2);
//手動
if (key.up && maze[x][y].up) {
y -= 1;
}
if (key.down && maze[x][y].down ) {
y += 1;
}
if (key.right && maze[x][y].right) {
x += 1;
}
if (key.left && maze[x][y].left) {
x -= 1;
}
//............................................
//自動
maze[x][y].color = 'lightblue';
if (maze[x][y - 1].color == 'white' && maze[x][y].up) {
y -= 1;
}
else if (maze[x][y + 1].color == 'white' && maze[x][y].down ) {
y += 1;
}
else if (maze[x + 1][y].color == 'white' && maze[x][y].right) {
x += 1;
}
else if (maze[x - 1][y].color == 'white' && maze[x][y].left) {
x -= 1;
} else {
maze[x][y].color = 'yellow';
if (maze[x][y + 1].color == 'lightblue' && maze[x][y].down) {
y += 1;
}
else if (maze[x + 1][y].color == 'lightblue' && maze[x][y].right) {
x += 1;
}
else if (maze[x][y - 1].color == 'lightblue' && maze[x][y].up) {
y -= 1;
}
else if (maze[x - 1][y].color == 'lightblue' && maze[x][y].left) {
x -= 1;
}
}
if (x == a && y == b) {
stop();}
}
```
> 6.線性搜尋法:
--Javascript--ex:
```javascript
// 哈利波特神秘的魔法石 - JK羅琳
var b1 = 'Harry Potter and the Philosopher’s Stone by JK Rowling';
// 愛麗絲夢遊仙境 - 查爾斯·路特維奇
var b2 = 'Alice’s Adventures in Wonderland by Lewis Carroll';
var up = 1000;
var low = 0;
for (var i = 0; i < 1000; i++) {
var result = books.search(i);
if (result == b1) {
break;
}
}
```
** HTML、CSS的程式請參照二分搜尋法
> 7.廣度優先搜尋法 // 最佳優先搜尋法:
--Javascript--ex:
```javascript
maze.hideSprite = false; //是否隱藏地形圖片
var start = maze[2][11]; //起點格子
var end = maze[29][11]; //終點格子
var back = undefined; //繪製綠色格子用
var player = createTarget('hero.png', 2, 11); //創造人物
var box = createTarget('box.png', 29, 11); //創造寶箱
randomBlock(0.35); // 0.35 的機率隨機生成障礙物
clearRect(start, 1); //清除起點2格內的障礙物
clearRect(end, 1); //清除終點2格內的障礙物
var arr = [start]; //存放要探索的格子
forever(loop); //不斷執行遊戲迴圈
// 遊戲迴圈
function loop () {
if (arr.length > 0) { //判斷還有沒有格子還需要探索
arr.sort(function(a, b) {
return getDistance(a, end) - getDistance(b, end);
});
var cell = arr.shift();
cell.color = 'orange';
var x = cell.x;
var y = cell.y;
if (maze[x+1][y].color == 'white') {
maze[x+1][y].color = 'red';
maze[x+1][y].from = 'left';
arr.push(maze[x+1][y]);
}
if (maze[x-1][y].color == 'white') {
maze[x-1][y].color = 'red';
maze[x-1][y].from = 'right';
arr.push(maze[x-1][y]);
}
if (maze[x][y-1].color == 'white') {
maze[x][y-1].color = 'red';
maze[x][y-1].from = 'down';
arr.push(maze[x][y-1]);
}
if (maze[x][y+1].color == 'white') {
maze[x][y+1].color = 'red';
maze[x][y+1].from = 'up';
arr.push(maze[x][y+1]);
}
if (cell == end) {
arr.length = 0;
back = end;
}
} else { //如果沒有格子需要探索,就開始繪製路徑
back.color = 'green';
if (back.from == 'up') {
back = maze[back.x][back.y-1];
}
else if (back.from == 'down') {
back = maze[back.x][back.y+1];
}
else if (back.from == 'right') {
back = maze[back.x+1][back.y];
}
else if (back.from == 'left') {
back = maze[back.x-1][back.y];
}
}
if (back == start) {
var x = player.x;
var y = player.y;
if (maze[x+1][y].color == 'green' && maze[x+1][y].from == 'left') {
player.x += 1; }
if (maze[x-1][y].color == 'green' && maze[x-1][y].from == 'right') {
player.x -= 1;
}
if (maze[x][y-1].color == 'green' && maze[x][y-1].from == 'down') {
player.y -= 1;
}
if (maze[x][y+1].color == 'green' && maze[x][y+1].from == 'up') {
player.y += 1;
}
}
};
// 計算a, b 兩個格子之間的距離
function getDistance(a, b) {
return Math.sqrt((a.x - b.x)**2 + (a.y - b.y)**2);
}
```
> 8.排除破解法 (+ 暴力破解法):
--Javascript--ex:
```javascript
$('#start').click(start); //開始遊戲
$('#guess').click(function () {
var str = prompt('輸入四位不重複數字');
guess(str); //將輸入的數字丟進遊戲去猜
});
$('#crack').click(crack); //破解遊戲
var answer = undefined; //存放解答
var count = 0; //紀錄猜的字數
start(); //預設開始遊戲
// 開始新的一局遊戲
function start () {
$('#textarea').append('\n========== 開始新的遊戲 ==========\n\n');
count = 0; //歸零紀錄猜的次數
var list = getList();
var rand = Math.floor(Math.random() * 5040);
answer = list[rand];
//console.log(answer);
}
// 傳入四位數字的字串 str 並將結果顯示到畫面上
function guess (str) {
var result = diff(str, answer);
count++;
$('#textarea').append(`${count} 猜${str} A:${result.a} B:${result.b}\n`);
if (result.a == 4) {
$('#textarea').append('\ncorrect !!!!!\n');
}
return result;
}
// 取得所有可能的答案的組合
function getList () {
var list = [];
for (var i = 122; i< 9877; i++) {
var t = i.toString();
if (t.length < 4) {
t = "0" + t;
}
if (t[0] != t[1] && t[0] != t[2] && t[0] != t[3] && t[1] != t[2] && t[1] != t[3] &&t[2] != t[3]) {
list.push(t);
}
// list.push(t);
}
return list;
}
// 比較 s1, s2 並返回一帶有 a,b 資訊個物件來表示結果
// a 表示位置一樣且數字一樣
// b 表示數字有出現,但位置不一樣
function diff (s1, s2) {
var a = 0;
var b = 0;
for (var k = 0; k < 4; k++) {
if (s1[k] == s2[k]) {
a++;
}
var idx = s2.indexOf(s1[k]);
if (idx != -1 && idx != k) {
b++;
}
}
// { a: a, b: b } 物件中
// 冒號左邊的 a, b 是屬性
// 冒號右邊的 a, b 其對應的資料(var a = 0; var b = 0;)
return {
a: a, b: b
};
}
// 用程式自動破解 1A2B 遊戲
function crack () {
var list = getList();
//暴力破解法
// for (var i = 0; i < list.length; i++) {
// var result = guess(list[i]);
// if (result.a == 4) {
// break;
// }
// }
//排除破解法
for (var i = 0; i < 5040; i++) {
var g = list.pop();
var result = guess(g);
if (result.a == 4) {
break;
}
for (var k = 0; k < list.length; k++) {
var result2 = diff(list[k], g);
if (result.a != result2.a || result.b != result2.b) {
list.splice(k, 1);
k--;
}
}
}
}
```
+CSS:
```css
body {
text-align: center;
background-color: #25313e;
font-family: Arial;
}
h1 {
color: #607489;
margin: 20px;
}
textarea {
width: 350px;
height: 350px;
padding: 15px;
border: 1px solid #aaa;
border-radius: 3px;
color: #ccc;
box-shadow: 0 0.25rem 0.5rem #12181e;
background-color: #191919;
text-align: center;
font-size: 16px;
line-height: 20px;
font-family: Monospace;
}
button {
padding: 10px;
color: #eee;
margin: 10px 5px;
border: 1px solid #aaa;
border-radius: 3px;
box-shadow: 0 0.25rem 0.5rem #12181e;
font-size: 1rem;
cursor: pointer;
}
button.red {
background-color: #fc4048;
}
button.yellow {
background-color: #fd9409;
}
button.green {
background-color: #1fc3b2;
}
```
+HTML:
```html
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
</head>
<body>
<h1>1A2B 推理遊戲</h1>
<textarea id="textarea" disabled autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
========== 遊戲規則說明 ==========
密碼是由 4 個不同的數字組成
每次猜完,電腦會返回 A、B 兩個數字結果
A 表示數字猜對 且 位置正確
B 表示數字猜對 但 位置錯誤
</textarea>
<br/>
<button id="start" class="green">開始新的遊戲</button>
<button id="guess" class="yellow">猜密碼</button>
<button id="crack" class="red">自動破解</button>
</body>
</html>
```
> 9.貪婪搜尋法:
--Javascript--ex:
```javascript
// var a = Math.floor(Math.random() * 9);
// grid[a] = 'o';
forever(loop); //不斷執行遊戲迴圈
//遊戲迴圈中印出格子分數
function loop () {
for (var i = 0; i < grid.length; i++) {
if (grid[i] == '') {
grid[i] = 'o';
var score = evaluate(grid);
grid[i] = 'x';
score += evaluate(grid);
grid[i] = '';
// showScore(score, i);
}
}
}
function AI (grid) {
var bestScore = -1;
var bestIdx = 0;
for (var i = 0; i < grid.length; i++) {
if (grid[i] == '') {
grid[i] = 'o';
var score = evaluate(grid);
grid[i] = 'x';
score += evaluate(grid);
if (score > bestScore) {
bestScore = score;
bestIdx = i;
}
grid[i] = '';
// showScore(score, i);
}
}
grid[bestIdx] = 'x';
}
//評估函式
function evaluate (grid) {
var a = getScore(grid[0], grid[1], grid[2]);
var b = getScore(grid[3], grid[4], grid[5]);
var c = getScore(grid[6], grid[7], grid[8]);
var d = getScore(grid[0], grid[3], grid[6]);
var e = getScore(grid[1], grid[4], grid[7]);
var f = getScore(grid[2], grid[5], grid[8]);
var g = getScore(grid[0], grid[4], grid[8]);
var h = getScore(grid[2], grid[4], grid[6]);
return a + b + c + d + e + f + g + h;
}
//計算某一條線的分數
function getScore (a, b, c) {
var line = a + b + c;
if (line == 'o' || line == 'x') {
return 1;
} else if (line == 'oo' || line == 'xx') {
return 10;
} else if (line == 'ooo' || line == 'xxx') {
return 100;
}else {
return 0;
}
}
```
> 10.凱薩密碼演算法:
--Javascript--ex:
```javascript
// a-z 字母
var alphabet = 'abcdefghijklmnopqrstuvwxyz';
//當「加密」按鈕被點擊就執行 encrypt 函式
$('.js-encrypt').click(encrypt);
//當「解密」按鈕被點擊就執行 decrypt 函式
$('.js-decrypt').click(decrypt);
//加密
function encrypt () {
var text = $('.js-text').val();
var offset = $('.js-offset').val();
offset = parseInt(offset);
//console.log(offset);
//console.log(text);
var code = '';
for (var i = 0; i < text.length; i++){
var idx = alphabet.indexOf(text[i]);
if (idx != -1) {
idx = (idx + offset) % 26;
code = code + alphabet[idx];
} else {
code = code + text[i];
}
}
$('.js-text').val(code);
//console.log(code);
}
//解密
function decrypt () {
var text = $('.js-text').val();
var offset = $('.js-offset').val();
offset = parseInt(offset);
//console.log(offset);
//console.log(text);
var code = '';
for (var i = 0; i < text.length; i++){
var idx = alphabet.indexOf(text[i]);
if (idx != -1) {
idx = (idx - offset + 26) % 26;
code = code + alphabet[idx];
} else {
code = code + text[i];
}
}
$('.js-text').val(code);
//console.log(code);
}
```
+HTML:
```html
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body class="py-4 px-5">
<h3 class="text-center">凱薩密碼</h3>
<div class="form-group">
<textarea class="form-control js-text" rows="8" placeholder="要加密解密的訊息...">要加密解密的訊息...(英文)
</textarea>
</div>
<div class="form-group">
<input class="form-control js-offset" type="number" placeholder="位移" value="0">
</div>
<div class="text-center">
<button class="btn btn-warning js-encrypt">加密</button>
<button class="btn btn-danger js-decrypt">解密</button>
</div>
</body>
</html>
```
+CSS:
```css
body {
background-color: #222;
background-image: url('dust.png');
}
```
> 11.XOR 加密演算法:
--Javascript--ex:
```javascript
//當「加密」按鈕被點擊就執行 encrypto 函式
$(".js-encrypto").click(encrypto);
//加密
function encrypto () {
var text = $('.js-text').val();
var key = $('.js-key').val();
var code = '';
for (var i = 0; i < text.length; i++){
var a = text[i].charCodeAt();
var b = key[i % key.length].charCodeAt();
var c = a ^ b;
//console.log(a + '^' + b + '=' + c);
code += String.fromCharCode(c);
}
$('.js-text').val(code);
}
```
+HTML:
```html
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
</head>
<body class="py-4 px-5">
<h3 class="text-center">加密解密神器</h3>
<p class="text-center">
想寫日記但又不想被爸媽看懂?
<br>
想寫情書告白但是不想讓草稿被發現?
<br>
想與心儀的對象偷偷傳遞曖昧訊息?
<br>
通通就交給這個加解密神器吧!
</p>
<div class="form-group">
<textarea class="form-control js-text" rows="8" placeholder="要加密解密的訊息..."></textarea>
</div>
<div class="form-group">
<input class="form-control border-warning js-key" placeholder="金鑰">
</div>
<div class="text-center">
<button class="btn btn-primary js-encrypto">加解密</button>
</div>
</body>
</html>
```
+CSS:
```css
body {
background-color: #222;
background-image: url('dust.png');
}
```
---
沒甚麼要寫的東西了 88