{

"name": "backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},

"author": "",
"license": "ISC",
"dependencies": {
"express": "4.17.1", //express 추가.
"lodash": "4.17.20"
}
}

package.json

 

 

서버에서

npm install

명령어 입력하여 package.json의 dependencies에 입력된 tool 설치.

 

 

 

네이버 클라우드에서 8080port 오픈

 

 

 

front 쪽이랑 Backend 쪽 나눠서 디렉토리 분리

 

table,
th,
td {
    border: 1px solid black;
}

#board > div {
    height: 100px;
}

.font_4em {
    font-size: 4em;
}

 

부트스트랩으로 안되는 부분 Class 만들어 css 관리

<!DOCTYPE html>
<html lang="ko">
    <!-- 스튜디오 코드 단축키
//https://demun.github.io/vscode-tutorial/shortcuts/
//행 위아래 복사 : shift+alt+down, shift+alt+up.
//행삭제 ctrl+shift+k
// 주석 : ctrl+/
//사이드바 토글 ctrl+b
//전체화면 토글 f11
-->

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous" />
        <link rel="stylesheet" href="./assets/css/main.css" />
        <title>TicTacToe</title>
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col">
                    <div class="btn-group d-flex mt-4">
                        <button type="button" class="btn btn-primary w-100 d-flex justify-content-between">
                            Name1
                            <span id="nameO">0</span>
                        </button>
                        <button type="button" class="btn btn-danger w-100 d-flex justify-content-between">
                            <span id="nameX">0</span>
                            Name2
                        </button>
                    </div>
                </div>
            </div>

            <div class="row py-3">
                <div class="col">
                    <button type="button" class="btn btn-info" onclick="TicTacToe.rematch()">Rematch</button>
                    <button type="button" class="btn btn-info" onclick="TicTacToe.reset()">Reset</button>
                </div>
                <span id="message"></span>
            </div>

            <div class="row" id="board">
                <div class="col-4 border" onclick="TicTacToe.click(0)">
                    <div class="text-center font_4em" id="0"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(1)">
                    <div class="text-center font_4em" id="1"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(2)">
                    <div class="text-center font_4em" id="2"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(3)">
                    <div class="text-center font_4em" id="3"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(4)">
                    <div class="text-center font_4em" id="4"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(5)">
                    <div class="text-center font_4em" id="5"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(6)">
                    <div class="text-center font_4em" id="6"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(7)">
                    <div class="text-center font_4em" id="7"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(8)">
                    <div class="text-center font_4em" id="8"></div>
                </div>
            </div>
        </div>
    </body>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>
    <script src="./assets/js/main.js"></script>
</html>

 

html 파일

var TicTacToe = (function () {
    var _init = false
    var _getStatusIntervalSecond = 250

    function _setMessage(message) {
        document.getElementById("message").innerHTML = message
    }

    function _pollingGetStatus() {
        $.ajax({
            url: "구매한 도메인:8080(포트)/getStatus",
            type: "GET",
            success: function (res) {
                //실시간 html 그리기.
                document.getElementById("nameO").innerHTML = res.user["O"].score
                document.getElementById("nameX").innerHTML = res.user["X"].score
                for (var i = 0; i < res.game.block.length; i++) {
                    document.getElementById(i).innerHTML = res.game.block[i]
                }

                if (!res.game.playable) {
                    _setMessage("게임이 종료되었습니다.")
                }
                // 0.25초마다 polling 호출
                setTimeout(_pollingGetStatus, _getStatusIntervalSecond)
            },
        })
    }

    function _rematch(reset) {
        //새롭게 게임 시작시. 재대결 이어서 대결.
        $.ajax({
            url: "구매한 도메인:8080(포트)/matchStatus",
            type: "GET",
            data: {
                reset: reset,
            },
            success: function (res) {
                //reset 버튼 여부로 인하여 true false 처리.
                if (!res.status) {
                    alert(res.message)
                } else {
                    _setMessage("새 게임이 시작되었습니다.")
                }
            },
        })
    }

    return {
        init: function () {
            if (_init) {
                return false
            }
            _init = true

            _pollingGetStatus()
        },
        //index : html 클릭한 파라미터
        click: function (index) {
            _setMessage("")
            $.ajax({
                //app.listen(8080)받았기 때문에 해당 메소드로 진입.
                url: "구매한 도메인:8080(포트)/setMarker",
                type: "GET",
                data: {
                    index: index,
                },
                success: function (res) {
                    if (!res.status) {
                        alert(res.message)
                    }
                },
            })
        },
        rematch: function () {
            _rematch()
        },
        reset: function () {
            _rematch(true)
        },
    }
})()

