본문 바로가기

HTML & CSS

[CSHTML][카드 게임] 2. JS ajax, 컨트롤러 만들기

반응형

Card.js

function saveCard() {
    var index = 0;
    var front = document.getElementById('CardFront');
    var back = document.getElementById('CardBack');
    // + 입력값 유효성 검사 추가

    $.ajax({
        url: '/Card/SaveCard',
        data: { CardIndex: index, CardFront: front.value, CardBack: back.value },
        dataType: 'json',
        method: 'post',
        success: function (res) {
            alert("입력되었습니다: " + front.value + ", " + back.value);
            // 입력값 초기화
            front.value = "";
            back.value = "";
            $(location).attr('href', 'http://localhost:52368/Card/CardList');
        },
        error: function (xhr, status, error) {
            alert("입력값은 빈 값일 수 없습니다. 다시 입력해주세요.");
        }
    });
}
function onDeckNumChange() {
    var deckNum = document.getElementById('DeckNum');
    var cardListCount = parseInt(document.getElementById('CardListCount').value);

    if (deckNum.value <= 0) {
        alert("문제 갯수는 0 이하일 수 없습니다.");
        deckNum.value = 1;
    } else if (deckNum.value > cardListCount) {
        alert("문제 갯수는 목록의 크기를 초과할 수 없습니다.");
        deckNum.value = cardListCount;
    }
}
function cardGameStart() {
    var deckNum = document.getElementById('DeckNum');
    var cardListCount = parseInt(document.getElementById('CardListCount').value);
    event.preventDefault();
    // + 입력값 유효성 검사 추가

    $.ajax({
        url: '/Card/CardGameStart',
        data: { DeckNum: deckNum.value },
        dataType: 'json',
        method: 'post',
        success: function (res) {
            $(location).attr('href', 'http://localhost:52368/Card/CardShow');
        },
        error: function (xhr, status, error) {
            if (error == "Internal Server Error") {
                alert("문제 갯수는 목록의 크기를 초과할 수 없습니다. 다시 입력해주세요.");
                deckNum.value = cardListCount;
            }
            else {
                alert("문제 갯수는 0 이하일 수 없습니다. 다시 입력해주세요.");
                deckNum.value = 1;
            }
        }
    });
}
function submitCard() {
    var card = document.querySelector("div.card");
    var back = document.getElementById('CardBack');
    var answer = document.getElementById('CardAnswer');
    var deckNum = document.getElementById('DeckNum').value;
    var cardIdx = document.getElementById('CardIdx').value;
    var correctCount = parseInt(document.getElementById('CorrectCount').value) + 1;
    // + 입력값 유효성 검사 추가

    if (back.innerText != answer.value) {
        alert("틀렸습니다! 다시 입력해주십시오.");
        answer.value = "";
    } else if (cardIdx  < deckNum ) {
        $.ajax({
            url: '/Card/SetCardIdx',
            data: { Idx: ++cardIdx, Cnt: correctCount },
            dataType: 'json',
            method: 'post',
            async: false, // 동기 방식 - 카드가 돌려지고 난 다음 링크 이동
            success: function (res) {
                card.animate(
                    {
                        transform: [
                            'rotateY(0deg)',
                            'rotateY(-180deg)'
                        ]
                    },
                    {
                        duration: 500, // 밀리초 지정
                        fill: 'forwards', // 종료 시 속성을 지님
                        easing: 'ease' // 가속도 종류
                    }
                );
                setTimeout(function () {
                    alert("맞았습니다!");
                }, 200);
                setTimeout(function () {
                    $(location).attr('href', 'http://localhost:52368/Card/CardShow');
                }, 500);
            },
            error: function (xhr, status, error) {
                alert(error);
            }
        });
    } else {
        card.animate(
            {
                transform: [
                    'rotateY(0deg)',
                    'rotateY(-180deg)'
                ]
            },
            {
                duration: 500, // 밀리초 지정
                fill: 'forwards', // 종료 시 속성을 지님
                easing: 'ease' // 가속도 종류
            }
        );
        setTimeout(function () {
            alert("끝났습니다. 맞힌 갯수: " + correctCount + "개");
        }, 200);
        setTimeout(function () {
            $(location).attr('href', 'http://localhost:52368/Card/CardList');
        }, 500);
    }
}
function nextCard() {
    var card = document.querySelector("div.card");
    var deckNum = document.getElementById('DeckNum').value;
    var cardIdx = document.getElementById('CardIdx').value;
    var correctCount = document.getElementById('CorrectCount').value;
    // + 입력값 유효성 검사 추가

    card.animate(
        {
            transform: [
                'rotateY(0deg)',
                'rotateY(-180deg)'
            ]
        },
        {
            duration: 500, // 밀리초 지정
            fill: 'forwards', // 종료 시 속성을 지님
            easing: 'ease' // 가속도 종류
        }
    );

    setTimeout(function () {
        if (cardIdx < deckNum) {
            $.ajax({
                url: '/Card/SetCardIdx',
                data: { Idx: ++cardIdx, Cnt: correctCount },
                dataType: 'json',
                method: 'post',
                async: false, // 동기 방식 - 카드가 돌려지고 난 다음 링크 이동
                success: function (res) {
                    $(location).attr('href', 'http://localhost:52368/Card/CardShow');
                },
                error: function (xhr, status, error) {
                    alert(error);
                }
            });
        } else {
            alert("끝났습니다. 맞힌 갯수: " + correctCount + "개");
            $(location).attr('href', 'http://localhost:52368/Card/CardList');
        }
     }, 500);
}
코드가 클린하지 않을 수 있습니다 ㅠ.ㅠ 참고해주세요

