before mutliplayer
This commit is contained in:
@@ -66,6 +66,8 @@ public partial class MainWindow : Window
|
|||||||
private DateTimeOffset _lastStatsAt = DateTimeOffset.MinValue;
|
private DateTimeOffset _lastStatsAt = DateTimeOffset.MinValue;
|
||||||
private DateTimeOffset _lastStatusAt = DateTimeOffset.MinValue;
|
private DateTimeOffset _lastStatusAt = DateTimeOffset.MinValue;
|
||||||
private (int X, int Y)? _nearestEnemy;
|
private (int X, int Y)? _nearestEnemy;
|
||||||
|
private (int X, int Y)? _lastObservedEnemyRelative;
|
||||||
|
private (int X, int Y)? _enemyVelocityEstimate;
|
||||||
private Direction _lastMoveDirection = Direction.North;
|
private Direction _lastMoveDirection = Direction.North;
|
||||||
private Direction _escapeDirection = Direction.North;
|
private Direction _escapeDirection = Direction.North;
|
||||||
private int _recentDamageTicks;
|
private int _recentDamageTicks;
|
||||||
@@ -402,11 +404,20 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
var scan = await _client.ScanAsync(_playerToken, ct);
|
var scan = await _client.ScanAsync(_playerToken, ct);
|
||||||
MarkUsed(BotAction.Scan);
|
MarkUsed(BotAction.Scan);
|
||||||
|
var previousEnemy = _nearestEnemy;
|
||||||
var sx = scan.DifferenceToNearestPlayer?.X;
|
var sx = scan.DifferenceToNearestPlayer?.X;
|
||||||
var sy = scan.DifferenceToNearestPlayer?.Y;
|
var sy = scan.DifferenceToNearestPlayer?.Y;
|
||||||
_nearestEnemy = sx.HasValue && sy.HasValue ? (sx.Value, sy.Value) : null;
|
_nearestEnemy = sx.HasValue && sy.HasValue ? (sx.Value, sy.Value) : null;
|
||||||
if (_nearestEnemy.HasValue)
|
if (_nearestEnemy.HasValue)
|
||||||
{
|
{
|
||||||
|
if (previousEnemy.HasValue)
|
||||||
|
{
|
||||||
|
_enemyVelocityEstimate = (
|
||||||
|
_nearestEnemy.Value.X - previousEnemy.Value.X,
|
||||||
|
_nearestEnemy.Value.Y - previousEnemy.Value.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastObservedEnemyRelative = _nearestEnemy;
|
||||||
AddHeat(_x + _nearestEnemy.Value.X, _y + _nearestEnemy.Value.Y, 5.5);
|
AddHeat(_x + _nearestEnemy.Value.X, _y + _nearestEnemy.Value.Y, 5.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -461,6 +472,26 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
var underPressure = hpRatio < PressureHpThreshold(profile) || _recentDamageTicks > 0 || closeThreats >= PressureThreatThreshold(profile) || _survivalTicks > 0 || _pressureStreak >= 2;
|
var underPressure = hpRatio < PressureHpThreshold(profile) || _recentDamageTicks > 0 || closeThreats >= PressureThreatThreshold(profile) || _survivalTicks > 0 || _pressureStreak >= 2;
|
||||||
_lastUnderPressure = underPressure;
|
_lastUnderPressure = underPressure;
|
||||||
|
var predictedEnemy = PredictEnemyRelative();
|
||||||
|
|
||||||
|
var bestSight = _lastPeek
|
||||||
|
.Where(x => x.Value.Executed && x.Value.PlayersInSight > 0)
|
||||||
|
.OrderBy(x => x.Value.SightedPlayerDistance ?? int.MaxValue)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (Ready(BotAction.Hit) && immediateDir.HasValue && closeThreats >= 1)
|
||||||
|
{
|
||||||
|
var dir = immediateDir.Value;
|
||||||
|
return new BotDecision(
|
||||||
|
"hit-lock",
|
||||||
|
$"Enemy committed in close range at {dir}; preemptive melee pressure.",
|
||||||
|
async ct =>
|
||||||
|
{
|
||||||
|
var response = await _client.HitAsync(_playerToken, (int)dir, ct);
|
||||||
|
MarkUsed(BotAction.Hit);
|
||||||
|
return response.Executed;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Teleport if we can and enemies are nearby - aggressive repositioning for kills
|
// Teleport if we can and enemies are nearby - aggressive repositioning for kills
|
||||||
if (Ready(BotAction.Teleport) && closeThreats >= 1 && _nearestEnemy.HasValue)
|
if (Ready(BotAction.Teleport) && closeThreats >= 1 && _nearestEnemy.HasValue)
|
||||||
@@ -487,10 +518,28 @@ public partial class MainWindow : Window
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Ready(BotAction.Dash) && TryGetAggressiveDashDirection(predictedEnemy, bestSight, out var dashDirection, out var dashReason))
|
||||||
|
{
|
||||||
|
return new BotDecision(
|
||||||
|
"dash-aggro",
|
||||||
|
dashReason,
|
||||||
|
async ct =>
|
||||||
|
{
|
||||||
|
var response = await _client.DashAsync(_playerToken, (int)dashDirection, ct);
|
||||||
|
MarkUsed(BotAction.Dash);
|
||||||
|
if (response.Executed)
|
||||||
|
{
|
||||||
|
ApplyMovement(dashDirection, Math.Max(response.BlocksDashed, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Executed;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var specialThreatThreshold = SpecialThreatThreshold(profile);
|
var specialThreatThreshold = SpecialThreatThreshold(profile);
|
||||||
var specialHpFloor = SpecialHpFloor(profile);
|
var specialHpFloor = SpecialHpFloor(profile);
|
||||||
|
|
||||||
if (Ready(BotAction.Special) && closeThreats >= specialThreatThreshold)
|
if (Ready(BotAction.Special) && closeThreats >= specialThreatThreshold && (hpRatio >= specialHpFloor || closeThreats > specialThreatThreshold))
|
||||||
{
|
{
|
||||||
return new BotDecision(
|
return new BotDecision(
|
||||||
"specialattack",
|
"specialattack",
|
||||||
@@ -575,22 +624,14 @@ public partial class MainWindow : Window
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var bestSight = _lastPeek
|
if (Ready(BotAction.Shoot) && TryGetPredictiveShotDirection(bestSight.Key, bestSight.Value, predictedEnemy, out var shotDirection, out var shotReason))
|
||||||
.Where(x => x.Value.Executed && x.Value.PlayersInSight > 0)
|
|
||||||
.OrderBy(x => x.Value.SightedPlayerDistance ?? int.MaxValue)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
// More aggressive shooting
|
|
||||||
if (bestSight.Value is not null && Ready(BotAction.Shoot))
|
|
||||||
{
|
{
|
||||||
var dir = bestSight.Key;
|
|
||||||
var dist = bestSight.Value.SightedPlayerDistance ?? 99;
|
|
||||||
return new BotDecision(
|
return new BotDecision(
|
||||||
"shoot",
|
"shoot",
|
||||||
$"Enemy at {dir} ({dist} dist); ranged kill.",
|
shotReason,
|
||||||
async ct =>
|
async ct =>
|
||||||
{
|
{
|
||||||
var response = await _client.ShootAsync(_playerToken, (int)dir, ct);
|
var response = await _client.ShootAsync(_playerToken, (int)shotDirection, ct);
|
||||||
MarkUsed(BotAction.Shoot);
|
MarkUsed(BotAction.Shoot);
|
||||||
return response.Executed;
|
return response.Executed;
|
||||||
});
|
});
|
||||||
@@ -641,7 +682,6 @@ public partial class MainWindow : Window
|
|||||||
foreach (var dir in scored.Keys.ToArray())
|
foreach (var dir in scored.Keys.ToArray())
|
||||||
{
|
{
|
||||||
var score = 0.0;
|
var score = 0.0;
|
||||||
// Always chase aggressively - ignore radar safety
|
|
||||||
score += scored[dir] * 0.5;
|
score += scored[dir] * 0.5;
|
||||||
|
|
||||||
if (_lastPeek.TryGetValue(dir, out var peek) && peek.Executed)
|
if (_lastPeek.TryGetValue(dir, out var peek) && peek.Executed)
|
||||||
@@ -656,8 +696,8 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
if (_nearestEnemy.HasValue)
|
if (_nearestEnemy.HasValue)
|
||||||
{
|
{
|
||||||
var targetDir = DirectionFromVector(_nearestEnemy.Value.X, _nearestEnemy.Value.Y);
|
var targetVector = PredictEnemyRelative() ?? _nearestEnemy.Value;
|
||||||
// Always move toward nearest enemy
|
var targetDir = DirectionFromVector(targetVector.X, targetVector.Y);
|
||||||
if (dir == targetDir)
|
if (dir == targetDir)
|
||||||
{
|
{
|
||||||
score += 12.0;
|
score += 12.0;
|
||||||
@@ -927,6 +967,96 @@ public partial class MainWindow : Window
|
|||||||
_ => hpRatio < 0.02,
|
_ => hpRatio < 0.02,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private (int X, int Y)? PredictEnemyRelative()
|
||||||
|
{
|
||||||
|
if (!_nearestEnemy.HasValue)
|
||||||
|
{
|
||||||
|
return _lastObservedEnemyRelative;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_enemyVelocityEstimate is null)
|
||||||
|
{
|
||||||
|
return _nearestEnemy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
_nearestEnemy.Value.X + _enemyVelocityEstimate.Value.X,
|
||||||
|
_nearestEnemy.Value.Y + _enemyVelocityEstimate.Value.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetPredictiveShotDirection(
|
||||||
|
Direction? sightDirection,
|
||||||
|
PeekEntitiesAsyncResponse? sightResponse,
|
||||||
|
(int X, int Y)? predictedEnemy,
|
||||||
|
out Direction direction,
|
||||||
|
out string reason)
|
||||||
|
{
|
||||||
|
if (sightDirection is null || sightResponse is null)
|
||||||
|
{
|
||||||
|
if (predictedEnemy.HasValue)
|
||||||
|
{
|
||||||
|
direction = DirectionFromVector(predictedEnemy.Value.X, predictedEnemy.Value.Y);
|
||||||
|
reason = $"Predicted enemy lane -> {direction}; taking lead shot.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
direction = Direction.North;
|
||||||
|
reason = string.Empty;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentDir = sightDirection.Value;
|
||||||
|
var dist = sightResponse.SightedPlayerDistance ?? 99;
|
||||||
|
if (predictedEnemy.HasValue && dist >= 2)
|
||||||
|
{
|
||||||
|
var predictedDir = DirectionFromVector(predictedEnemy.Value.X, predictedEnemy.Value.Y);
|
||||||
|
if (predictedDir != currentDir)
|
||||||
|
{
|
||||||
|
direction = predictedDir;
|
||||||
|
reason = $"Enemy moving toward {predictedDir}; lead shot instead of static line {currentDir}.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
direction = currentDir;
|
||||||
|
reason = $"Enemy at {currentDir} ({dist} dist); ranged kill.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetAggressiveDashDirection(
|
||||||
|
(int X, int Y)? predictedEnemy,
|
||||||
|
KeyValuePair<Direction, PeekEntitiesAsyncResponse>? bestSight,
|
||||||
|
out Direction direction,
|
||||||
|
out string reason)
|
||||||
|
{
|
||||||
|
if (_nearestEnemy.HasValue)
|
||||||
|
{
|
||||||
|
var target = predictedEnemy ?? _nearestEnemy.Value;
|
||||||
|
var dist = Math.Abs(target.X) + Math.Abs(target.Y);
|
||||||
|
if (dist >= 2 && dist <= 6)
|
||||||
|
{
|
||||||
|
direction = DirectionFromVector(target.X, target.Y);
|
||||||
|
reason = $"Aggressive gap-close toward enemy at {direction} (predicted distance {dist}).";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestSight.HasValue && bestSight.Value.Value.Executed && bestSight.Value.Value.PlayersInSight > 0)
|
||||||
|
{
|
||||||
|
var dist = bestSight.Value.Value.SightedPlayerDistance ?? 99;
|
||||||
|
if (dist >= 2 && dist <= 5)
|
||||||
|
{
|
||||||
|
direction = bestSight.Value.Key;
|
||||||
|
reason = $"Enemy visible at {direction} ({dist} dist); dash to force close-range combat.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
direction = Direction.North;
|
||||||
|
reason = string.Empty;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void MarkVisit(int x, int y, double amount)
|
private void MarkVisit(int x, int y, double amount)
|
||||||
{
|
{
|
||||||
var key = (x, y);
|
var key = (x, y);
|
||||||
|
|||||||
288
DDApp/DDApplication/multiplayer.txt
Normal file
288
DDApp/DDApplication/multiplayer.txt
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
Digital Dojo <https://dd.countit.at/> Menü //
|
||||||
|
|
||||||
|
* //Coden lernen<https://dd.countit.at/programmieren-lernen>
|
||||||
|
o //Programmier-Roadmap <https://dd.countit.at/programmieren-lernen>
|
||||||
|
o //Programmierschule <https://dd.countit.at/programmierschule>
|
||||||
|
o //Übungsräume <https://dd.countit.at/dojos>
|
||||||
|
o //Katas <https://dd.countit.at/katas>
|
||||||
|
o //Tutorials <https://dd.countit.at/tutorials>
|
||||||
|
* //Dojo Game<https://dd.countit.at/dojo-game/multiplayer-modus>
|
||||||
|
o //Besiege unseren Bot <https://dd.countit.at/dojo-game>
|
||||||
|
o //Spieleinstieg <https://dd.countit.at/dojo-game/spieleinstieg>
|
||||||
|
o //Levels & Bots <https://dd.countit.at/dojo-game/levels>
|
||||||
|
o //Leaderboard <https://dd.countit.at/dojo-game/leaderboard>
|
||||||
|
o //Multiplayer Modus <https://dd.countit.at/dojo-game/
|
||||||
|
multiplayer-modus>
|
||||||
|
o //Tipps <https://dd.countit.at/dojo-game/tipps>
|
||||||
|
* //Programmier-Challenge <https://dd.countit.at/programmierwettbewerb>
|
||||||
|
* //Bewerben <https://dd.countit.at/bewerben>
|
||||||
|
* //Feedback <https://dd.countit.at/feedback>
|
||||||
|
* // <#>
|
||||||
|
Ausloggen
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
/
|
||||||
|
/
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
//Teilen //Facebook <https://www.facebook.com/sharer/sharer.php?
|
||||||
|
u=https%3A%2F%2Fdd.countit.at%2Fdojo-game%2Fmultiplayer-modus> //
|
||||||
|
Instagram <https://www.instagram.com/count_it_group/> //LinkedIn
|
||||||
|
<https://www.linkedin.com/shareArticle?
|
||||||
|
mini=true&url=https%3A%2F%2Fdd.countit.at%2Fdojo-game%2Fmultiplayer-
|
||||||
|
modus&title=&summary=&source=> //E-Mail <mailto:m.mustermann@countit.at?
|
||||||
|
subject=Lese-
|
||||||
|
Tipp%3A%20Dojo%20Game%20%7C%20Multiplayer%20Modus&body=Hey%2C%0D%0A%0D%0Aich%20habe%20auf%20https%3A%2F%2Fkarriere.countit.at%20einen%20Beitrag%20gefunden%2C%20der%20dich%20interessieren%20k%C3%B6nnte%3A%0D%0A%22Dojo%20Game%20%7C%20Multiplayer%20Modus%22%0D%0ASchau%20ihn%20dir%20mal%20an%3A%20https%3A%2F%2Fkarriere.countit.at%2Fdojo-game%2Fmultiplayer-modus%3Fkaid%3Dsharemail%0D%0A%0D%0ABeste%20Gr%C3%BC%C3%9Fe>
|
||||||
|
|
||||||
|
|
||||||
|
Der Multiplayer Modus
|
||||||
|
|
||||||
|
|
||||||
|
Dojo Game
|
||||||
|
|
||||||
|
|
||||||
|
//Multiplayer Modus
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Der Mutiplayer Modus basiert auf einem *Lobby System*. Erstelle eine
|
||||||
|
Lobby, lade Freunde ein oder spiele mit anderen Usern! Alle
|
||||||
|
Möglichkeiten stehen dir offen.
|
||||||
|
|
||||||
|
Desto mehr Spieler in einer Lobby sind, mit welchen du zuvor noch nicht
|
||||||
|
viel gespielt hast, desto mehr Punkte werden dir für eine gute
|
||||||
|
Platzierung gutgeschrieben. Der Mehrspieler Modus funktioniert mit den
|
||||||
|
selben API-Aufrufen <https://dd.countit.at/dojo-game/spieleinstieg#api>
|
||||||
|
wie der Singleplayer - es werden lediglich Bots durch Spieler ersetzt.
|
||||||
|
Du kannst daher deinen Einzelspieler Code auch für Mehrspieler Matches
|
||||||
|
verwenden.
|
||||||
|
|
||||||
|
|
||||||
|
*Viel Spaß!*
|
||||||
|
|
||||||
|
|
||||||
|
// Lobby Manager
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
Lobby-Key
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
/
|
||||||
|
//
|
||||||
|
|
||||||
|
//Starten <https://dd.countit.at/lobby/start>
|
||||||
|
//Verlassen <https://dd.countit.at/lobby/leave>
|
||||||
|
//Schließen <https://dd.countit.at/lobby/close>
|
||||||
|
// tikaiz1 ADMIN
|
||||||
|
// Bot
|
||||||
|
// Bot
|
||||||
|
// Bot
|
||||||
|
// Bot
|
||||||
|
// Bot
|
||||||
|
|
||||||
|
|
||||||
|
// Dein derzeitiger Spielstand
|
||||||
|
|
||||||
|
|
||||||
|
Deine Tötungen: *21*
|
||||||
|
|
||||||
|
Deine Tode: *43*
|
||||||
|
|
||||||
|
Dein Leben: *(7/10)*
|
||||||
|
|
||||||
|
|
||||||
|
// Server Status
|
||||||
|
|
||||||
|
Server - Adresse: game-dd.countit.at
|
||||||
|
|
||||||
|
Port: 80 (optional)
|
||||||
|
|
||||||
|
Status: Online
|
||||||
|
|
||||||
|
|
||||||
|
//Wichtige Informationen
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//Der Start
|
||||||
|
|
||||||
|
Um eine Lobby zu starten, müssen mindestens die minimale Anzahl an
|
||||||
|
Spielern in einer Lobby sein - standardmäßig sind dies 2. Wir das Spiel
|
||||||
|
dann gestartet, wird die Lobby aus der Liste entfernt, da diese dann
|
||||||
|
nicht mehr benötigt wird. Spielern wird die eigene Lobby nach dem Start
|
||||||
|
nicht mehr angezeigt.
|
||||||
|
|
||||||
|
|
||||||
|
//Dein Algorithmus
|
||||||
|
|
||||||
|
Dein Algorithmus kann schon laufen bevor deine Lobby gestartet wurde.
|
||||||
|
Dein Code wird, sobald eine Verbindung zu einem Spiel hergestellt wurde,
|
||||||
|
automatisch Befehle ausführen.
|
||||||
|
*Vorsicht:* Du darfst deinen Singleplayer Code nicht 1:1 übernehmen.
|
||||||
|
Wenn du ein Lobby Game spielst, darfst du zuvor keine Singleplayer Game
|
||||||
|
Instanz erstellen.
|
||||||
|
|
||||||
|
|
||||||
|
//Dein Spieler
|
||||||
|
|
||||||
|
Dein Spieler ist im Multiplayer mit den selben Stärken und Fähigkeiten
|
||||||
|
ausgestattet wie im Singleplayer. In diesem Modus sind alle Spieler
|
||||||
|
gleich stark - es gibt keine unterschiedlichen Klassen, denn es geht
|
||||||
|
darum, wer den besten Code hat.
|
||||||
|
|
||||||
|
|
||||||
|
//Rangliste
|
||||||
|
|
||||||
|
Unsere Rangliste wird durch Kills und an der Vielzahl der verschiedenen
|
||||||
|
Gegner in einem Match berechnet. Spielst du gegen neue Gegner oder
|
||||||
|
andere Spieler, mit welchen du noch nicht all zu viel gespielt hast,
|
||||||
|
bekommst du mehr Punkte als wenn du beispielsweise immer mit denselben 3
|
||||||
|
Freunden spielst.
|
||||||
|
|
||||||
|
|
||||||
|
//Public/Private Lobby
|
||||||
|
|
||||||
|
Eine öffentliche Lobby ist für jeden Nutzer zugänglich und kann mit
|
||||||
|
jedem Spieler gespielt werden. Eine geschlossene und private Lobby ist
|
||||||
|
nur für jene Spieler zugänglich, welche von einem bereits in der Lobby
|
||||||
|
vorhandenen Spieler den Lobby-Key o.a. Lobby-ID erhalten haben. Beim
|
||||||
|
Eintreten in eine private Lobby wird nach diesem Key verlangt.
|
||||||
|
|
||||||
|
|
||||||
|
//Lobby Admin
|
||||||
|
|
||||||
|
Standardmäßig ist der Ersteller einer Lobby der Admin für die derzeitige
|
||||||
|
Sitzung. Verlässt dieser Nutzer die Lobby, wird durch ein Zufallsprinzip
|
||||||
|
ein neuer Admin ausgewählt. Das Spiel kann nur vom Lobby-Admin
|
||||||
|
geschlossen oder gestartet werden.
|
||||||
|
|
||||||
|
|
||||||
|
//Update Changelog
|
||||||
|
|
||||||
|
Es sind seit dem neuesten Update nur 2 Spieler notwendig, um eine Lobby
|
||||||
|
zu starten. Zusätzlich wurde die Interkation mit dem User durch
|
||||||
|
verbesserte Nachrichten und Übersetzungen optimiert.
|
||||||
|
|
||||||
|
|
||||||
|
Übung macht den Meister!
|
||||||
|
|
||||||
|
Du möchtest deine Skills noch ein wenig trainieren? Dann führe ein paar
|
||||||
|
Katas aus!
|
||||||
|
|
||||||
|
Katas //
|
||||||
|
<https://dd.countit.at/katas>
|
||||||
|
/
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
|
||||||
|
Dojo - virtueller Übungsraum
|
||||||
|
|
||||||
|
Löse die Dojo-Aufgaben und werde Programmier-Profi!
|
||||||
|
|
||||||
|
Zu den Dojos // <https://dd.countit.at/dojos>
|
||||||
|
/
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
|
||||||
|
Ultimative Coding-Roadmap
|
||||||
|
|
||||||
|
Unsere Roadmap weist dir den Weg zum Coding-Profi!
|
||||||
|
|
||||||
|
Mehr erfahren // <https://dd.countit.at/programmieren-lernen>
|
||||||
|
/
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
|
||||||
|
Bewerbung bei COUNT IT
|
||||||
|
|
||||||
|
Starte deine Karriere als Softwareentwickler*in bei COUNT IT.
|
||||||
|
|
||||||
|
Zum Formular! // <https://dd.countit.at/bewerben>
|
||||||
|
|
||||||
|
|
||||||
|
Über Digital Dojo
|
||||||
|
|
||||||
|
Das Digital Dojo ist der virtuelle Übungsraum von COUNT IT.
|
||||||
|
|
||||||
|
Angehende Programmierer*innen, Code-Neulinge, Wiedereinsteiger*innen und
|
||||||
|
Fortgeschrittene finden hier das nötige Rüstzeug für ihre Karriere.
|
||||||
|
|
||||||
|
Du möchtest deine Lehre bei COUNT IT starten? Dann bist du hier richtig
|
||||||
|
- besiege deine Gegner im Dojo Game und sichere dir deine Lehrstelle!
|
||||||
|
|
||||||
|
Inspire your career.
|
||||||
|
|
||||||
|
|
||||||
|
Navigation
|
||||||
|
|
||||||
|
Programmieren lernen <https://dd.countit.at/programmieren-lernen> News
|
||||||
|
<https://dd.countit.at/news>
|
||||||
|
Programmierschule <https://dd.countit.at/programmierschule> Partner
|
||||||
|
<https://dd.countit.at/partner>
|
||||||
|
Programmier-Challenge <https://dd.countit.at/programmierwettbewerb>
|
||||||
|
Dojo Game <https://dd.countit.at/dojo-game>
|
||||||
|
|
||||||
|
|
||||||
|
Datenschutz <https://www.countit.at/datenschutz> Karriere @ COUNT IT
|
||||||
|
<https://karriere.countit.at/>
|
||||||
|
Impressum <https://www.countit.at/impressum> COUNT IT
|
||||||
|
Softwarehouse <https://it.countit.at/>
|
||||||
|
|
||||||
|
|
||||||
|
Newsletter abonnieren
|
||||||
|
|
||||||
|
Der COUNT IT Newsletter liefert viermal jährlich interessante
|
||||||
|
Neuigkeiten über das Unternehmen. Gleich anfordern!
|
||||||
|
|
||||||
|
E-Mail-Adresse
|
||||||
|
Senden
|
||||||
|
|
||||||
|
// <https://de-de.facebook.com/COUNTITGroup/> // <https://
|
||||||
|
www.instagram.com/count_it_group/> // <https://de.linkedin.com/company/
|
||||||
|
count-it-group>
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
COUNT IT Group verwendet Cookies, um die Website bestmöglich an die
|
||||||
|
Bedürfnisse der User anpassen zu können.
|
||||||
|
|
||||||
|
* Google
|
||||||
|
* Microsoft
|
||||||
|
* Ahrefs
|
||||||
|
* Statistik
|
||||||
|
|
||||||
|
Akzeptieren
|
||||||
|
Individuelle EinstellungenIndividuelle Einstellungen ausblenden |
|
||||||
|
Datenschutzerklärung <https://www.countit.at/datenschutz>
|
||||||
|
|
||||||
|
Google
|
||||||
|
|
||||||
|
Google Analytics und Optimize aggregiert Daten über unsere Besucher und
|
||||||
|
ihr Verhalten auf unserer Website. Wir nutzen diese Informationen zur
|
||||||
|
Verbesserung unserer Seite.
|
||||||
|
|
||||||
|
Microsoft
|
||||||
|
|
||||||
|
Microsoft aggregiert Daten über unsere Besucher und ihr Verhalten auf
|
||||||
|
unserer Website. Wir nutzen diese Informationen zur Verbesserung unserer
|
||||||
|
Seite.
|
||||||
|
|
||||||
|
Ahrefs
|
||||||
|
|
||||||
|
Ahrefs aggregiert Daten über unsere Besucher und ihr Verhalten auf
|
||||||
|
unserer Website. Wir nutzen diese Informationen zur Verbesserung unserer
|
||||||
|
Seite.
|
||||||
|
|
||||||
|
Statistik
|
||||||
|
|
||||||
|
Es werden grundlegend notwendige, anonymisierte Userdaten aufgezeichnet,
|
||||||
|
welche nur von uns für Auswertungen verwendet werden!
|
||||||
|
|
||||||
|
Cookie Entscheidung speichern
|
||||||
Reference in New Issue
Block a user