TicTacToe.init()

main.js 

프론트 부분은 html 받아온 값만 이벤트 처리를 back단으로 넘기는 형식으로 구현하였다.

var express = require("express")
var app = express()
var _ = require("lodash")

// CORS대응 코드.
app.all("/*", function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Headers", "X-Requested-With")
    next()
})

// DATABASE
var _database = {
    game: {
        playable: true,
        count: 0,
        block: ["", "", "", "", "", "", "", "", ""],
        winner: "", // [X, O, _, ]
    },
    user: {
        X: { name: "user1", score: 0 },
        O: { name: "user2", score: 0 },
    },
}

var _successCondition = [
    //틱택토 게임 성공의 경우의 수.
    ["0", "1", "2"],
    ["3", "4", "5"],
    ["6", "7", "8"],
    ["0", "3", "6"],
    ["1", "4", "7"],
    ["2", "5", "8"],
    ["0", "4", "8"],
    ["2", "4", "6"],
]

function _getMarker() {
    //처음 시작시 X,O 표시
    return _database.game.count == 0 || _database.game.count % 2 == 0 ? "X" : "O"
}

function _getResult(marker) {
    var markeredIndex = _.compact(
        _.map(_database.game.block, function (value, index) {
            return value == marker ? index.toString() : ""
        })
    )

    var checkNumber = Math.abs(3 - markeredIndex.length)
    _.map(_successCondition, function (condition) {
        if (_.xor(condition, markeredIndex).length == checkNumber) {
            _database.user[marker].score++
            _database.game.playable = false
            _database.game.winner = marker
        }
    })

    if (_database.game.playable && _database.game.count == 9) {
        _database.game.winner = "_"
        _database.game.playable = false
    }
}

//matchStatus
app.get("/matchStatus", function (req, res) {
    var response = {
        status: false,
        message: "Wrong Access.",
    }

    if (_database.game.playable) {
        response.message = "게임이 진행중입니다."
    } else {
        _database = {
            game: {
                playable: true,
                count: 0,
                block: ["", "", "", "", "", "", "", "", ""],
                winner: "", // [X, O, _, ]
            },
            user: {
                X: { name: "baek", score: _database.user["X"].score },
                O: { name: "oh", score: _database.user["O"].score },
            },
        }

        if (req.query.reset) {
            _database.user = {
                X: { name: "baek", score: 0 },
                O: { name: "oh", score: 0 },
            }
        }

        response = {
            status: true,
            message: "게임이 초기화되었습니다.",
        }
    }

    res.send(response)
})

// getStatus
app.get("/getStatus", function (req, res) {
    res.send(_database)
})

/*
    - 마커를 입력한다.
    {
        index: int(required)
    }
*/
app.get("/setMarker", function (req, res) {
    var response = {
        status: false,
        message: "Wrong Access.",
    }

    //잘못된 값이 들어올경우의 예외처리
    if (typeof req.query.index === "undefined") {
        response.message += "(-1)"
    } else if ([0, 1, 2, 3, 4, 5, 6, 7, 8].includes(req.query.index)) {
        response.message += "(-2)"
    } else if (!_database.game.playable) {
        response.message = "게임이 종료되었습니다."
    } else if (_database.game.block[req.query.index].length) {
        response.message = "이미 선택된 블록입니다."
    } else {
        //해당 예외처리가 아니면 O,X 찍어주고 선택횟수가 5이상 넘넘어가면 게임종료.
        _database.game.block[req.query.index] = _getMarker()
        _database.game.count++

        if (_database.game.count >= 5) {
            _getResult(_database.game.block[req.query.index])
        }

        response = {
            status: true,
            message: "Success.",
        }
    }

    res.send(response)
})
//(오픈된 방화벽 port)
app.listen(8080)

 

