-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.rb
150 lines (126 loc) · 4.85 KB
/
game.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
require 'set'
require_relative "player"
class Game
def initialize()
words = File.readlines("dictionary.txt").map(&:chomp)
@alphabet = "abcdefghijklmnopqrstuvxyz"
@dictionary = Set.new(words)
# @dictionary = ["abc", "bac", "cba"] # Just for testing in Pry. (Loads forever if set alphabet is loaded)
@players = []
@fragment = ""
@current_player = nil
@loosers = {}
@winners = Hash.new{0}
@remaining_players = 0
@wins_needed = 2
end
attr_reader :dictionary, :players, :fragment, :current_player, :alphabet, :loosers
def play_game
until game_over
play_round
reset_game
end
end
# Until we got a winner (1 remaining player), a guess is received(get_guess checks for validity, so only correct guesses arrive here)
# guess is then added to the fragment and next player is activated
# Add letter checks if the fragment is now a word, that is in the dictionary. if it is, the active player is kicked.
# if we got a winner after that guess, the game ends.
def play_round
until we_got_a_winner
add_letter(get_guess)
self.next_player!
if we_got_a_winner
puts "\n#{current_player.name} has won this round!"
@winners[@current_player] += 1
end
end
end
def reset_game
add_players(@players)
@fragment = ""
end
def game_over
@winners.each do |player, wins|
if wins == @wins_needed
return true
end
end
false
end
# If remaining players is down to 1, the last player has to be the winner
def we_got_a_winner
@remaining_players == 1
end
# Sets a players name in loosers-hash to true. Loosers are skipped by next_player!
def kick_player
@loosers[previous_player.name] = true
end
# asks a guess from current player
# with valid_play? loop it is made sure, that only valid guesses are returned
def get_guess
guess = @current_player.guess
if valid_play?(guess)
return guess
else
puts "This was not a valid guess. Has to be exactly one alphabetic letter!"
get_guess
end
end
# CHECKING AND WORKING WITH USER INPUT (GUESSES)
# return false, if alphabet does not include the letter.
# downcased, because alphabet-set is completely lowercase.
# by calling does_beginning_exist? It is made sure, that players must not add nonsense to the fragment
def valid_play?(letter)
return false unless @alphabet.include?(letter.downcase)
potential_fragment = @fragment + letter
does_beginning_exist?(potential_fragment)
end
# goes through dictionary and checks every word. if any word starts_with? the potential fragment returns true. if not false
def does_beginning_exist?(fragment)
@dictionary.any? {|word| word.start_with?(fragment)}
end
# adds a letter to the fragment.
# it then checks whether fragment is a word from the dictionary.
# if it is, the player is kicked(set to true in loosers / marked as a looser)
def add_letter(guessed_letter)
@fragment = @fragment + guessed_letter
if fragment_is_word(@fragment)
p "#{@fragment} is an actual word! You are out of the game!"
@fragment = ""
kick_player
@remaining_players -= 1
end
end
# checks if the fragment is a word from dict.
def fragment_is_word(fragment)
@dictionary.include?(fragment)
end
# HANDLING THE PLAYERS
# receives an array of players from session.rb
# goes through array catching every player
# initialising new player
# adding it to loosers as false (not a looser yet)
# sets remaining_players to array length
def add_players(array_of_players)
array_of_players.each do |player|
new_player = Player.new(player)
@players << new_player
@loosers[new_player.name] = false
@remaining_players = array_of_players.length
end
end
# current player is always first player of players array
def set_current_player
@current_player = @players.first
end
# previous player is alway last player of players array
def previous_player
@players[-1]
end
#rotates players once
# if current player then is a looser, rotates it again
def next_player!
@current_player = @players.rotate!.first
next_player! if @loosers[@current_player.name] == true
end
end