Skip to content

Commit 973b5af

Browse files
authored
Merge pull request #6652 from hozlucas28/Solution-42-Go
#42 - Go
2 parents b8f933d + 4fbbd80 commit 973b5af

File tree

1 file changed

+359
-0
lines changed

1 file changed

+359
-0
lines changed
Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"math"
7+
"math/rand/v2"
8+
"slices"
9+
)
10+
11+
/* -------------------------------------------------------------------------- */
12+
/* CLASSES */
13+
/* -------------------------------------------------------------------------- */
14+
15+
/* --------------------------------- Fighter -------------------------------- */
16+
17+
type IFighter interface {
18+
GetAttack() float64
19+
GetDefense() float64
20+
GetLife() float64
21+
GetName() string
22+
GetSpeed() float64
23+
SetLife(newLife float64) IFighter
24+
Clone() IFighter
25+
}
26+
27+
type fighter struct {
28+
attack float64
29+
defense float64
30+
life float64
31+
name string
32+
speed float64
33+
_ struct{}
34+
}
35+
36+
func NewFighter(attack float64, defense float64, life float64, name string, speed float64) IFighter {
37+
var fighter fighter = fighter{
38+
attack: attack,
39+
defense: defense,
40+
life: 100,
41+
name: name,
42+
speed: speed,
43+
}
44+
45+
return &fighter
46+
}
47+
48+
func (fgt *fighter) GetAttack() float64 {
49+
return fgt.attack
50+
}
51+
52+
func (fighter *fighter) GetDefense() float64 {
53+
return fighter.defense
54+
}
55+
56+
func (fighter *fighter) GetLife() float64 {
57+
return fighter.life
58+
}
59+
60+
func (fighter *fighter) GetName() string {
61+
return fighter.name
62+
}
63+
64+
func (fighter *fighter) GetSpeed() float64 {
65+
return fighter.speed
66+
}
67+
68+
func (fighter *fighter) SetLife(newLife float64) IFighter {
69+
if newLife > 0 {
70+
fighter.life = newLife
71+
} else {
72+
fighter.life = 0
73+
}
74+
75+
return fighter
76+
}
77+
78+
func (fgt *fighter) Clone() IFighter {
79+
var fighter IFighter = NewFighter(
80+
fgt.attack,
81+
fgt.defense,
82+
fgt.life,
83+
fgt.name,
84+
fgt.speed,
85+
)
86+
87+
return fighter
88+
}
89+
90+
/* ------------------------------- Tournament ------------------------------- */
91+
92+
type ShiftInformation struct {
93+
AttackDamage float64
94+
Attacker IFighter
95+
Shift int
96+
Victim IFighter
97+
_ struct{}
98+
}
99+
100+
type Round struct {
101+
InfoPerShift []ShiftInformation
102+
Looser IFighter
103+
Shifts int
104+
Winner IFighter
105+
_ struct{}
106+
}
107+
108+
type ITournament interface {
109+
GetPhase() int
110+
GetTeamA() []IFighter
111+
GetTeamB() []IFighter
112+
GetWinner() (IFighter, error)
113+
HasWinner() bool
114+
ExecuteNextRound() (Round, error)
115+
}
116+
117+
type tournament struct {
118+
pairOfFighters []IFighter
119+
phase int
120+
round int
121+
teamA []IFighter
122+
teamB []IFighter
123+
winner IFighter
124+
hasWinner bool
125+
}
126+
127+
func NewTournament(teamA []IFighter, teamB []IFighter) (ITournament, error) {
128+
if len(teamA) != len(teamB) {
129+
return nil, errors.New("The number of fighters in both teams must be equal")
130+
}
131+
132+
if (len(teamA)%2 != 0) || (len(teamB)%2 != 0) {
133+
return nil, errors.New("The number of fighters in both teams must be even")
134+
}
135+
136+
var tournament tournament = tournament{
137+
teamA: teamA,
138+
teamB: teamB,
139+
}
140+
141+
tournament.setRndPairOfFighters()
142+
143+
return &tournament, nil
144+
}
145+
146+
func (tournament *tournament) GetPhase() int {
147+
return tournament.phase
148+
}
149+
150+
func (tournament *tournament) GetTeamA() []IFighter {
151+
return tournament.teamA
152+
}
153+
154+
func (tournament *tournament) GetTeamB() []IFighter {
155+
return tournament.teamB
156+
}
157+
158+
func (tournament *tournament) GetWinner() (IFighter, error) {
159+
if !tournament.hasWinner {
160+
return tournament.winner, errors.New("The tournament has no winner")
161+
}
162+
163+
return tournament.winner, nil
164+
}
165+
166+
func (tournament *tournament) HasWinner() bool {
167+
return tournament.hasWinner
168+
}
169+
170+
func (tournament *tournament) setRndPairOfFighters() {
171+
var indexesToIgnoreA []int
172+
var indexesToIgnoreB []int
173+
174+
var rndIndex int
175+
var rndFighter IFighter
176+
177+
for range tournament.teamA {
178+
rndIndex = rand.IntN(len(tournament.teamA))
179+
for slices.Contains(indexesToIgnoreA, rndIndex) {
180+
rndIndex = rand.IntN(len(tournament.teamA))
181+
}
182+
183+
rndFighter = tournament.teamA[rndIndex]
184+
185+
tournament.pairOfFighters = append(tournament.pairOfFighters, rndFighter)
186+
indexesToIgnoreA = append(indexesToIgnoreA, rndIndex)
187+
188+
rndIndex = rand.IntN(len(tournament.teamB))
189+
for slices.Contains(indexesToIgnoreB, rndIndex) {
190+
rndIndex = rand.IntN(len(tournament.teamB))
191+
}
192+
193+
rndFighter = tournament.teamB[rndIndex]
194+
195+
tournament.pairOfFighters = append(tournament.pairOfFighters, rndFighter)
196+
indexesToIgnoreB = append(indexesToIgnoreB, rndIndex)
197+
}
198+
}
199+
200+
func (tournament *tournament) ExecuteNextRound() (Round, error) {
201+
var round Round
202+
203+
if tournament.hasWinner {
204+
return round, errors.New("The tournament already has a winner")
205+
}
206+
207+
if len(tournament.pairOfFighters) < 2 {
208+
return round, errors.New("Not enough fighters to execute the next round")
209+
}
210+
211+
tournament.round += 1
212+
var offset int = tournament.round - 1
213+
214+
var fighter01 IFighter = tournament.pairOfFighters[offset]
215+
var fighter02 IFighter = tournament.pairOfFighters[offset+1]
216+
var fighterAux IFighter
217+
218+
if fighter01.GetSpeed() < fighter02.GetSpeed() {
219+
fighterAux = fighter01
220+
fighter01 = fighter02
221+
fighter02 = fighterAux
222+
}
223+
224+
var shifts int = 0
225+
var infoPerShift []ShiftInformation
226+
227+
for fighter01.GetLife() > 0 && fighter02.GetLife() > 0 {
228+
var attackDamage float64 = 0
229+
230+
if rand.Float32() > 0.2 {
231+
var attack float64 = fighter01.GetAttack()
232+
var defense float64 = fighter02.GetDefense()
233+
234+
attackDamage = math.Abs(attack - defense)
235+
if defense > attack {
236+
attackDamage = attackDamage * 0.1
237+
}
238+
239+
fighter02.SetLife(fighter02.GetLife() - attackDamage)
240+
}
241+
242+
shifts++
243+
244+
infoPerShift = append(infoPerShift, ShiftInformation{
245+
AttackDamage: attackDamage,
246+
Attacker: fighter01.Clone(),
247+
Victim: fighter02.Clone(),
248+
Shift: shifts,
249+
})
250+
251+
fighterAux = fighter01
252+
fighter01 = fighter02
253+
fighter02 = fighterAux
254+
}
255+
256+
fighter01 = tournament.pairOfFighters[offset]
257+
fighter02 = tournament.pairOfFighters[offset+1]
258+
259+
var looserIndex int
260+
261+
if fighter01.GetLife() > 0 {
262+
looserIndex = offset + 1
263+
} else {
264+
looserIndex = offset
265+
}
266+
267+
tournament.pairOfFighters = slices.Delete(tournament.pairOfFighters, looserIndex, looserIndex+1)
268+
269+
if len(tournament.pairOfFighters) < 2 {
270+
tournament.winner = tournament.pairOfFighters[0]
271+
tournament.hasWinner = true
272+
}
273+
274+
if tournament.round == len(tournament.pairOfFighters) {
275+
tournament.round = 0
276+
tournament.phase += 1
277+
}
278+
279+
if fighter01.GetLife() > 0 {
280+
round.Winner = fighter01.Clone()
281+
round.Looser = fighter02.Clone()
282+
} else {
283+
round.Winner = fighter02.Clone()
284+
round.Looser = fighter01.Clone()
285+
}
286+
287+
round.Shifts = shifts
288+
round.InfoPerShift = infoPerShift
289+
290+
return round, nil
291+
}
292+
293+
/* -------------------------------------------------------------------------- */
294+
/* MAIN */
295+
/* -------------------------------------------------------------------------- */
296+
297+
func main() {
298+
var teamA []IFighter = []IFighter{
299+
NewFighter(90, 80, 100, "Goku", 95),
300+
NewFighter(85, 75, 100, "Vegeta", 90),
301+
NewFighter(70, 65, 100, "Piccolo", 80),
302+
NewFighter(60, 55, 100, "Krillin", 70),
303+
}
304+
305+
var teamB []IFighter = []IFighter{
306+
NewFighter(88, 78, 100, "Frieza", 92),
307+
NewFighter(82, 72, 100, "Cell", 88),
308+
NewFighter(75, 65, 100, "Majin Buu", 85),
309+
NewFighter(65, 60, 100, "Broly", 75),
310+
}
311+
312+
tournament, err := NewTournament(teamA, teamB)
313+
if err != nil {
314+
panic(err)
315+
}
316+
317+
var rounds int = 0
318+
319+
for !tournament.HasWinner() {
320+
round, err := tournament.ExecuteNextRound()
321+
if err != nil {
322+
panic(err)
323+
}
324+
325+
rounds++
326+
327+
fmt.Printf("> Round %d (%s vs %s)...\n\n", rounds, round.Winner.GetName(), round.Looser.GetName())
328+
329+
for _, shift := range round.InfoPerShift {
330+
if shift.AttackDamage > 0 {
331+
fmt.Printf(
332+
"> Shift %d: %s attacks %s with an attack damage of %.2f.\n",
333+
shift.Shift,
334+
shift.Attacker.GetName(),
335+
shift.Victim.GetName(),
336+
shift.AttackDamage,
337+
)
338+
} else {
339+
fmt.Printf(
340+
"> Shift %d: %s attacks %s, but %s evades the attack.\n",
341+
shift.Shift,
342+
shift.Attacker.GetName(),
343+
shift.Victim.GetName(),
344+
shift.Victim.GetName(),
345+
)
346+
}
347+
}
348+
349+
fmt.Printf(
350+
"\n> %s wins the fight against %s in %d shifts!\n\n",
351+
round.Winner.GetName(),
352+
round.Looser.GetName(),
353+
round.Shifts,
354+
)
355+
}
356+
357+
winner, err := tournament.GetWinner()
358+
fmt.Printf("> The winner of the tournament is %s!", winner.GetName())
359+
}

0 commit comments

Comments
 (0)