중요 로직 및 통신관련부분은 index.js로 구분하여 처리

해당 소스 부분 수정시에는 

node index.js

를 서버에서 입력하여 실행

 

다른 브라우저.(즉 다른 세션)에서 동기화 되는것 테스트.

 

 

 

1. github에서 토큰값 받기

github.com/

 

Settings > Developer settings > Personal access tokens

 

 

 

 

 

 

해당 토큰값은 다시는 확인이 힘드니 해당화면에서 무조건 메모장이나 다른곳에 저장을 해놓도록 하자.

2. 비쥬얼 스튜디오 코드 프로그램에서 'Setting sync' 프로그램 설치

Ctrl+Shift+P 눌러서 해당값 설정

 

얻은 엑세스 토큰 입력후 저장.

Shift + Alt + u  단축키 사용하여 업로드 진행.

 

3. 동기화시킬 비쥬얼 스튜디오 프로그램에 'Setting Sync' 설치후 

gist.github.com/로그인하여 CloudSettings 클릭하여 

URL 상단의 gist.github.com/ 유저아이디 / GIST ID 값 확인

 

Shift + Alt + d  단축키 사용하여 다운로드 진행.

 

그다음에 비쥬얼스튜디오 코드 재시작하면 셋팅 끝 ~~

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="utf-8" />
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
        <link
            rel="stylesheet"
            href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
            crossorigin="anonymous"
        />
        <link rel="stylesheet" href="./assets/css/main.css" />
        <title>TicTacToe</title>
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col">
                    <div class="btn-group d-flex mt-4">
                        <button
                            type="button"
                            class="btn btn-primary w-100 d-flex justify-content-between"
                        >
                            Name1
                            <span id="name1">0</span>
                        </button>
                        <button
                            type="button"
                            class="btn btn-danger w-100 d-flex justify-content-between"
                        >
                            <span id="name2">0</span>
                            Name2
                        </button>
                    </div>
                </div>
            </div>
            <div class="row p-3">
                <button
                    type="button"
                    class="btn btn-info"
                    onclick="TicTacToe.rematch()"
                >
                    Rematch
                </button>
                <button
                    type="button"
                    class="btn btn-info"
                    onclick="TicTacToe.reset()"
                >
                    Reset
                </button>
                <span id="message"></span>
            </div>

            <!-- First Row-->
            <div class="row" style="height: 100px">
                <div class="col-4 border" onclick="TicTacToe.click(0)">
                    <div class="text-center" id="0"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(1)">
                    <div class="text-center" id="1"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(2)">
                    <div class="text-center" id="2"></div>
                </div>
            </div>
            <!-- Second Row -->
            <div class="row" style="height: 100px">
                <div class="col-4 border" onclick="TicTacToe.click(3)">
                    <div class="text-center" id="3"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(4)">
                    <div class="text-center" id="4"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(5)">
                    <div class="text-center" id="5"></div>
                </div>
            </div>

            <!-- Third Row -->
            <div class="row" style="height: 100px">
                <div class="col-4 border" onclick="TicTacToe.click(6)">
                    <div class="text-center" id="6"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(7)">
                    <div class="text-center" id="7"></div>
                </div>
                <div class="col-4 border" onclick="TicTacToe.click(8)">
                    <div class="text-center" id="8"></div>
                </div>
            </div>
        </div>
    </body>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
    <script
        src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
        crossorigin="anonymous"
    ></script>
    <script
        src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
        crossorigin="anonymous"
    ></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>
    <script src="./assets/js/main.js"></script>
</html>

 

 

