## 計算機概論Lab-8
### javascript

<p>https://hackmd.io/@IMOK/Lab8</p>
---
<img src="https://hackmd.io/_uploads/ryUSIqnJT.jpg" width=400 style="border-radius:1000px;"/>
講師: 賴昱有
---
## 15puzzle game
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!---
width=device-width 表示網頁的寬度應該等於設備的寬度。
確保網頁在不同設備上有適當的寬度。
initial-scale=1.0 表示初始的縮放比例為1.0。
這確保了網頁在載入時不進行縮放
--->
<title>15 Puzzle</title>
<link rel="stylesheet" href="15puzzle.css">
</head>
<body>
<div id="puzzle"></div>
<div id="controls">
<button id="solve">Solve</button>
<button id="scramble">Scramble</button>
</div>
<script src="script.js"></script>
</body>
</html>
```
----
## div(division)
```html
<div>
<!-- 這裡可以包含其他HTML元素,如文本、圖片、表格等 -->
<p>This is a paragraph inside a div.</p>
<img src="example.jpg" alt="An example image">
</div>
```
<font size =4>經常作為CSS selector的容器,以便對特定區域設計樣式</font>
---
## CSS複習
<font size =5>定義每個文字的顏色、物件的外框、element 之間的距離,甚至撰寫動畫等等。</font>
<font size =5>CSS語法重點:</font>
<font size =5>1. selector 語法:用來指定 HTML 中,哪些 element 要套用這個樣式
2. 樣式描述:用來說明指定的 elements 要用什麼樣子去顯示</font>
----
## selectors種類
<font size =5>• Simple selectors (select elements based on name, id, class)
• Combinator selectors (select elements based on a specific relationship between them)
• Pseudo-class selectors (select elements based on a certain state)
• Pseudo-elements selectors (select and style a part of an element)
• Attribute selectors (select elements based on an attribute or attribute value)</font>
----
## Simple Selectors
<font size =5>• Element selector
• ID selector
• Class selector
• Grouping selector
• Universal selector</font>
----
## Element selector
<font size =5>選擇的 element 名稱來設定該類 element 的顯示樣式</font>
```css
p {
color: yellow;
}
div {
height: 50px;
width: 60px;
}
```
----
## ID selector
<font size =5>幫 element 設定 id attribute ,再利用這個 id 來設定不同的顯示樣式</font>
<font size =5>HTML:</font>
```html
<div id="block"></div>
```
<font size =5>CSS:</font>
```css
#block {
height: 50px;
width: 50px;
color: red;
}
```
----
## Class selector
<font size =5>在 css 中先定義好一個種類的樣式,
然後在HTML 中透過 class attribute 來選擇要使用哪一個種類的樣式顯示。</font>
<font size =5>CSS:</font>
```css
.redBlock {
height: 50px;
width: 50px;
color: red;
}
```
<font size =5>HTML:</font>
```html
<div class="redBlock"></div>
```
----
## Grouping selector
<font size =5>group selector 的寫法可以省略重複的樣式定義。</font>
```css
p {
color: red;
}
input {
color: red;
}
div {
color: red;
}
```
```css
p, input , div {
color: red;
}
```
----
## Universal selector
<font size =5>對所有的 element 進行樣式定義。</font>
```css
* {
color: red;
}
```
----
## CSS Box Model

<font size =5>• Content : element 內容所顯示的區域
• Padding : 位於外框 (Border) 與內容 (Content) 之間的空間
• Border : element 的邊框
• Margin : element 與 element 之間的空間</font>
----
## CSS Properties
<font size =5>CSS 還可以做什麼呢?
https://www.w3schools.com/cssref/index.php</font>
<font size =5>https://css-tricks.com/</font>
---
## 15puzzle.css
```CSS
/* pseudo-element */
::selection {background: transparent;}
p{margin: 0; font: 12px/150% Arial; text-align: center; color: #999;}
p a{color: #888;}
#controls{text-align: center;}
#controls button{
cursor: pointer; /*設置鼠標懸停在按鈕上時的鼠標樣式為手型*/
outline: none; /*去掉按鈕點擊時的默認輪廓線*/
padding: 10px 20px;
margin: 25px 2px;
border: 0;
border-radius: 4px;
background: #001F1F;
font: bold 14px Arial;
text-align: center;
text-transform: uppercase;
text-shadow: -1px -1px 0 rgba(0,0,0, 0.5);
color: #fff;
}
#controls button:hover{background: #003333;}
#puzzle{
position: relative;
width: 325px;
height: 325px;
margin: 0 auto;
margin-top: 80px;
border: 8px solid #001F1F;
border-radius: 4px;
}
#puzzle span{
position: absolute;
display: block;
width: 80px;
height: 80px;
border-radius: 4px;
}
#puzzle span.number{
cursor: pointer;
font: bold 36px/80px Arial;
text-align: center;
text-shadow: -1px -1px 0 rgba(0,0,0, 0.5);
color: #fff;
}
#puzzle span.empty{background: transparent;}
#puzzle span.number.light{background: #226666;}
#puzzle span.number.dark{background: #003333;}
#puzzle.animate span{
-webkit-transition: 0.15s left, 0.15s top;
transition: 0.15s left, 0.15s top; /*left、top 會在0.15s內被改變*/
/*-webkit-transition 用於支援WebKit(例如Chrome和Safari等)的瀏覽器*/
/*transition 則是標準的CSS3屬性*/
}
```
---
## Javascript Introduction

----
<font size =5>Javascript做了哪些事情?</font>
<img src=https://hackmd.io/_uploads/B1MdWTINp.png width=500px>
<font size =5>1. 接收使用者的輸入內容
2. 根據輸入內容來做判斷
3. 將結果顯示在網頁上</font>
----
```javascript
function search_animal() {
let input = document.getElementById('searchbar').value
input=input.toLowerCase();
let x = document.getElementsByClassName('animals');
for (i = 0; i < x.length; i++) {
if (!x[i].innerHTML.toLowerCase().includes(input)) {
x[i].style.display="none";
}
else {
x[i].style.display="list-item";
}
}
}
function checkEnter(event) {
// 檢查是否按下的是 Enter 鍵
if (event.key === "Enter") {
search_animal();
}
}
```
---
## Hello world (- -b)
```html
<!DOCTYPE html>
<html>
<head>
<title>Hello Javascript</title>
<meta charset="utf-8">
<script>
console.log("Hello World");
/*使用瀏覽器打開.html,按下F12,選擇console*/
</script>
</head>
<body>
</body>
</html>
```
----

---
## Variable Declaration
<font size =5>告訴電腦說,我要產生一個變數,並且給他一個名子,
讓我們之後可以根據這個名子找到他。</font>
```javascript
var x = 5;
```
----
## Data Type
```javascript
var x = 1; //整 數(integer)
var y = 10.13; //浮 點 數(float)
var z = "Hello"; //字 串(String)
var p = true; //布 林 值 (Boolean)
var o = { firstName: 123 } //物 件 (object)
// = 這個符號,不是數學上的等於喔,他代表 Assignment
```
----
## Number Operator
```javascript
var x = 1;
x = x + 2;
console.log(x); // 3
x = x - 1;
console.log(x); // 2
x = x * 12;
console.log(x); // 24
x = x / 3;
console.log(x); // 8
x = x % 5; //取餘數
console.log(x); //3
```
----
## String Operator
<font size =5>這邊我們嘗試將字串進行串接 (+)</font>
```javascript
var str = "Hello";
var blank = " ";
var world = "World";
var helloWorld = str + blank + world;
console.log(helloWorld); //Hello World
```
---
## Condition and Loop
<font size =4>撰寫flow chart可以幫助我們釐清流程,而撰寫程式與撰寫flow chart是相同的
在程式的流程中,主要影響正個流程的走向有兩種不同的語法,分別稱為 Condition 跟Loop。</font>

----
## Condition
<font size =4>最常用的判斷語法為 if 判斷句</font>
```javascript
if (grade > 60)
{
console.log("good");
}
else if (grade == 60)
{
console.log("safe")
}
else
{
console.log("nice to meet you.see you next year!");
}
```
----
## Comparison Operators
```javascript
• == (等於)
• != (不等於)
• > (大於)
• < (小於)
• >= (大於等於)
• <= (小於等於)
```
----
## Switch
```javascript
var day;
switch (new Date().getDay())
{
case 0:
day = "Sunday";
break;
case 1:
day = "Monday";
break;
case 2:
day = "Tuesday";
break;
case 3:
day = "Wednesday";
break;
case 4:
day = "Thursday";
break;
case 5:
day = "Friday";
break;
case 6:
day = "Saturday";
default:
day = "Unknown"; // 在這裡添加了 default,以處理未知的日期情況
}
console.log("Today is " + day);
```
----
## While loop
```javascript
var x = 1;
while(x <= 5)
{
console.log(x);
x = x + 1;
}
```
----
## For loop
```javascript
for(let i =1; i<=5 ;i++){
console.log(i)
}
```
---
## Javascript Html Input
<font size =4>接下來看看javascript要怎麼知道要怎麼知道使用者輸入了甚麼呢</font>
----
#### HTML DOM(Document Object Model) Event
<font size =4>在 HTML 中,當使用者使用鍵盤或是滑鼠對 element 進行操作的時候,</font>
<font size =4> element 會發出一個訊號,這個訊號中會記錄了使用者正在對 element 進行甚麼樣的操作。</font>
<font size =4> 例如,當我們用滑鼠點擊 element ,他會發出一個訊號說使用者使用滑鼠左鍵進行點擊。</font>
<font size =4> 因此在獲取使用者的輸入之前,我們要先取得我們要關注的 Html element 。</font>
----

----
#### 從Javascript中取得Html Element(getElementById)
<font size =4>在 Javascript 中,我們可以透過 Html Element 的 ID attribute 來取得 html 中的 element</font>
HTML:
```html
<div id="block" class="a"></div>
```
Javascript:
```javascript
var x = document.getElementById("block");
console.log(x.id); //block
console.log(x.className); //a
```
----
#### 聽取 Html 中發出的 Event(addEventListener)
```html
<!--創建一個按鈕被點擊時輸出Click!!!-->
<!DOCTYPE html>
<html>
<head>
<title>addEventListener</title>
<meta charset="utf-8">
</head>
<body>
<input id="btn" type="button" value="Click!!!">
<script>
function clickHandler()
{
console.log("Click!!");
}
var button = document.getElementById("btn");
button.addEventListener("click", clickHandler , false);
</script>
</body>
</html>
```
<font size =4> Html 是直譯式語言,因此我們 getElementById 一
定要寫在要取得的 element 之後,這也是為什麼這邊的 script element 寫在 body 最後的原因。</font>
----
### 更改 Html 的內容
<font size =4> 透過 getElementById 取得 Html element 之後,我們可以透過他更改 element 的各種attriubte 以及 element content </font>
```html
<!DOCTYPE html>
<html>
<head>
<title>change element content</title>
<meta charset="utf-8">
</head>
<body>
<input id="btn" type="button" value="Click!!!">
<div id="board">
</div>
<script>
function clickHandler()
{
var board = document.getElementById("board");
board.innerHTML = "Click!!";
board.style = "color: red;";
}
var button = document.getElementById("btn");
button.addEventListener("click", clickHandler , false);
</script>
</body>
</html>
```
----
## 常用element object method
<font size =4>.id : 存取指定element的id。</font>
<font size =4>.nodeName : 取得指定element的節點名稱,但是無法變更element。</font>
<font size =4>.innerHTML : 取出指定element下所有的內容。</font>
<font size =4>.textContent : 取出指定element下的content。</font>
---
## 15puzzle.js
```javascript
(function(){
var state = 1;
var puzzle = document.getElementById('puzzle');
// Creates solved puzzle
solve();
// Listens for click on puzzle cells
puzzle.addEventListener('click', function(e){
if(state == 1){
// Enables sliding animation
puzzle.className = 'animate';
shiftCell(e.target);
}
});
// Listens for click on control buttons
document.getElementById('solve').addEventListener('click', solve);
document.getElementById('scramble').addEventListener('click', scramble);
/*Creates solved puzzle*/
function solve(){
if(state == 0){
return;
}
puzzle.innerHTML = '';
var n = 1;
for(var i = 0; i <= 3; i++){
for(var j = 0; j <= 3; j++){
var cell = document.createElement('span');
cell.id = 'cell-'+i+'-'+j;
cell.style.left = (j*80+1*j+1)+'px';
cell.style.top = (i*80+1*i+1)+'px';
if(n <= 15){
cell.classList.add('number');
cell.classList.add((i%2==0 && j%2>0 || i%2>0 && j%2==0) ? 'dark' : 'light');
cell.innerHTML = (n++).toString();
} else {
cell.className = 'empty';
}
puzzle.appendChild(cell);
}
}
}
/*Shifts number cell to the empty cell*/
function shiftCell(cell){
// Checks if selected cell has number
if(cell.clasName != 'empty'){
// Tries to get empty adjacent cell
var emptyCell = getEmptyAdjacentCell(cell);
if(emptyCell){
// Temporary data
var tmp = {style: cell.style.cssText, id: cell.id};
// Exchanges id and style values
cell.style.cssText = emptyCell.style.cssText;
cell.id = emptyCell.id;
emptyCell.style.cssText = tmp.style;
emptyCell.id = tmp.id;
if(state == 1){
// Checks the order of numbers
setTimeout(checkOrder, 150);
}
}
}
}
/*Gets specific cell by row and column*/
function getCell(row, col){
return document.getElementById('cell-'+row+'-'+col);
}
/*Gets empty cell*/
function getEmptyCell(){
return puzzle.querySelector('.empty');
}
/*Gets empty adjacent cell if it exists*/
function getEmptyAdjacentCell(cell){
// Gets all adjacent cells
var adjacent = getAdjacentCells(cell);
// Searches for empty cell
for(var i = 0; i < adjacent.length; i++){
if(adjacent[i].className == 'empty'){
return adjacent[i];
}
}
// Empty adjacent cell was not found
return false;
}
/*Gets all adjacent cells*/
function getAdjacentCells(cell){
var id = cell.id.split('-');
// Gets cell position indexes
var row = parseInt(id[1]);
var col = parseInt(id[2]);
var adjacent = [];
// Gets all possible adjacent cells
if(row < 3){adjacent.push(getCell(row+1, col));}
if(row > 0){adjacent.push(getCell(row-1, col));}
if(col < 3){adjacent.push(getCell(row, col+1));}
if(col > 0){adjacent.push(getCell(row, col-1));}
return adjacent;
}
/*Chechs if the order of numbers is correct*/
function checkOrder(){
// Checks if the empty cell is in correct position
if(getCell(3, 3).className != 'empty'){
return;
}
var n = 1;
// Goes through all cells and checks numbers
for(var i = 0; i <= 3; i++){
for(var j = 0; j <= 3; j++){
if(n <= 15 && getCell(i, j).innerHTML != n.toString()){
// Order is not correct
return;
}
n++;
}
}
// Puzzle is solved, offers to scramble it
if(confirm('Congrats, You did it! \nScramble the puzzle?')){
scramble();
}
}
/*Scrambles puzzle*/
function scramble(){
if(state == 0){
return;
}
puzzle.removeAttribute('class');
state = 0;
var previousCell;
var i = 1;
var interval = setInterval(function(){
if(i <= 100){
var adjacent = getAdjacentCells(getEmptyCell());
if(previousCell){
for(var j = adjacent.length-1; j >= 0; j--){
if(adjacent[j].innerHTML == previousCell.innerHTML){
adjacent.splice(j, 1);
}
}
}
// Gets random adjacent cell and memorizes it for the next iteration
previousCell = adjacent[rand(0, adjacent.length-1)];
shiftCell(previousCell);
i++;
} else {
clearInterval(interval);
state = 1;
}
}, 5);
}
/*Generates random number*/
function rand(from, to){
return Math.floor(Math.random() * (to - from + 1)) + from;
}
}());
```
----
### Self-Executing Anonymous Function
<font size =4>匿名函數or立即函數,這個語法的目的是在定義函數之後立即執行它。</font>
```javascript
(function() {
// 這裡是函數體,可以包含你想要執行的程式碼
}());
```
<font size =4>1.作用域隔離: 這個函數的所有變數和函數定義都將位於函數作用域內,不會污染全局作用域。</font>
<font size =4>2.避免衝突: 在這個函數內,你可以使用相同的變數名稱而不擔心與全局作用域中的變數產生衝突。</font>
----
## var 和 let
+ <font size =4>Function Scope: var 屬於函數作用域(Function Scope),變數的作用範圍限於聲明它的函數內。
在函數內聲明,在函數外也可以訪問</font>
+ <font size =4>Block Scope: let 屬於區塊作用域(Block Scope),變數的作用範圍僅限於它所在的區塊(例如,if語句、for循環等)。</font>
---
## Lab Questions
----
## Question 1
<font size=4>使用至少4種simple selector美化自我介紹網頁</font>
----
## Question 2
<font size=4>在我最喜歡的神奇寶貝頁面使用至少2個CSS box model</font>
----
## Question 3
<font size=4>畫出flow chart並在自我介紹頁面,設計一個按鈕,content為九九乘法表真好玩,
並在script加入連結.js檔使用javascript於console顯示九九乘法表的計算結果
奇數從1乘到9,偶數從9乘到1,完成後換行,兩個計算結果之間需要使用空白作為間隔
(使用巢狀迴圈完成該要求)
</font>
----
## Question 4
<font size=4>於自我介紹頁面建立一個內部連接至新的分頁,另外選一隻神奇寶貝並加入退化、進化按鈕</font>
<font size=4>點選進(退)化按鈕後由進化前型態變更為進(退)化後的資訊</font>
<font size=4>需包含神奇寶貝名稱,圖片及數值表格(如Lab7所顯示資訊)</font>
----
## Question 5
<font size=4>製作一個9 puzzle game(字體、字塊顏色不可和16puzzle範例相同)</font>
<font size=4>並在自我介紹網頁建立作品集 內部連結連結至9puzzle game網頁</font>

---
## 作業網站
http://140.121.197.13/tutorial
{"title":"計算機概論Lab-8","description":"<font size =4>經常與CSS一起使用,通常用作CSS選擇器的容器,以便對特定區域設計樣式</font>","contributors":"[{\"id\":\"738dd674-cd6a-462c-87e2-b67e68f12ac0\",\"add\":16643,\"del\":735}]"}