first commit

This commit is contained in:
co 2023-10-23 17:58:49 +02:00
parent b73cb02daf
commit 66dc169be0
6 changed files with 672 additions and 0 deletions

605
src/App.vue Normal file
View file

@ -0,0 +1,605 @@
<template>
<h2>
Wer die letzte Münze nimmt, verliert.<br />
Trainiere die KI!
</h2>
<br />
<H3>Münzen:</H3>
<b style="font-size: xx-large">{{ this.aktueller_muenzen_stand }}</b>
<br />
<br />
<div class="grid-container-spalten-2">
<div
class="grid-item-spalte"
v-bind:class="[
{ aktiv: this.wer_ist_dran_mensch },
{
inaktiv:
!this.wer_ist_dran_mensch || this.aktueller_muenzen_stand <= 0,
},
]"
>
<h3>Mensch</h3>
</div>
<div
class="grid-item-spalte"
v-bind:class="[
{ aktiv: !this.wer_ist_dran_mensch },
{
inaktiv:
this.wer_ist_dran_mensch || this.aktueller_muenzen_stand <= 0,
},
]"
>
<h3>KI</h3>
</div>
<div
v-bind:class="[
{ aktiv: this.wer_ist_dran_mensch },
{
inaktiv:
!this.wer_ist_dran_mensch || this.aktueller_muenzen_stand <= 0,
},
]"
>
<template v-for="index in this.max_muenzen_pro_zug">
<button class="btn btn-primary"
v-on:click="nimm(index, false)"
:disabled="!wer_ist_dran_mensch"
v-show="index <= this.aktueller_muenzen_stand"
>
nimm {{ this.gib_muenztext(index) }}
</button>
<br />
</template>
</div>
<div
class="grid-container-spalten-3"
v-bind:class="[
{ aktiv: !this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch == null },
]"
>
<div
class="grid-item-spalte"
v-bind:class="[
{ aktiv: !this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch == null },
]"
>
Anzahl Münzen
</div>
<div
class="grid-item-spalte"
v-bind:class="[
{ aktiv: !this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch == null },
]"
>
Mögliche Züge
</div>
<div
class="grid-item-spalte"
v-bind:class="[
{ aktiv: !this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch },
{ inaktiv: this.wer_ist_dran_mensch == null },
]"
>
Gemerkter Zug
</div>
<template
v-for="(element, element_index) in this.spielsituationen"
:key="element.anzahl_muenzen"
>
<div
class="grid-item-spalte"
v-bind:class="[
{
aktiv:
!this.wer_ist_dran_mensch &&
element.anzahl_muenzen == this.aktueller_muenzen_stand,
},
{
inaktiv:
!this.wer_ist_dran_mensch &&
element.anzahl_muenzen != this.aktueller_muenzen_stand,
},
]"
>
{{ element.anzahl_muenzen }}
</div>
<div
class="grid-item-spalte"
v-bind:class="[
{
aktiv:
!this.wer_ist_dran_mensch &&
element.anzahl_muenzen == this.aktueller_muenzen_stand,
},
{
inaktiv:
!this.wer_ist_dran_mensch &&
element.anzahl_muenzen != this.aktueller_muenzen_stand,
},
]"
>
<template v-for="zug_moeglichkeit in element.moegliche_zuege">
<button class="btn btn-primary"
v-on:click="nimm(zug_moeglichkeit, true)"
:disabled="
this.wer_ist_dran_mensch ||
element.anzahl_muenzen != this.aktueller_muenzen_stand
"
v-show="zug_moeglichkeit <= element.anzahl_muenzen"
>
nimm {{ zug_moeglichkeit }}
</button>
<br />
</template>
</div>
<div
class="grid-item-spalte"
v-bind:class="[
{
aktiv:
!this.wer_ist_dran_mensch &&
element.anzahl_muenzen == this.aktueller_muenzen_stand,
},
{
inaktiv:
!this.wer_ist_dran_mensch &&
element.anzahl_muenzen != this.aktueller_muenzen_stand,
},
]"
>
<button class="btn btn-primary"
disabled v-show="element.gemerkter_zug > 0">
{{ this.gib_gemerkter_zug_ausgabe(element.gemerkter_zug) }}
</button>
</div>
</template>
</div>
</div>
<br />
{{ this.ausgabe }}
<br />
<br />
<br />
<button class="btn btn-primary" @click="neuer_spieldurchgang">
neues Spiel (Münzstand zurücksetzen)
</button>
<br />
<br />
<br />
<div style="width: 800px; margin: auto">
<button class="btn btn-primary collapsible" style="background: grey">
Vertiefung: weitere Einstellungsmöglichkeiten
</button>
<div class="content" id="content0" style="text-align: center">
<br />
<button
class="btn btn-primary"
style="background-color: red"
@click="initialisiere_spiel"
>
Alle gelernten KI-Züge löschen.
</button>
<br />
<br />
<hr />
<br />
Durch jede Änderung werden die gelernten KI-Züge werden gelöscht.
<div class="row">
<div class="column" style="text-align: center">
<h3>Münzenanzahl</h3>
<button
class="btn btn-primary"
@click="update_anzahl_muenzen(--this.zustaende)"
>
-
</button>
&nbsp;
<b style="font-size: xx-large">{{ this.zustaende }}</b
>&nbsp;
<button
class="btn btn-primary"
@click="update_anzahl_muenzen(++this.zustaende)"
>
+
</button>
<br />
<br />
</div>
<div class="column" style="text-align: center">
<h3>max. Münzen pro Zug</h3>
<button
class="btn btn-primary"
@click="update_max_muenzen_pro_zug(--this.max_muenzen_pro_zug)"
>
-
</button>
&nbsp;
<b style="font-size: xx-large">{{ this.max_muenzen_pro_zug }}</b>
&nbsp;
<button
class="btn btn-primary"
@click="update_max_muenzen_pro_zug(++this.max_muenzen_pro_zug)"
>
+
</button>
<br />
<br />
</div>
</div>
</div>
</div>
<br />
<br />
</template>
<script>
export default {
name: "App",
components: {
// Zeichnung,
//HelloWorld
},
data() {
return {
wer_ist_dran_mensch: true,
aktueller_muenzen_stand: 4,
zustaende: 4,
max_muenzen_pro_zug: 3,
spielsituationen: [],
letzter_gewinner_mensch: null,
ausgabe: "",
};
},
computed: {
wer_ist_dran: function () {
if (this.wer_ist_dran_mensch == true) {
return "Mensch";
}
if (this.wer_ist_dran_mensch == false) {
return "KI";
}
if (this.wer_ist_dran_mensch == null) {
return "---";
}
return "";
},
},
methods: {
initialisiere_spiel() {
this.wer_ist_dran_mensch = true;
this.aktueller_muenzen_stand = this.zustaende;
this.ausgabe = "Spiel läuft";
this.spielsituationen = [];
let zug_moeglichkeiten = [];
for (let i = 1; i <= this.max_muenzen_pro_zug; i++) {
zug_moeglichkeiten.push(i);
}
for (let i = this.zustaende; i >= 1; i--) {
let situation = {
anzahl_muenzen: i,
moegliche_zuege: zug_moeglichkeiten,
gemerkter_zug: null,
geloeschte_zuege: [],
};
this.spielsituationen.push(situation);
}
},
neuer_spieldurchgang() {
this.aktueller_muenzen_stand = this.zustaende;
console.log("letzter gewinner: " + this.letzter_gewinner_mensch);
if (this.letzter_gewinner_mensch) {
this.loesche_gemerkten_zug();
} else {
this.reset_gemerkten_zug();
}
this.wer_ist_dran_mensch = true;
this.letzter_gewinner_mensch = null;
this.ausgabe = "Spiel läuft";
},
nimm(anzahl, ki_zug) {
if (this.aktueller_muenzen_stand > 0) {
let alter_muenzen_stand = this.aktueller_muenzen_stand;
this.aktueller_muenzen_stand -= anzahl;
let wer = "Der Mensch";
if (ki_zug) {
this.reset_gemerkten_zug();
this.merke_zug(alter_muenzen_stand, anzahl);
wer = "Die KI";
}
this.ausgabe = wer + " hat im letzten Zug " + this.gib_muenztext(anzahl) + "genommen.";
if (
this.aktueller_muenzen_stand <= 0 ||
this.spielsituationen[
this.spielsituationen.length - this.aktueller_muenzen_stand
].moegliche_zuege.length == 0
) {
this.letzter_gewinner_mensch = this.wer_ist_dran_mensch;
this.ausgabe += "Spielende: " + wer + " hat gewonnen.";
this.wer_ist_dran_mensch = null;
} else {
this.wer_ist_dran_mensch = !this.wer_ist_dran_mensch;
}
}
},
reset_gemerkten_zug() {
for (let i = 0; i < this.spielsituationen.length; i++) {
console.log(this.spielsituationen[i]);
let gemerkter = this.spielsituationen[i].gemerkter_zug;
if (gemerkter != null) {
this.spielsituationen[i].moegliche_zuege.push(gemerkter);
this.spielsituationen[i].moegliche_zuege.sort();
this.spielsituationen[i].gemerkter_zug = null;
}
}
},
loesche_gemerkten_zug() {
for (let i = 0; i < this.spielsituationen.length; i++) {
this.spielsituationen[i].gemerkter_zug = null;
}
},
merke_zug(alter_muenzen_stand, anzahl) {
console.log(this.spielsituationen[alter_muenzen_stand]);
this.spielsituationen[
this.spielsituationen.length - alter_muenzen_stand
].moegliche_zuege = this.array_remove_item_once(
this.spielsituationen[
this.spielsituationen.length - alter_muenzen_stand
].moegliche_zuege,
anzahl
);
this.spielsituationen[
this.spielsituationen.length - alter_muenzen_stand
].gemerkter_zug = anzahl;
},
array_remove_item_once(arr, value) {
arr = arr.filter(function (item) {
return item !== value;
});
return arr;
},
update_anzahl_muenzen(neue_anzahl) {
this.initialisiere_spiel();
},
update_max_muenzen_pro_zug(neue_anzahl) {
this.initialisiere_spiel();
},
gib_muenztext(anzahl) {
let rueckgabe = anzahl;
/*
let rueckgabe = anzahl + " Münzen";
if (anzahl == 1) {
rueckgabe = "1 Münze";
}
*/
return rueckgabe;
},
gib_gemerkter_zug_ausgabe(anzahl) {
if (anzahl > 0) {
return "nimm " + this.gib_muenztext(anzahl);
} else {
return "";
}
},
},
mounted() {
document.onreadystatechange = () => {
// collapsible
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function () {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
if (document.readyState == "complete") {
this.initialisiere_spiel();
}
};
},
};
//------------------------------------------------------------
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
* {
box-sizing: border-box;
}
.row {
display: flex;
}
/* Create two equal columns that sits next to each other */
.column {
flex: 50%;
padding: 10px;
/*border: solid black 1px;
/*height: 300px; /* Should be removed. Only for demonstration */
}
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #555;
}
.collapsible:after {
content: "\002B";
color: white;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212";
}
.content {
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.btn {
display: inline-block;
font-weight: 400;
color: #212529;
text-align: center;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: transparent;
border: 1px solid transparent;
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 0.25rem;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.btn:not(:disabled):not(.disabled) {
cursor: pointer;
}
.btn:disabled {
cursor: default;
background-color: lightgray;
color: grey
}
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
</style>
<style>
.grid-container-zeilen {
display: grid;
grid-template-columns: auto;
/*background-color: #2196f3;
padding: 10px;
*/
}
.grid-item-zeile {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 30px;
text-align: center;
}
.grid-container-spalten-2 {
display: grid;
grid-template-columns: auto auto;
background-color: #2196f3;
padding: 2px;
}
.grid-container-spalten-3 {
display: grid;
grid-template-columns: auto auto auto;
background-color: #2196f3;
padding: 2px;
}
.grid-item-spalte {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid white;
padding: 2px;
font-size: 20px;
text-align: center;
}
.aktiv {
/*color: lightgreen;*/
color: black;
background-color: lightgreen;
border: 1px solid lightgreen;
}
.inaktiv {
/* color: grey;*/
color: black;
background-color: lightgray;
border: 1px solid lightgray;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

63
src/generateColors.js Normal file
View file

@ -0,0 +1,63 @@
/* eslint-disable no-unused-vars */
export function generateDifferentColors(x) {
const colors = [];
const step = 360 / x; // Calculate the step size for hue
for (let i = 0; i < x; i++) {
const hue = i * step;
const saturation = 50; // You can adjust saturation and lightness as needed
const lightness = 50; // for your desired color appearance
// Convert HSL to RGB
const rgbColor = hslToRgb(hue / 360, saturation / 100, lightness / 100);
// Convert RGB to HEX
const hexColor = rgbToHex(rgbColor[0], rgbColor[1], rgbColor[2]);
colors.push(hexColor);
}
return colors;
}
function hslToRgb(h, s, l) {
let r, g, b;
if (s === 0) {
r = g = b = l; // Achromatic
} else {
const hueToRgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hueToRgb(p, q, h + 1 / 3);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1 / 3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
function rgbToHex(r, g, b) {
return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1).toUpperCase()}`;
}
//const numberOfColors = 10; // Change this to the number of colors you want
//const differentColors = generateDifferentColors(numberOfColors);
//console.log(differentColors);
export default {
name: 'generateColors',
props: {
}
}

4
src/main.js Normal file
View file

@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')