var TicTacToe = (function () {
    var _init = false;
    var _playable = true;
    var _count = 0;
    var _block = ["", "", "", "", "", "", "", "", ""];
    var _successCondition = [
        //틱택토 게임 성공의 경우의 수.
        ["0", "1", "2"],
        ["3", "4", "5"],
        ["6", "7", "8"],
        ["0", "3", "6"],
        ["1", "4", "7"],
        ["2", "5", "8"],
        ["0", "4", "8"],
        ["2", "4", "6"],
    ];

    function _getMarker() {
        //처음 시작시 X,O 표시
        return _count == 0 || _count % 2 == 0 ? "X" : "O";
    }

    function _setMessage(message) {
        document.getElementById("message").innerHTML = message;
    }

    function _getResult(marker) {
        var markeredIndex = _.compact(
            _.map(_block, function (value, index) {
                return value == marker ? index.toString() : "";
            })
        );

        var checkNumber = Math.abs(3 - markeredIndex.length);
        _.map(_successCondition, function (condition) {
            if (_.xor(condition, markeredIndex).length == checkNumber) {
                _setMessage("Winner is " + marker);
                var user1_score = document.getElementById("name1").innerHTML;
                var user2_score = document.getElementById("name2").innerHTML;

                console.log("user1_score", user1_score);
                console.log("user2_score", user2_score);

                if (marker == "X") {
                    user1_score++;
                    document.getElementById("name1").innerHTML = user1_score;
                } else if (marker == "O") {
                    user2_score++;
                    document.getElementById("name2").innerHTML = user2_score;
                }

                _playable = false;
            }
        });

        if (_playable && _count == 9) {
            _setMessage("Draw");
            _playable = false;
        }
    }

    function _rematch() {
        _playable = true;
        _count = 0;
        _block = ["", "", "", "", "", "", "", "", ""];
        for (var i = 0; i < 9; i++) {
            document.getElementById(i).innerHTML = "";
        }
    }

    return {
        init: function () {
            if (_init) {
                return false;
            }
            _init = true;
        },
        click: function (index) {
            if (!_playable) {
                return false;
            }

            _setMessage("");

            if (!_block[index].length) {
                _block[index] = _getMarker();
                document.getElementById(index).innerHTML = _block[index];
                //글자 가운데 처리 안되어서 사이즈를 늘림.
                document.getElementById(index).style.fontSize = "4em";
                _count++;
                //5번이상 클릭시 결과가 나옴.
                if (_count >= 5) {
                    _getResult(_block[index]);
                }
            } else {
                _setMessage("have clicked block");
            }
        },
        rematch: function () {
            _setMessage("rematch start");
            _rematch();
        },
        reset: function () {
            _setMessage("reset start");
            _rematch();
            document.getElementById("name1").innerHTML = 0;
            document.getElementById("name2").innerHTML = 0;
        },
    };
})();

TicTacToe.init();

 

점수표기 추가

O,X 부트스트랩으로 정가운데 정렬이 힘들어서

텍스트만 center로 놓고 크기를 늘려서 칸을 조절

 

 

상단의 점수판 변함.

Rematch Reset 버튼 추가.

 

 

기존에 있던 형태를

CSS, Js,html로 분류하였다.

 

 

<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <link rel="stylesheet" href="./assets/css/main.css">
    <title>TicTacToe</title>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col">
                <div class="btn-group d-flex mt-4">
                    <button type="button" class="btn btn-primary w-100 d-flex justify-content-between">
                        Name1
                        <span class="">0</span>
                    </button>
                    <button type="button" class="btn btn-danger w-100 d-flex justify-content-between">
                        <span class="">0</span>
                        Name2
                    </button>
                </div>
            </div>
        </div>
        <div class="row p-3">
            <span id="message"></span>
            <button type="button" class="btn btn-info" onclick="TicTacToe.reset()">Reset</button>
        </div>
        <div class="row p-3">
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(0)"><div id="0"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(1)"><div id="1"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(2)"><div id="2"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(3)"><div id="3"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(4)"><div id="4"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(5)"><div id="5"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(6)"><div id="6"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(7)"><div id="7"></div></div>
            <div class="col-4 border" style="height: 100px;" onclick="TicTacToe.click(8)"><div id="8"></div></div>
        </div>
    </div>
</body>
<!-- 기존 제이쿼리 -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<!-- 노드 JS를 위한 라이브러리 -->
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<!-- 부트스트랩 추가 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<!-- 반복문 처리를 위한 Lodash 라이브러리 -->
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>
<!-- 작성한 Javascripty -->
<script src="./assets/js/main.js"></script>
</html>

 

먼저 html 구조이다.

