diff --git a/.gitignore b/.gitignore index ea8c4bf..ccb5166 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +.vscode \ No newline at end of file diff --git a/app/package-lock.json b/app/package-lock.json index 11a7e44..139e747 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -12,6 +12,7 @@ }, "devDependencies": { "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-static": "^3.0.4", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@types/eslint": "^9.6.0", @@ -988,6 +989,16 @@ "@sveltejs/kit": "^2.0.0" } }, + "node_modules/@sveltejs/adapter-static": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.4.tgz", + "integrity": "sha512-Qm4GAHCnRXwfWG9/AtnQ7mqjyjTs7i0Opyb8H2KH9rMR7fLxqiPx/tXeoE6HHo66+72CjyOb4nFH3lrejY4vzA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@sveltejs/kit": "^2.0.0" + } + }, "node_modules/@sveltejs/kit": { "version": "2.5.26", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.26.tgz", diff --git a/app/package.json b/app/package.json index 88e5ed1..da5534f 100644 --- a/app/package.json +++ b/app/package.json @@ -13,6 +13,7 @@ }, "devDependencies": { "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-static": "^3.0.4", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@types/eslint": "^9.6.0", diff --git a/app/src/lib/board.svelte b/app/src/lib/board.svelte index beab97a..16f1629 100644 --- a/app/src/lib/board.svelte +++ b/app/src/lib/board.svelte @@ -1,21 +1,27 @@
- {#each board as row, i} + {#each board.board as row, i} {#each row as cell, j} - callback(i, j)} /> + {/each} {/each}
diff --git a/app/src/lib/cell.svelte b/app/src/lib/cell.svelte deleted file mode 100644 index 5abf34f..0000000 --- a/app/src/lib/cell.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/app/src/lib/header.svelte b/app/src/lib/header.svelte index a9a7d0b..3a1ac88 100644 --- a/app/src/lib/header.svelte +++ b/app/src/lib/header.svelte @@ -2,7 +2,9 @@ import { Anchor } from 'lucide-svelte'; -
- +
+

Battleship Online

diff --git a/app/src/lib/state.svelte.ts b/app/src/lib/state.svelte.ts index 97ce06d..98fec78 100644 --- a/app/src/lib/state.svelte.ts +++ b/app/src/lib/state.svelte.ts @@ -1,8 +1,53 @@ - export type Phase = 'placement' | 'battle' | 'gameover'; -export type CellType = 'empty' | 'ship' | 'hit' | 'miss'; -export type Board = Array>; +export type CellType = 'e' | 's' | 'h' | 'm'; // empty, ship, hit, miss export class State { phase: Phase = $state('placement'); + playerBoard = $state(new Board(false)); + opponentBoard = $state(new Board(true)); } + +export class Board { + static shipTypes = [5, 4, 3, 3, 2]; + board: Array> = $state(Array.from({ length: 10 }, () => Array.from({ length: 10 }, () => 'e'))); + isOpponent: boolean = false; + + constructor(isOpponent: boolean) { + this.isOpponent = isOpponent; + if (!isOpponent) this.randomize(); + } + + set(x: number, y: number, type: CellType) { + this.board[x][y] = type; + } + + randomize() { + this.board = Array.from({ length: 10 }, () => Array.from({ length: 10 }, () => 'e')); + for (const shipLength of Board.shipTypes) { + while (true) { + const dir = Math.round(Math.random()); + const x = Math.floor(Math.random() * (dir ? 10 : 11 - shipLength)); + const y = Math.floor(Math.random() * (dir ? (11 - shipLength) : 10)); + if (this.isOverlapping(x, y, shipLength, dir)) continue; + for (let i = 0; i < shipLength; i++) { + this.board[dir ? x : x + i][dir ? y + i : y] = 's'; + } + break; + } + } + } + + isOverlapping(x: number, y: number, length: number, dir: number): boolean { + for (let i = -1; i < 2; i++) { + for (let j = -1; j < length + 1; j++) { + let [tx, ty] = [x + (dir ? i : j), y + (dir ? j : i)]; + if (tx < 0 || tx >= 10 || ty < 0 || ty >= 10) continue; + if (this.board[tx][ty] != 'e') return true; + } + } + return false; + } + +} + + diff --git a/app/src/routes/+layout.ts b/app/src/routes/+layout.ts new file mode 100644 index 0000000..d2c0be2 --- /dev/null +++ b/app/src/routes/+layout.ts @@ -0,0 +1,2 @@ +export const prerender = true; +export const ssr = false; \ No newline at end of file diff --git a/app/src/routes/+page.svelte b/app/src/routes/+page.svelte index 4c158d5..cc264f6 100644 --- a/app/src/routes/+page.svelte +++ b/app/src/routes/+page.svelte @@ -25,17 +25,22 @@

Your Board

- + {}} />

Opponent's Board

- + gameState.opponentBoard.set(i, j, 'h')} + />
{#if gameState.phase === 'placement'} - + {:else} {/if} diff --git a/app/svelte.config.js b/app/svelte.config.js index 4a82086..c58cb17 100644 --- a/app/svelte.config.js +++ b/app/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from '@sveltejs/adapter-auto'; +import adapter from '@sveltejs/adapter-static'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */ @@ -6,12 +6,16 @@ const config = { // Consult https://kit.svelte.dev/docs/integrations#preprocessors // for more information about preprocessors preprocess: vitePreprocess(), - kit: { - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. - // If your environment is not supported, or you settled on a specific environment, switch out the adapter. - // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter() + adapter: adapter({ + // default options are shown. On some platforms + // these options are set automatically — see below + pages: 'build', + assets: 'build', + fallback: undefined, + precompress: false, + strict: true + }) } }; diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..c522e2e --- /dev/null +++ b/src/game.rs @@ -0,0 +1,8 @@ +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct Board([[Option; 10]; 10]); + +impl Board { + // pub async fn new +} diff --git a/src/main.rs b/src/main.rs index 43927bc..af0aad5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ -use axum::{routing::get, Router}; +mod game; + +use axum::{routing::get, Json, Router}; use tokio::net::TcpListener; #[tokio::main]