CardController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using WebProject.Models;

namespace WebProject.Controllers
{
    public class CardController : Controller
    {
        private static List<Card> cardList = new List<Card> {
            new Card { CardFront = "사과", CardBack = "Apple" }
            ,new Card { CardFront = "곰", CardBack = "Bear" }
            ,new Card { CardFront = "고양이", CardBack = "Cat" }
            ,new Card { CardFront = "개", CardBack = "Dog" }
            ,new Card { CardFront = "코끼리", CardBack = "Elephant" }
        };

        private static List<Card> cardShowList = new List<Card>();
        private static int cardIdx = 0;
        private static int correctCount = 0;

        // CardList: CardList.cshtml 보여줌
        public ActionResult CardList()
        {
            ViewBag.Message = "Card List";
            ViewBag.CardList = cardList;
            cardIdx = 0;
            correctCount = 0;
            return View();
        }

        // AddCard: AddCard.cshtml 보여줌
        public ActionResult AddCard()
        {
            ViewBag.Message = "Add Card";
            return View();
        }

        // CardGame: CardGame.cshtml 보여줌
        public ActionResult CardGame()
        {
            ViewBag.Message = "Card Game";
            ViewBag.CardListCount = cardList.Count;
            cardIdx = 0;
            correctCount = 0;
            return View();
        }

        // CardShow: CardShow.cshtml 보여줌
        public ActionResult CardShow()
        {
            ViewBag.Message = "Card Show";
            ViewBag.CardList = cardShowList;
            ViewBag.CardIdx = cardIdx;
            ViewBag.CorrectCount = correctCount;
            return View();
        }

        public ActionResult SaveCard(Card card)
        {
            // todo
            // SDK.GetCard(); // 또는
            // CardManager.GetCardListInfo();

            ViewBag.Message = "Save Card";

            // + 유효성 검사 추가
            if (card == null || card.CardFront == null || card.CardBack == null) {
                // 오류처리
                // 실패에 대한 응답 - HttpStatusCode 종류가 워낙 많아서 세세한 오류코드까지는 지정안해도 됨
                return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
            }
            cardList.Add(card);

            // http 상태 코드(성공)를 JSON으로 변환하여 전달
            // return Json(new HttpStatusCodeResult(HttpStatusCode.OK));
            return Json(cardList);
        }
        
        public ActionResult CardGameStart(int deckNum)
        {
            ViewBag.Message = "Card Game Start";
            
            // + 유효성 검사 추가
            if (deckNum <= 0) {
                return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
            }
            if (deckNum > cardList.Count) {
                return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
            }
            cardShowList = cardList.GetRange(0, deckNum);
            return Json(new HttpStatusCodeResult(HttpStatusCode.OK));
        }

        public ActionResult SetCardIdx(int idx, int cnt)
        {
            ViewBag.Message = "Set Card Idx";

            // + 유효성 검사 추가
            if (idx < 0) {
                return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
            }
            if (cnt < 0) {
                return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
            }
            cardIdx = idx;
            correctCount = cnt;
            return Json(new HttpStatusCodeResult(HttpStatusCode.OK));
        }
    }
}

작동 방식

CardGame.cshtml

CardGame에서 시작 버튼을 누르면 card.js로 가서 cardGameStart() 함수 실행

card.js

cardGameStart()에서 CardController의 CardGameStart() 메소드에 요청을 보냄

CardController.cs

deckNum(문제 개수)를 받아 cardShowList에서 0번부터 deckNum까지 갖고 옴

Card.js

성공 시 다시 card.js로 돌아와, CardShow 화면으로 감

CardController.cs

CardShow에서 cardShowList를 받아와 한 장 씩 넘기며 보여주게 됨

CardShow.cshtml

제출 버튼을 누르면 submitCard() 함수가 실행됨

card.js

현 문제 인덱스를 저장, index+1하여 CardController의 SetCardIdx 메소드를 호출

CardController.cs

이후에 CardShow를 호출할 때 사용하게 됨

CardShow.cshtml

CardList.cshtml

모든 인덱스를 순회한 경우, 다시 CardList로 돌아오게 됨

최종 정리

반응형