일단 기존의것을 바꾸기 위해서 

lodash.com/docs/4.17.15

 

Lodash Documentation

_(value) source Creates a lodash object which wraps value to enable implicit method chain sequences. Methods that operate on and return arrays, collections, and functions can be chained together. Methods that retrieve a single value or may return a primiti

lodash.com

반복문 처리를 위한 라이브러리 추가.

부트스트랩 추가.

getbootstrap.com/docs/4.5/layout/overview/

 

Overview

Components and options for laying out your Bootstrap project, including wrapping containers, a powerful grid system, a flexible media object, and responsive utility classes.

getbootstrap.com

 

추후에 처리를 위한 NodeJs 관련 라이브러리도 추가.

 

           table, th, td { border: 1px solid black}
           .fix_td {width:100px; height: 50px;}

일단 만들어놓은 CSS인데 부트스트랩 쓰면서 사용안할듯.

 

var TicTacToe = (function () {
    var _init = false;
    var _playable = true;
    var _count = 0;
    var _block = ["", "", "", "", "", "", "", "", ""];
    var _successCondition = [
        //틱택토 게임 성공의 경우의 수.
        ["0", "1", "2"],
        ["3", "4", "5"],
        ["6", "7", "8"],
        ["0", "3", "6"],
        ["1", "4", "7"],
        ["2", "5", "8"],
        ["0", "4", "8"],
        ["2", "4", "6"],
    ];

    function _getMarker() {
        //처음 시작시 X,O 표시
        return _count == 0 || _count % 2 == 0 ? "X" : "O";
    }

    function _setMessage(message) {
        document.getElementById("message").innerHTML = message;
    }

    function _getResult(marker) {
        var markeredIndex = _.compact(
            _.map(_block, function (value, index) {
                return value == marker ? index.toString() : "";
            })
        );

        var checkNumber = Math.abs(3 - markeredIndex.length);
        _.map(_successCondition, function (condition) {
            if (_.xor(condition, markeredIndex).length == checkNumber) {
                _setMessage("Winner is " + marker);
                _playable = false;
            }
        });

        if (_playable && _count == 9) {
            _setMessage("Draw");
            _playable = false;
        }
    }

    return {
        init: function () {
            if (_init) {
                return false;
            }
            _init = true;
        },
        click: function (index) {
            if (!_playable) {
                return false;
            }

            _setMessage("");

            if (!_block[index].length) {
                _block[index] = _getMarker();
                document.getElementById(index).innerHTML = _block[index];
                _count++;

                if (_count >= 5) {
                    _getResult(_block[index]);
                }
            } else {
                _setMessage("have clicked block");
            }
        },
        reset: function () {
            _setMessage("new game start");
            _playable = true;
            _count = 0;
            _block = ["", "", "", "", "", "", "", "", ""];
            for (var i = 0; i < 9; i++) {
                document.getElementById(i).innerHTML = "";
            }
        },
    };
})();

TicTacToe.init();

 - 제이쿼리 문법을 걷어냄

 - table id로 if문 주던 로직을 _successCondition 변수선언하여 모든경우의 수를 추가.

 - 메세지 관련 함수 추가

 - 모든 기능을 function으로 나누었으며 Lodash 라이브러리 사용하여 for문을 간략하게 나누어서 처리하였다.

 

 

 

부트스트랩 좀더 손보고.

Node 공부좀 해봐야지

좀더 함수화 하는 방법으로 코딩방법을 개선해봐야지.

