---
# System prepended metadata

title: ㄅㄅㄅㄅㄅ宗の部落格

---

# *ㄅㄅㄅㄅㄅ宗の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

