mirror of
https://github.com/Kugelschieber/breach.git
synced 2026-01-18 12:00:25 +00:00
Hightlight active row/column, show error when field cannot be selected.
This commit is contained in:
@@ -27,7 +27,7 @@
|
|||||||
matrix: [
|
matrix: [
|
||||||
"AA", "BB", "CC",
|
"AA", "BB", "CC",
|
||||||
"DD", "AA", "BB",
|
"DD", "AA", "BB",
|
||||||
"CC", "DD", "AA",
|
"CC", "DD", "DD",
|
||||||
],
|
],
|
||||||
sequences: [
|
sequences: [
|
||||||
["AA", "CC", "DD"],
|
["AA", "CC", "DD"],
|
||||||
|
|||||||
@@ -2,34 +2,84 @@
|
|||||||
<div class="matrix">
|
<div class="matrix">
|
||||||
<h2>Code-Matrix</h2>
|
<h2>Code-Matrix</h2>
|
||||||
<div class="matrix-row" v-for="i in size" :key="i">
|
<div class="matrix-row" v-for="i in size" :key="i">
|
||||||
<div class="matrix-column" v-for="j in size" :key="j" v-on:click="select(i, j)">
|
<div :class="{'matrix-column': true, active: active.row === j || active.column === i, used: game.getCell(j-1, i-1).isUsed, error: error.row === j && error.column === i}"
|
||||||
{{matrix[(j - 1)*size + (i - 1)]}}
|
v-for="j in size" :key="j"
|
||||||
|
v-on:click="select(j, i)">
|
||||||
|
{{game.getCell(j-1, i-1).value}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Game } from "@/game/Game";
|
import { Game, matchState, matchSelectionState } from "@/game/Game";
|
||||||
import {defineComponent, inject, computed, Ref} from "vue";
|
import {defineComponent, inject, computed, Ref, ref} from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const game = inject("game") as Ref<Game>;
|
const game = inject("game") as Ref<Game>;
|
||||||
const size = computed(() => game.value.size);
|
const size = computed(() => game.value.size);
|
||||||
const matrix = computed(() => game.value.matrix);
|
const matrix = computed(() => game.value.matrix);
|
||||||
|
const state = computed(() => game.value.state);
|
||||||
|
const active = ref({row: -1, column: -1});
|
||||||
|
const error = ref({row: -1, column: -1});
|
||||||
|
let errorTimeout: number;
|
||||||
|
|
||||||
function select(row: number, column: number) {
|
function select(row: number, column: number) {
|
||||||
try {
|
try {
|
||||||
game.value.pick(row-1, column-1);
|
const newState = game.value.pick(row-1, column-1);
|
||||||
|
|
||||||
|
matchState({
|
||||||
|
Won: () => {
|
||||||
|
console.log("Won!");
|
||||||
|
},
|
||||||
|
Lost: () => {
|
||||||
|
console.log("Lost!");
|
||||||
|
},
|
||||||
|
InProgress: state => {
|
||||||
|
matchSelectionState({
|
||||||
|
Free: () => {/**/},
|
||||||
|
Row: () => {
|
||||||
|
active.value = {
|
||||||
|
row: -1,
|
||||||
|
column,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
Column: () => {
|
||||||
|
active.value = {
|
||||||
|
row,
|
||||||
|
column: -1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
})(state);
|
||||||
|
},
|
||||||
|
})(newState);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("nö!");
|
error.value = {
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(errorTimeout) {
|
||||||
|
clearTimeout(errorTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorTimeout = setTimeout(() => {
|
||||||
|
error.value = {
|
||||||
|
row: -1,
|
||||||
|
column: -1,
|
||||||
|
};
|
||||||
|
}, 500) as unknown as number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
game,
|
||||||
size,
|
size,
|
||||||
matrix,
|
matrix,
|
||||||
|
state,
|
||||||
|
active,
|
||||||
|
error,
|
||||||
select
|
select
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,20 @@
|
|||||||
const game = inject("game") as Ref<Game>;
|
const game = inject("game") as Ref<Game>;
|
||||||
const remainingMilliseconds = ref(game.value.remainingMilliseconds);
|
const remainingMilliseconds = ref(game.value.remainingMilliseconds);
|
||||||
const timeoutMilliseconds = computed(() => game.value.timeoutMilliseconds);
|
const timeoutMilliseconds = computed(() => game.value.timeoutMilliseconds);
|
||||||
const progress = computed(() => remainingMilliseconds.value/timeoutMilliseconds.value*100);
|
const progress = computed(() => {
|
||||||
const countdown = computed(() => (remainingMilliseconds.value/1000).toFixed(2));
|
if(remainingMilliseconds.value > 0) {
|
||||||
|
return remainingMilliseconds.value/timeoutMilliseconds.value*100;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
const countdown = computed(() => {
|
||||||
|
if(remainingMilliseconds.value > 0) {
|
||||||
|
return (remainingMilliseconds.value/1000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0.00";
|
||||||
|
});
|
||||||
|
|
||||||
const updateTime = () => {
|
const updateTime = () => {
|
||||||
remainingMilliseconds.value = game.value.remainingMilliseconds;
|
remainingMilliseconds.value = game.value.remainingMilliseconds;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ interface StateSpecificHandler<T> {
|
|||||||
InProgress(selectionState: SelectionState): T
|
InProgress(selectionState: SelectionState): T
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchState<T>(h: StateSpecificHandler<T>): (a: State) => T {
|
export function matchState<T>(h: StateSpecificHandler<T>): (a: State) => T {
|
||||||
return (a: State) => {
|
return (a: State) => {
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case EndState.Won:
|
case EndState.Won:
|
||||||
@@ -54,7 +54,7 @@ interface SelectionStateSpecificHandler<T> {
|
|||||||
Column(column: number): T;
|
Column(column: number): T;
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchSelectionState<T>(h: SelectionStateSpecificHandler<T>): (a: SelectionState) => T {
|
export function matchSelectionState<T>(h: SelectionStateSpecificHandler<T>): (a: SelectionState) => T {
|
||||||
return (a: SelectionState) => {
|
return (a: SelectionState) => {
|
||||||
switch (a.selectionMode) {
|
switch (a.selectionMode) {
|
||||||
case SelectionMode.FreePick:
|
case SelectionMode.FreePick:
|
||||||
@@ -162,7 +162,7 @@ export class Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pick(row: number, column: number): void {
|
pick(row: number, column: number): State {
|
||||||
if (row < 0 || column < 0 || row >= this.size || column >= this.size) {
|
if (row < 0 || column < 0 || row >= this.size || column >= this.size) {
|
||||||
throw new IllegalMoveError()
|
throw new IllegalMoveError()
|
||||||
}
|
}
|
||||||
@@ -215,6 +215,7 @@ export class Game {
|
|||||||
})(this.state)
|
})(this.state)
|
||||||
|
|
||||||
this.checkEndGame();
|
this.checkEndGame();
|
||||||
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxBufferLength(): number {
|
get maxBufferLength(): number {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
$background: #121018;
|
$background: #121018;
|
||||||
$yellow: #d0ee58;
|
$yellow: #d0ee58;
|
||||||
|
$red: rgb(211, 0, 0);
|
||||||
|
$dark-gray: rgb(49, 49, 49);
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -103,16 +105,35 @@ main {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 32px;
|
width: 64px;
|
||||||
height: 32px;
|
height: 64px;
|
||||||
margin: 0 5px 5px 0;
|
margin: 0 5px 5px 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
font-size: 32px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $yellow;
|
background: $yellow !important;
|
||||||
color: $background;
|
color: $background;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.used {
|
||||||
|
opacity: 0.5;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: none;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background: $dark-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background: $red !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2 {
|
h1, h2 {
|
||||||
|
|||||||
Reference in New Issue
Block a user