Skip to content

Commit cb41530

Browse files
committed
Refactoring-6: Replace global variables with procedure arguments
1 parent a5f5f2a commit cb41530

File tree

1 file changed

+66
-27
lines changed

1 file changed

+66
-27
lines changed

episodes/7-refactoring-fortran/solution/src/game_of_life.f90

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,10 @@ program game_of_life
88

99
implicit none
1010

11-
!! Board args
12-
integer, parameter :: max_generations = 100, max_nrows = 100, max_ncols = 100
13-
integer :: nrow, ncol, generation_number
14-
integer, dimension(:,:), allocatable :: current_board, new_board
15-
logical :: steady_state = .false.
16-
17-
!> Whether to animate the board
1811
logical, parameter :: animate = .true.
12+
integer, dimension(:,:), allocatable :: starting_board
13+
integer :: generation_number
14+
logical :: steady_state = .false.
1915

2016
!! CLI args
2117
character(len=:), allocatable :: executable_name, input_filename
@@ -30,9 +26,9 @@ program game_of_life
3026
stop
3127
end if
3228

33-
call read_model_from_file()
29+
call read_model_from_file(input_filename, starting_board)
3430

35-
call find_steady_state()
31+
call find_steady_state(steady_state, generation_number, starting_board, animate)
3632

3733
if (steady_state) then
3834
write(*,'(a,i6,a)') "Reached steady after ", generation_number, " generations"
@@ -43,7 +39,7 @@ program game_of_life
4339
contains
4440

4541
!> Read a cli arg at a given index and return it as a string (character array)
46-
recursive subroutine read_cli_arg(arg_index, arg)
42+
subroutine read_cli_arg(arg_index, arg)
4743
!> The index of the cli arg to try and read
4844
integer, intent(in) :: arg_index
4945
!> The string into which to store the cli arg
@@ -59,12 +55,16 @@ recursive subroutine read_cli_arg(arg_index, arg)
5955
end subroutine read_cli_arg
6056

6157
!> Populate the board from a provided file
62-
subroutine read_model_from_file()
58+
subroutine read_model_from_file(input_filename, board)
59+
character(len=:), allocatable, intent(in) :: input_filename
60+
integer, dimension(:,:), allocatable, intent(out) :: board
61+
6362
!> A flag to indicate if reading the file was successful
6463
character(len=:), allocatable :: io_error_message
6564

6665
! Board definition args
67-
integer :: row
66+
integer :: row, nrow, ncol
67+
integer, parameter :: max_nrows = 100, max_ncols = 100
6868

6969
! File IO args
7070
integer :: input_file_io, iostat
@@ -98,12 +98,12 @@ subroutine read_model_from_file()
9898

9999
if (.not. allocated(io_error_message)) then
100100

101-
allocate(current_board(nrow, ncol))
101+
allocate(board(nrow, ncol))
102102

103103
read(input_file_io,'(a)') text_to_discard ! Skip next line
104104
! Populate the boards starting state
105105
do row = 1, nrow
106-
read(input_file_io,*) current_board(row, :)
106+
read(input_file_io,*) board(row, :)
107107
end do
108108

109109
end if
@@ -118,14 +118,27 @@ subroutine read_model_from_file()
118118
end subroutine read_model_from_file
119119

120120
!> Find the steady state of the Game of Life board
121-
subroutine find_steady_state()
121+
subroutine find_steady_state(steady_state, generation_number, input_board, animate)
122+
!> Whether the board has reached a steady state
123+
logical, intent(out) :: steady_state
124+
!> The number of generations that have been processed
125+
integer, intent(out) :: generation_number
126+
!> The starting state of the board
127+
integer, dimension(:,:), allocatable, intent(in) :: input_board
128+
!> Whether to animate the board
129+
logical, intent(in) :: animate
130+
131+
integer, dimension(:,:), allocatable :: current_board, new_board
132+
integer, parameter :: max_generations = 100
122133

123134
!! Animation args
124135
integer, dimension(8) :: date_time_values
125136
integer :: mod_ms_step
126137
integer, parameter :: ms_per_step = 250
127138

128-
allocate(new_board(size(current_board,1), size(current_board, 2)))
139+
allocate(current_board(size(input_board,1), size(input_board, 2)))
140+
allocate(new_board(size(input_board,1), size(input_board, 2)))
141+
current_board = input_board
129142
new_board = 0
130143

131144
! Clear the terminal screen
@@ -143,10 +156,10 @@ subroutine find_steady_state()
143156
end if
144157

145158
if (mod_ms_step == 0) then
146-
call evolve_board()
147-
call check_for_steady_state()
159+
call evolve_board(current_board, new_board)
160+
call check_for_steady_state(steady_state, current_board, new_board)
148161
current_board = new_board
149-
if (animate) call draw_board()
162+
if (animate) call draw_board(current_board)
150163

151164
generation_number = generation_number + 1
152165
end if
@@ -155,8 +168,16 @@ subroutine find_steady_state()
155168
end subroutine find_steady_state
156169

157170
!> Evolve the board into the state of the next iteration
158-
subroutine evolve_board()
159-
integer :: row, col, sum
171+
subroutine evolve_board(current_board, new_board)
172+
!> The current state of the board
173+
integer, dimension(:,:), allocatable, intent(in) :: current_board
174+
!> The new state of the board
175+
integer, dimension(:,:), allocatable, intent(inout) :: new_board
176+
177+
integer :: row, col, sum, nrow, ncol
178+
179+
nrow = size(current_board, 1)
180+
ncol = size(current_board, 2)
160181

161182
do row=2, nrow-1
162183
do col=2, ncol-1
@@ -185,8 +206,18 @@ subroutine evolve_board()
185206
end subroutine evolve_board
186207

187208
!> Check if we have reached steady state, i.e. current and new board match
188-
subroutine check_for_steady_state()
189-
integer :: row, col
209+
subroutine check_for_steady_state(steady_state, current_board, new_board)
210+
!> Whether the board has reached a steady state
211+
logical, intent(out) :: steady_state
212+
!> The current state of the board
213+
integer, dimension(:,:), allocatable, intent(in) :: current_board
214+
!> The new state of the board
215+
integer, dimension(:,:), allocatable, intent(inout) :: new_board
216+
217+
integer :: row, col, nrow, ncol
218+
219+
nrow = size(current_board, 1)
220+
ncol = size(current_board, 2)
190221

191222
do row=1, nrow
192223
do col=1, ncol
@@ -200,17 +231,25 @@ subroutine check_for_steady_state()
200231
end subroutine check_for_steady_state
201232

202233
!> Output the current board to the terminal
203-
subroutine draw_board()
204-
integer :: row, col
205-
character(nrow) :: output
234+
subroutine draw_board(board)
235+
!> The current state of the board
236+
integer, dimension(:,:), allocatable, intent(in) :: board
237+
238+
integer :: row, col, nrow, ncol
239+
character(:), allocatable :: output
240+
241+
nrow = size(board, 1)
242+
ncol = size(board, 2)
243+
244+
allocate(character(nrow) :: output)
206245

207246
! Clear the terminal screen
208247
call system("clear")
209248

210249
do row=1, nrow
211250
output = ""
212251
do col=1, ncol
213-
if (current_board(row,col) == 1) then
252+
if (board(row,col) == 1) then
214253
output = trim(output)//"#"
215254
else
216255
output = trim(output)//"."

0 commit comments

Comments
 (0)