From cca5620a3d91dc7894d833aaa06a2bee0df8db1f Mon Sep 17 00:00:00 2001 From: aleigi Date: Tue, 5 Mar 2024 16:23:28 +0300 Subject: [PATCH 1/2] MODIFY app --- pom.xml | 30 +++-- .../com/tictactoe/controller/InitServlet.java | 37 ++++++ .../tictactoe/controller/LogicServlet.java | 125 ++++++++++++++++++ .../tictactoe/controller/RestartServlet.java | 17 +++ .../com/tictactoe/{ => entity}/Field.java | 4 +- .../java/com/tictactoe/{ => entity}/Sign.java | 5 +- src/main/webapp/WEB-INF/index.jsp | 65 +++++++++ src/main/webapp/WEB-INF/web.xml | 6 + src/main/webapp/index.jsp | 17 --- src/main/webapp/static/main.css | 19 +++ 10 files changed, 294 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/tictactoe/controller/InitServlet.java create mode 100644 src/main/java/com/tictactoe/controller/LogicServlet.java create mode 100644 src/main/java/com/tictactoe/controller/RestartServlet.java rename src/main/java/com/tictactoe/{ => entity}/Field.java (95%) rename src/main/java/com/tictactoe/{ => entity}/Sign.java (66%) create mode 100644 src/main/webapp/WEB-INF/index.jsp create mode 100644 src/main/webapp/WEB-INF/web.xml delete mode 100644 src/main/webapp/index.jsp diff --git a/pom.xml b/pom.xml index cb226e88..6b671e54 100644 --- a/pom.xml +++ b/pom.xml @@ -12,21 +12,35 @@ UTF-8 - 18 - 18 + 21 + 21 + + + + org.springframework.boot + spring-boot-dependencies + 3.2.2 + pom + import + + + + - javax.servlet - javax.servlet-api - 4.0.1 + jakarta.servlet + jakarta.servlet-api provided - javax.servlet - jstl - 1.2 + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + + + org.glassfish.web + jakarta.servlet.jsp.jstl diff --git a/src/main/java/com/tictactoe/controller/InitServlet.java b/src/main/java/com/tictactoe/controller/InitServlet.java new file mode 100644 index 00000000..dfcd48b7 --- /dev/null +++ b/src/main/java/com/tictactoe/controller/InitServlet.java @@ -0,0 +1,37 @@ +package com.tictactoe.controller; + +import com.tictactoe.entity.Field; +import com.tictactoe.entity.Sign; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +@WebServlet(name = "InitServlet", value = "/start") +public class InitServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + // Создание новой сессии + HttpSession currentSession = req.getSession(true); + + // Создание игрового поля + Field field = new Field(); + + // Получение списка значений поля + List data = field.getFieldData(); + + // Добавление в сессию параметров поля (нужно будет для хранения состояния между запросами) + currentSession.setAttribute("field", field); + // и значений поля, отсортированных по индексу (нужно для отрисовки крестиков и ноликов) + currentSession.setAttribute("data", data); + + // Перенаправление запроса на страницу index.jsp через сервер + getServletContext().getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp); + } +} \ No newline at end of file diff --git a/src/main/java/com/tictactoe/controller/LogicServlet.java b/src/main/java/com/tictactoe/controller/LogicServlet.java new file mode 100644 index 00000000..67845f8c --- /dev/null +++ b/src/main/java/com/tictactoe/controller/LogicServlet.java @@ -0,0 +1,125 @@ +package com.tictactoe.controller; + +import com.tictactoe.entity.Field; +import com.tictactoe.entity.Sign; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.List; + + +@WebServlet(name = "LogicServlet", value = "/logic") +public class LogicServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + // Получаем текущую сессию + + HttpSession currentSession = req.getSession(); + // Получаем объект игрового поля из сессии + Field field = extractField(currentSession); + Sign currentSign; + int index = getSelectedIndex(req); + + // получаем индекс ячейки, по которой произошел клик + + currentSign = field.getField().get(index); + // Проверяем, что ячейка, по которой был клик пустая. + // Иначе ничего не делаем и отправляем пользователя на ту же страницу без изменений + // параметров в сессии + if (Sign.EMPTY != currentSign) { + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/index.jsp"); + dispatcher.forward(req, resp); + return; + } + // ставим крестик в ячейке, по которой кликнул пользователь + field.getField().put(index, Sign.CROSS); + // Проверяем, не победил ли крестик после добавления последнего клика пользователя + if (checkWin(resp, req, currentSession, field)) { + return; + } + // Получаем пустую ячейку поля + int emptyFieldIndex = field.getEmptyFieldIndex(); + + if (emptyFieldIndex >= 0) { + field.getField().put(emptyFieldIndex, Sign.NOUGHT); + // Проверяем, не победил ли нолик после добавление последнего нолика + if (checkWin(resp, req, currentSession, field)) { + return; + } + } + // Если пустой ячейки нет и никто не победил - значит это ничья + else { + // Добавляем в сессию флаг, который сигнализирует что произошла ничья + currentSession.setAttribute("draw", true); + + // Считаем список значков + List data = field.getFieldData(); + + // Обновляем этот список в сессии + currentSession.setAttribute("data", data); + + // Шлем редирект + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/index.jsp"); + dispatcher.forward(req, resp); + return; + } + + // Считаем список значков + List data = field.getFieldData(); + + // Обновляем объект поля и список значков в сессии + currentSession.setAttribute("data", data); + currentSession.setAttribute("field", field); + + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/index.jsp"); + dispatcher.forward(req, resp); + + } + + + private int getSelectedIndex(HttpServletRequest request) { + String click = request.getParameter("click"); + boolean isNumeric = click.chars().allMatch(Character::isDigit); + return isNumeric ? Integer.parseInt(click) : 0; + } + + private Field extractField(HttpSession currentSession) { + Object fieldAttribute = currentSession.getAttribute("field"); + if (Field.class != fieldAttribute.getClass()) { + currentSession.invalidate(); + throw new RuntimeException("Session is broken, try one more time"); + } + return (Field) fieldAttribute; + } + + /** + * Метод проверяет, нет ли трех крестиков/ноликов в ряд. + * Возвращает true/false + */ + private boolean checkWin(HttpServletResponse resp, HttpServletRequest req, HttpSession currentSession, Field field) throws IOException, ServletException { + Sign winner = field.checkWin(); + if (Sign.CROSS == winner || Sign.NOUGHT == winner) { + // Добавляем флаг, который показывает что кто-то победил + currentSession.setAttribute("winner", winner); + + // Считаем список значков + List data = field.getFieldData(); + + // Обновляем этот список в сессии + currentSession.setAttribute("data", data); + + // Шлем редирект + RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/index.jsp"); + dispatcher.forward(req, resp); + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/com/tictactoe/controller/RestartServlet.java b/src/main/java/com/tictactoe/controller/RestartServlet.java new file mode 100644 index 00000000..79594939 --- /dev/null +++ b/src/main/java/com/tictactoe/controller/RestartServlet.java @@ -0,0 +1,17 @@ +package com.tictactoe.controller; + +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet(name = "RestartServlet", value = "/restart") +public class RestartServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + req.getSession().invalidate(); + resp.sendRedirect("/start"); + } +} \ No newline at end of file diff --git a/src/main/java/com/tictactoe/Field.java b/src/main/java/com/tictactoe/entity/Field.java similarity index 95% rename from src/main/java/com/tictactoe/Field.java rename to src/main/java/com/tictactoe/entity/Field.java index c52d2a0d..8f94df38 100644 --- a/src/main/java/com/tictactoe/Field.java +++ b/src/main/java/com/tictactoe/entity/Field.java @@ -1,4 +1,4 @@ -package com.tictactoe; +package com.tictactoe.entity; import java.util.HashMap; import java.util.List; @@ -54,7 +54,7 @@ public Sign checkWin() { for (List winPossibility : winPossibilities) { if (field.get(winPossibility.get(0)) == field.get(winPossibility.get(1)) && field.get(winPossibility.get(0)) == field.get(winPossibility.get(2))) { - return field.get(winPossibility.get(0)); + return field.get(winPossibility.getFirst()); } } return Sign.EMPTY; diff --git a/src/main/java/com/tictactoe/Sign.java b/src/main/java/com/tictactoe/entity/Sign.java similarity index 66% rename from src/main/java/com/tictactoe/Sign.java rename to src/main/java/com/tictactoe/entity/Sign.java index e9db74d2..60186011 100644 --- a/src/main/java/com/tictactoe/Sign.java +++ b/src/main/java/com/tictactoe/entity/Sign.java @@ -1,4 +1,4 @@ -package com.tictactoe; +package com.tictactoe.entity; public enum Sign { EMPTY(' '), @@ -11,7 +11,4 @@ public enum Sign { this.sign = sign; } - public char getSign() { - return sign; - } } \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/index.jsp b/src/main/webapp/WEB-INF/index.jsp new file mode 100644 index 00000000..9ad6e6aa --- /dev/null +++ b/src/main/webapp/WEB-INF/index.jsp @@ -0,0 +1,65 @@ +<%@ page import="com.tictactoe.entity.Sign" %> +<%@ page contentType="text/html;charset=UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + Tic-Tac-Toe + + + + +