완성된것을 보면 정말 쉬워보이는데 막상하려면 진짜 어렵네. ㅠㅠ 

 

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<html>
<!-- 스튜디오 코드 단축키
//https://demun.github.io/vscode-tutorial/shortcuts/
//행 위아래 복사 : shift+alt+down, shift+alt+up.
//행삭제 ctrl+shift+k 
// 주석 : ctrl+/
-->
    <head>
        <style>
           table, th, td { border: 1px solid black}
           .fix_td {width:100px; height: 50px;}
        </style>
    <body>
        <!-- 클릭했을때 이벤트 실행 O,X값을 구분해줄 칸이 필요.-->
        <div style="padding: 15%;">
            <div style="padding-bottom: 5px;">
                <div style="float:left;">플레이어 구분
                    <select class="choice_user">
                        <option value="O">O</option>
                        <option value="X">X</option>
                    </select>
                </div>
                <div class="reset" style="float:left; margin-left:15px; border:2px solid;">다시시작</div>
            </div>
            <table id="main_table" style="width:100%;height: 150px;">
                <tbody>
                    <tr >
                        <td class="fix_td">
                            <div id =11></div>
                        </td>
                        <td class="fix_td">
                            <div id =12></div>
                        </td>
                        <td class="fix_td">
                            <div id =13></div>
                        </td>
                    </tr>
                    <tr>
                        <td class="fix_td">
                            <div id =21></div>
                        </td>
                        <td class="fix_td">
                            <div id =22></div>
                        </td>
                        <td class="fix_td">
                            <div id =23></div>
                        </td>
                    </tr>
                    <tr>
                        <td class="fix_cd">
                            <div id =31></div>
                        </td>
                        <td class="fix_cd">
                            <div id =32></div>
                        </td>
                        <td class="fix_cd">
                            <div id =33></div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </body>
    <script>
        var count = 0;
        //td값 선택
        $("#main_table").find('td').click(function(){
         //이미 입력된 값은 수정 불가.
            if(!$(this).children().hasClass("")){
                alert("입력된값이 있음.");
                return false;
            }
        //추후에 그림이 어찌될지 모르니 div로 감싸자.    
            var div_class = $(this).children().addClass("choice"+count);
            var choice_user = $('.choice_user').val();
            $(".choice"+count).text(choice_user);
            
        // O선택이 되었으면 다음 select box는 X로 해야함.
            if(choice_user == "O"){
                $(".choice_user").val("X");
            }else{
                $(".choice_user").val("O");
            }
            count ++;
       
        //첫줄
            var cell_11 = $('#main_table').find('#11').text();
            var cell_12 = $('#main_table').find('#12').text();
            var cell_13 = $('#main_table').find('#13').text();
        //두번째 줄
            var cell_21 = $('#main_table').find('#21').text();
            var cell_22 = $('#main_table').find('#22').text();
            var cell_23 = $('#main_table').find('#23').text();
        // 세번째 줄
            var cell_31 = $('#main_table').find('#31').text();
            var cell_32 = $('#main_table').find('#32').text();
            var cell_33 = $('#main_table').find('#33').text();

//가로
            if(cell_11 == "O" && cell_12 == "O" && cell_13 == 'O'){
                alert("O 가로 1줄");
                return false;
            }else if(cell_11 == "X" && cell_12 == "X" && cell_13 == 'X'){
                alert("X가로 1줄");
                return false;
            }

            if(cell_21 == "O" && cell_22 == "O" && cell_23 == 'O'){
                alert("O 가로 2줄");
                return false;
            }else if(cell_21 == "X" && cell_22 == "X" && cell_23 == 'X'){
                alert("X가로 2줄");
                return false;
            }

            if(cell_31 == "O" && cell_32 == "O" && cell_33 == 'O'){
                alert("O 가로 3줄");
                return false;
            }else if(cell_31 == "X" && cell_32 == "X" && cell_33 == 'X'){
                alert("X 가로 3줄");
                return false;
            }

//세로
            if(cell_11 == "O" && cell_21 == "O" && cell_31 == 'O'){
                alert("O 세로 첫줄");
                return false;
            }else if(cell_11 == "X" && cell_21 == "X" && cell_31 == 'X'){
                alert("X 세로 첫줄");
                return false;
            }

            if(cell_12 == "O" && cell_22 == "O" && cell_32 == 'O'){
                alert("O 세로2줄");
                return false;
            }else if(cell_12 == "X" && cell_22 == "X" && cell_32 == 'X'){
                alert("X 세로2줄");
                return false;
            }

            if(cell_31 == "O" && cell_32 == "O" && cell_33 == 'O'){
                alert("세로3줄");
                return false;
            }else if(cell_31 == "X" && cell_32 == "X" && cell_33 == 'X'){
                alert("세로 3줄X");
                return false;
            }
//대각선
            if(cell_11 == "O" && cell_22 == "O" && cell_33 == 'O'){
                alert("왼쪽 대각선 O");
                return false;
            }else if(cell_11 == "X" && cell_22 == "X" && cell_33 == 'X'){
                alert("왼쪽  대각선 X");
                return false;
            }else if(cell_31 == "O" && cell_22 == "O" && cell_13 == 'O'){
                alert("오른쪽 대각선 O");
                return false;
            }else if(cell_31 == "X" && cell_22 == "X" && cell_13 == 'X'){
                alert("오른쪽 대각선 X");
                return false;
            }

            if($(this).children().hasClass("choice8")){
                alert("무승부.");
                return false;
            }    
            // console.log('test',test);

     });
     $('.reset').click(function(){
         //refresh로 일단 처리.
        location.reload(true);  
     });
  
    </script>
