diff --git a/Backend/src/main/java/hsrt/VSundSOA/backendapi/GameController.java b/Backend/src/main/java/hsrt/VSundSOA/backendapi/GameController.java index b5edf7acbf41e9d9d70e50cec172b8fd2ac720f9..1134a86f1985826c8eef04bd61133d1589bac1b3 100644 --- a/Backend/src/main/java/hsrt/VSundSOA/backendapi/GameController.java +++ b/Backend/src/main/java/hsrt/VSundSOA/backendapi/GameController.java @@ -11,7 +11,7 @@ import java.util.*; @CrossOrigin(origins = "*") @RestController public class GameController { - private ArrayList<String> history = new ArrayList<>(); + private ArrayList<Placement> history = new ArrayList<>(); private Field field = new Field(); @PostConstruct @@ -21,23 +21,15 @@ public class GameController { @ResponseStatus(HttpStatus.OK) @GetMapping("/fields") - public ArrayList<int[][]> GetFields(){ - ArrayList<int[][]> fields = new ArrayList<>(); - fields.add(field.getStartField()); - fields.add(field.getSolutionField()); - return fields; + public int[][] GetFields(){ + return field.getStartField(); } @ResponseStatus(HttpStatus.OK) - @PutMapping("/game/{username}") - public Boolean ValidatePlacement(@PathVariable(name = "username") String username, @Valid @RequestBody @NotNull String placement){ - String[] placementValues = placement.split(" ", 3); - int x = Integer.parseInt(placementValues[0]); - int y = Integer.parseInt(placementValues[1]); - int value = Integer.parseInt(placementValues[2]); - - if (field.getSolutionField()[x][y] == value){ - history.add(username.concat(" " + placement)); + @PutMapping("/game/placement") + public Boolean ValidatePlacement(@Valid @RequestBody @NotNull Placement placement){ + if (field.getSolutionField()[placement.getX()][placement.getY()] == placement.getValue()){ + history.add(placement); return true; } return false; @@ -47,6 +39,7 @@ public class GameController { @GetMapping("/game/win") public Boolean VerifyWin(){ if (field.getCellsToFill() <= history.size()){ + history.clear(); return true; } return false; @@ -54,7 +47,7 @@ public class GameController { @ResponseStatus(HttpStatus.OK) @GetMapping("/game/history") - private ArrayList<String> getHistory(){ + private ArrayList<Placement> getHistory(){ return history; } } diff --git a/Backend/src/main/java/hsrt/VSundSOA/backendapi/Placement.java b/Backend/src/main/java/hsrt/VSundSOA/backendapi/Placement.java new file mode 100644 index 0000000000000000000000000000000000000000..80c9693fbcc901a6e2776efeb5d37636ea7fd2c9 --- /dev/null +++ b/Backend/src/main/java/hsrt/VSundSOA/backendapi/Placement.java @@ -0,0 +1,13 @@ +package hsrt.VSundSOA.backendapi; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Placement { + private String username; + private Integer x; + private Integer y; + private Integer value; +} diff --git a/Sudoku.html b/Sudoku.html index 0d6b82b82466592e7f4910a1d4d95f6b0506b53b..4a48ac6f779e84e66c5b95fb64f08f2c602b3dbb 100644 --- a/Sudoku.html +++ b/Sudoku.html @@ -9,274 +9,15 @@ <div id="options"> <h1>Sudoku with Friends</h1> <h2>Welcome, please enter your username</h2> - <input type="text" id="username" class="input" placeholder='Username'/> - <button type="button" id="login" class="button">Connect</button> + <input type="text" id="username" class="input" placeholder="Username"/> + <button type="button" id="login" class="button" onclick="loginOnClick()">Connect</button> </div> <div id="game"> <table id="Sudoku"> - <tr id="row1"> - <td id="1cell1"> - - </td> - <td id="1cell2"> - - </td> - <td id="1cell3"> - - </td> - <td id=1cell4"> - - </td> - <td id="1cell5"> - - </td> - <td id="1cell6"> - - </td> - <td id="1cell7"> - - </td> - <td id="1cell8"> - - </td> - <td id="1cell9"> - - </td> - </tr> - <tr id="row2"> - <td id="2cell1"> - - </td> - <td id="2cell2"> - - </td> - <td id="2cell3"> - - </td> - <td id="2cell4"> - - </td> - <td id="2cell5"> - - </td> - <td id="2cell6"> - - </td> - <td id="2cell7"> - - </td> - <td id="2cell8"> - - </td> - <td id="2cell9"> - - </td> - </tr> - <tr id="row3"> - <td id="3cell1"> - - </td> - <td id="3cell2"> - - </td> - <td id="3cell3"> - - </td> - <td id="3cell4"> - - </td> - <td id="3cell5"> - - </td> - <td id="3cell6"> - - </td> - <td id="3cell7"> - - </td> - <td id="3cell8"> - - </td> - <td id="3cell9"> - - </td> - </tr> - <tr id="row4"> - <td id="4cell1"> - - </td> - <td id="4cell2"> - - </td> - <td id="4cell3"> - - </td> - <td id="4cell4"> - - </td> - <td id="4cell5"> - - </td> - <td id="4cell6"> - - </td> - <td id="4cell7"> - - </td> - <td id="4cell8"> - - </td> - <td id="4cell9"> - - </td> - </tr> - <tr id="row5"> - <td id="5cell1"> - - </td> - <td id="5cell2"> - - </td> - <td id="5cell3"> - - </td> - <td id="5cell4"> - - </td> - <td id="5cell5"> - - </td> - <td id="5cell6"> - - </td> - <td id="5cell7"> - - </td> - <td id="5cell8"> - - </td> - <td id="5cell9"> - - </td> - </tr> - <tr id="row6"> - <td id="6cell1"> - - </td> - <td id="6cell2"> - - </td> - <td id="6cell3"> - - </td> - <td id="6cell4"> - - </td> - <td id="6cell5"> - - </td> - <td id="6cell6"> - - </td> - <td id="6cell7"> - - </td> - <td id="6cell8"> - - </td> - <td id="6cell9"> - - </td> - </tr> - <tr id="row7"> - <td id="7cell1"> - - </td> - <td id="7cell2"> - - </td> - <td id="7cell3"> - - </td> - <td id="7cell4"> - - </td> - <td id="7cell5"> - - </td> - <td id="7cell6"> - - </td> - <td id="7cell7"> - - </td> - <td id="7cell8"> - - </td> - <td id="7cell9"> - - </td> - </tr> - <tr id="row8"> - <td id="8cell1"> - - </td> - <td id="8cell2"> - - </td> - <td id="8cell3"> - - </td> - <td id="8cell4"> - - </td> - <td id="8cell5"> - - </td> - <td id="8cell6"> - - </td> - <td id="8cell7"> - - </td> - <td id="8cell8"> - - </td> - <td id="8cell9"> - - </td> - </tr> - <tr id="row9"> - <td id="9cell1"> - - </td> - <td id="9cell2"> - - </td> - <td id="9cell3"> - - </td> - <td id="9cell4"> - - </td> - <td id="9cell5"> - - </td> - <td id="9cell6"> - - </td> - <td id="9cell7"> - - </td> - <td id="9cell8"> - - </td> - <td id="9cell9"> - - </td> - </tr> </table> </div> - <script src=""></script> + <div id="number-pad" style="display: grid; grid-template-columns: 40px 40px 40px"> + </div> + <script src="Sudoku.js"></script> </body> </html> \ No newline at end of file diff --git a/Sudoku.js b/Sudoku.js new file mode 100644 index 0000000000000000000000000000000000000000..0f87f936712cfc92ced27fdc26c7abcbb9cd10a6 --- /dev/null +++ b/Sudoku.js @@ -0,0 +1,137 @@ +const GameAPI = 'http://localhost:8080'; + +let username = ''; +let activeNumber = 0; +let history = []; + +function createEmptySudokuGrid() { + const table = document.getElementById('Sudoku'); + for (let row = 0; row < 9; row++) { + const tr = document.createElement('tr'); + table.appendChild(tr) + for (let cell = 0; cell < 9; cell++) { + const td = document.createElement('td'); + td.id = `${row + 1}cell${cell + 1}`; + td.onclick = () => sudokuOnClickAsync(cell, row); + tr.appendChild(td); + } + } +} + +function createNumberPadButtons() { + const div = document.getElementById('number-pad'); + for (let i = 1; i <= 9; i++) { + const input = document.createElement('input'); + input.id = `number-pad-${i}`; + input.type = 'button'; + input.value = i.toString(); + input.style.backgroundColor = 'Gray'; + input.onclick = () => numbersOnClick(i); + div.append(input); + } +} + +async function fillSudokuGrid() { + const sudoku = await getFieldsAsync(); + for (let row = 0; row < 9; row++) { + for (let cell = 0; cell < 9; cell++) { + if (sudoku[row][cell] > 0) { + document.getElementById(`${row + 1}cell${cell + 1}`).innerText = sudoku[row][cell]; + } else { + document.getElementById(`${row + 1}cell${cell + 1}`).innerText = '_'; + } + } + } +} + +async function getFieldsAsync() { + const fields = await fetch(GameAPI + "/fields", {method: "GET"}); + return await fields.json(); +} + +async function getHistoryAsync() { + const history = await fetch(GameAPI + "/game/history", {method: "GET"}); + return await history.json(); +} + +async function getWinVerificationAsync() { + const win = await fetch(GameAPI + "/game/win", {method: 'GET'}); + return await win.json(); +} + +async function putPlacementAsync(placement) { + const move = await fetch(GameAPI + "/game/placement", { + method: "PUT", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(placement) + }); + return await move.json(); +} + +async function reloadOnTimerAsync() { + if (await getWinVerificationAsync()) { + window.alert("you won!"); + // Reset + history = []; + document.getElementById('Sudoku').remove(); + const table = document.createElement('table'); + table.id = 'Sudoku'; + document.getElementById('game').append(table); + } else { + const historyList = await getHistoryAsync(); + for (const element of historyList) { + if (history.find(h => h.x === element.x && h.y === element.y)) { + continue; + } + + history.push(element); + reloadCell(element.x, element.y, element.value, 'red'); + } + } +} + +function reloadCell(X, Y, value, color) { + document.getElementById(`${Y + 1}cell${X + 1}`).innerText = value.toString(); + document.getElementById(`${Y + 1}cell${X + 1}`).style.color = color; +} + +async function sudokuOnClickAsync(X, Y) { //how to get x, Y? + if (activeNumber < 1) { + return; + } + const placement = { + username: username, + x: X, + y: Y, + value: activeNumber + }; + const worked = await putPlacementAsync(placement); + if (worked) { + reloadCell(X, Y, activeNumber, 'green'); + history.push(placement); + } +} + +function numbersOnClick(number) { + activeNumber = number; + for (let i = 1; i <= 9; i++) { + document.getElementById(`number-pad-${i}`).style.backgroundColor = i === number ? 'Yellow' : 'Gray'; + } +} + +async function loginOnClick() { + username = document.getElementById('username').value; + document.getElementById('login').remove(); + document.getElementById('username').remove(); + const span = document.createElement("h2"); + span.innerText = username; + document.getElementById('options').append(span); + + createEmptySudokuGrid(); + createNumberPadButtons(); + + await fillSudokuGrid(); + await reloadOnTimerAsync(); + + setInterval(reloadOnTimerAsync, 2 * 1000); +} \ No newline at end of file