Tic-Tac-Toe

+ + + + + + + + + + + + + + + + +
${data.get(0).getSign()}${data.get(1).getSign()}${data.get(2).getSign()}
${data.get(3).getSign()}${data.get(4).getSign()}${data.get(5).getSign()}
${data.get(6).getSign()}${data.get(7).getSign()}${data.get(8).getSign()}
+
+ + + + +

CROSSES WIN!

+ +
+ +

NOUGHTS WIN!

+ +
+ +

IT'S A DRAW

+ +
+ +

+
+ + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..24917953 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp deleted file mode 100644 index 964cc071..00000000 --- a/src/main/webapp/index.jsp +++ /dev/null @@ -1,17 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - - - Tic-Tac-Toe - - -

Tic-Tac-Toe

- - - - - - \ No newline at end of file diff --git a/src/main/webapp/static/main.css b/src/main/webapp/static/main.css index e69de29b..dd98a687 100644 --- a/src/main/webapp/static/main.css +++ b/src/main/webapp/static/main.css @@ -0,0 +1,19 @@ +body { + text-align: center; +} +table { + display: flex; + align-items: center; + justify-content: center; +} +td { + border: 3px solid black; + padding: 10px; + border-collapse: separate; + margin: 10px; + width: 100px; + height: 100px; + font-size: 50px; + text-align: center; + empty-cells: show; +} From 9522c55ff49ffcc9e8c454931393da9ca8a95327 Mon Sep 17 00:00:00 2001 From: aleigi Date: Tue, 5 Mar 2024 16:24:44 +0300 Subject: [PATCH 2/2] MODIFY app --- src/main/java/com/tictactoe/entity/Sign.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/tictactoe/entity/Sign.java b/src/main/java/com/tictactoe/entity/Sign.java index 60186011..d4191e32 100644 --- a/src/main/java/com/tictactoe/entity/Sign.java +++ b/src/main/java/com/tictactoe/entity/Sign.java @@ -11,4 +11,7 @@ public enum Sign { this.sign = sign; } + public char getSign() { + return sign; + } } \ No newline at end of file