</html>

 

가로,세로,대각선 부분 다 table id및 if문으로 줘서 처리했는데 더 좋은 방법이 있지 않을까. ㅠㅠ

 

 

 

1.table id를 줘서 'O,X'의 값 가로세로대각선 경우의수 지정

2. hasClass, find 정도의 html 속성값찾는 함수사용.

만약에O,X를 이미지로 처리한다면 아마 따로 변수줘서 테스트를 해야할듯.

 

일단 jquery로 하여서 

테이블을 css로 그려주고 O,X선택에 따라 값이 되게만 하였다.

 

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<html>
<!-- 스튜디오 코드 단축키
//https://demun.github.io/vscode-tutorial/shortcuts/
//행 위아래 복사 : shift+alt+down, shift+alt+up.
//행삭제 ctrl+shift+k 
// 주석 : ctrl+/
-->
    <head>
        <style>
           table, th, td { border: 1px solid black}
           .fix_td{width:100px; height: 50px;}
        </style>
    <body>
        <!-- 클릭했을때 이벤트 실행 O,X값을 구분해줄 칸이 필요.-->
        <!-- O,X의 값이 가로세로 대각선이 맞으면 게임종료 표시.-->
        <div style="padding: 15%;">
            <div style="padding-bottom: 5px;">
                플레이어 구분
                <select class="choice_user">
                    <option value="O">O</option>
                    <option value="X">X</option>
                </select>
            </div>
            <table id="main_table" style="width:100%;height: 150px;">
                <tbody>
                    <tr >
                        <td class="fix_td">
                            <div></div>
                        </td>
                        <td class="fix_td">
                            <div></div>
                        </td>
                        <td class="fix_td">
                            <div></div>
                        </td>
                    </tr>
                    <tr>
                        <td class="fix_td">
                            <div></div>
                        </td>
                        <td class="fix_td">
                            <div></div>
                        </td>
                        <td class="fix_td">
                            <div></div>
                        </td>
                    </tr>
                    <tr>
                        <td class="fix_cd">
                            <div></div>
                        </td>
                        <td class="fix_cd">
                            <div></div>
                        </td>
                        <td class="fix_cd">
                            <div></div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </body>
    <script>
       var count = 0;
        //td값 선택
       $("#main_table").find('td').click(function(){
        var choice_user = $('.choice_user').val();
        var div_class = $(this).children().addClass("choice"+count);
        $(".choice"+count).text(choice_user);
        
        // O선택이 되었으면 다음 select box는 X로 해야함.
        if(choice_user == "O"){
            $(".choice_user").val("X");
        }else{
            $(".choice_user").val("O");
        }
        count ++;
    });
    </script>
</html>

 

** TD값 가져오는데에서 헷갈려 했다. 처음에 Tr로 클래스를 줘서 해야하나 막 고민하다가..

div로 하긴했는데 솔직히 이부분도 굳이 children으로 div을 줄필요는 없는듯한데.. 이건뭐 나중에 바꿔나가야지..

 

예외처리 해야할 사항.

대각선과 가로 세로 일치하였을때 alert으로 승자표시 해주고

이미 선택된 셀은 바꿔지지 않게 수정을 해야할듯

www.hosting.kr/

 

https://www.hosting.kr/

 

www.hosting.kr

 

해당사이트에서 도메인도 사고

네이버클라우드에서 공인 웹서버용 ip도 받았다.

그리고 같이 공부할 친구와 서버환경을 위하여 Drop Box 

 

www.dropbox.com/

 

Dropbox

Dropbox는 바쁜 업무의 부담을 줄이고 중요한 업무에 주력할 수 있도록 디자인된 최신 작업 공간입니다. 로그인하여 업무에 창의적인 에너지를 활용하세요.

www.dropbox.com

구글계정으로 가입하여 개발환경 폴더도 공유

 

 

 

code.visualstudio.com

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

 

KOREA 한글패키지와 SFTP 소스 저장시 바로 서버로 저장을 위한 FTP 툴도 설치

 

 

{
    "name": "프로젝트에서 사용할 이름..아무거나.?",
    "host": "IP주소",
    "protocol": "sftp",
    "port": 포트주소,
    "username": "서버사용자 아이디",
    "remotePath": "공유할 경로",
    "password": "서버 패스워드",
    "ignore": ["FTP동기화시 무시할 파일."],
    "uploadOnSave": true
}

Sftp.json 파일에 필요한 부분을 적는다.

참고 : vscode.tistory.com/entry/sftp

 

www.netsarang.com/ko/free-for-home-school/

Xsheel 설치하여서 서버로 바로 접속가능한 툴도 설치

 

서버내에서 node.js 및 톰켓 관련 파일 설치

 - Node.js (LTS 써있는것을 설치하는게 좋음)

 

 sudo apt-get install curl
  -> sudo apt install curl (뒤에 get 없어도 가능함)
 curl -sL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
 sudo apt-get install -y nodejs
   -> sudo apt install -y ndoejs
   
 nvm ls-remote로 체크한후 14.9.0으로 바꿈
 nvm install 14.9.0
 nvm use 14.9.0
 
 node -v로 확인
 
 
 -- 웹 서버를 위한 아파치 설치
 
 apt install apache2

 

github.com/nodesource/distributions/blob/master/README.md

 

nodesource/distributions

NodeSource Node.js Binary Distributions. Contribute to nodesource/distributions development by creating an account on GitHub.

github.com

 

 

사용하였던 리눅스 명령어.

* histroy : 이제까지 사용된 명령어 확인가능

* histroyLine :  !30 이리적으면 히스토리 라인에서 30번째 명령어가 실행된다

* cat :  파일 확인/열기

* netstat -ntlp: 포트확인(자주사용)

*rm -rf :  파일삭제

 

====정리

1. 클라우드 서버 구매

2. 도메인,공인아이피,드랍박스,Xshell 설치

3. 비쥬얼스튜디오코드 설치, 서버에 nodejs 설치 

이제 뭔가 만들어봐야지 ~ 

www.ncloud.com/

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

 

 

 

네이버 클라우드 접속하여 많은 서비스중에서 Server 선택한다.

처음 결재자로 지정되면 크레딧 100,000원으로 3개월정도 무료로 사용이 가능하다.

 

 

 

 

 

자주사용할 목록이니 즐겨찾기 해노기.

 

 

2세대로 서버 생성 시작.

 

사진이 늘려서 잘 안보이지만 ㅠㅠ

부팅 디스크 크기 : 50GB

이미지 타입 : OS

OS 이미지 타입 : Ubuntu

서버타입 : Compact

어차피 공부용이라 HDD로 설정하고 요금제는 시간요금제로 정하였다. 혹시몰라서 서버를 날리고

다시 생성할지도 모르니깐 ~

 

인증키 이름을 적어서 인증키를 생성한다.

나중에 관리자 비번을 찾을때 쓰는 인증키 파일이니 잘 보관하도록 하자.

 

방화벽 설정 일단 소스는 0.0.0.0으로 지정하였고 포트는 20번대만 잡아놓았다.

 

 

마무리하기전에 뒤로 버튼을 눌러서 보유하고 있는 AOG를 클릭하여 자신의것과 네이버 클라우드 둘다 선택.

서버 구축완료. 확인버튼을 누르면 진행상황을 볼수 있다.

 

 

 

 

 

설치된것 확인 끝!! 

+ Recent posts