Poll of the Day > Does anyone want to code review a tic tac toe game I wrote in Ruby?

Topic List
Page List: 1
IronBornCorps
03/10/21 12:42:54 PM
#1:


WIN_COMBINATIONS = [
[0,1,2],
[3,4,5],
[6,7,8],
[0,3,6],
[1,4,7],
[2,5,8],
[0,4,8],
[6,4,2]
]

def new_board()
return [" ", " ", " ", " ", " ", " ", " ", " ", " "]
end

def display_board(board)
system('clear')
puts " #{board[0]} | #{board[1]} | #{board[2]} "
puts "-----------"
puts " #{board[3]} | #{board[4]} | #{board[5]} "
puts "-----------"
puts " #{board[6]} | #{board[7]} | #{board[8]} "
end

def input_to_index(user_input)
user_input.to_i - 1
end

def move(board, index, current_player)
board[index] = current_player
end

def position_taken?(board, location)
board[location] != " " && board[location] != ""
end

def valid_move?(board, index)
index.between?(0,8) && !position_taken?(board, index)
end

def turn(board)
display_board(board)
puts "Please enter 1-9 (press Q to quit at anytime)"
input = gets.strip.upcase
if input == "Q"
quit
end
index = input_to_index(input)
if valid_move?(board, index)
move(board, index, current_player(board))
display_board(board)
if over?(board)
won?(board) ? (puts "Congratulations #{winner(board)}!") : (puts "Cat's Game!")
else
turn(board)
end
else
turn(board)
end
end

def current_player(board)
return turn_count(board) % 2 == 0 ? "X" : "O"
end

def turn_count(board)
return board.map{|space| space != " "}.count(true)
end

def play(board)
while turn_count(board) < 10 && !over?(board)
turn(board)
end
if over?(board)
puts "Play again? Y/N"
input = gets.strip.upcase
input == "Y" ? play(new_board) : quit
end
end

def won?(board)
result = false
WIN_COMBINATIONS.each { |win_combination|

win_indexs = [
win_combination[0],
win_combination[1],
win_combination[2]
]
board_positions = [
board[win_indexs[0]],
board[win_indexs[1]],
board[win_indexs[2]]
]
#use of the full? function takes in a partial board a verifies no spaces are empty
if (board_positions[0] == board_positions[1] && board_positions[1] == board_positions[2]) && full?(board_positions)
result = win_combination
end
}
return result
end

def full?(board)
return !board.any? {|position| position == " " || position.nil?}
end

def draw?(board)
return full?(board) && !won?(board)
end

def over?(board)
return full?(board) || won?(board) || draw?(board)
end

def winner(board)
win_condition = won?(board)
if win_condition != false
return board[win_condition[0]]
else
return nil
end
end

def quit()
puts "Thank you for playing!"
exit
end
... Copied to Clipboard!
IronBornCorps
03/10/21 12:43:45 PM
#2:


ope, should have know gfaqs, does not like indentation.

Ruby is interesting, I like my brackets though.

The game runs in CLI, and the bin calls the play function.
... Copied to Clipboard!
Clench281
03/10/21 12:45:04 PM
#3:


Can't you use the code block formatting

---
Take me for what I am -- who I was meant to be.
And if you give a damn, take me baby, or leave me.
... Copied to Clipboard!
IronBornCorps
03/10/21 12:50:09 PM
#4:


still doesn't like indentation.
... Copied to Clipboard!
IronBornCorps
03/10/21 1:11:49 PM
#5:


... Copied to Clipboard!
CoorsLight
03/10/21 1:19:44 PM
#6:


I don't know ruby and it's too hard to read on a phone right now but good luck! Hopefully you don't get some smug comment about not knowing some obscure minor optimization, that seems to be every code review I've seen on gfaqs
... Copied to Clipboard!
Mead
03/10/21 1:21:33 PM
#7:


I had a tic tac toe game back when it was new but it got stolen by some ruby guy on the bus who said he just wanted to look at it cause he had never seen one before

---
YOU control the numbers of leches. -Sal Vulcano
... Copied to Clipboard!
IronBornCorps
03/10/21 1:31:10 PM
#8:


CoorsLight posted...
I don't know ruby and it's too hard to read on a phone right now but good luck! Hopefully you don't get some smug comment about not knowing some obscure minor optimization, that seems to be every code review I've seen on gfaqs

thanks! I tried to use all the built in functions I could.
... Copied to Clipboard!
IronBornCorps
03/10/21 6:36:36 PM
#9:


just one bump for the later crowd uwu
... Copied to Clipboard!
CoorsLight
03/10/21 7:48:50 PM
#10:


Just at a high level, first thing that jumped out to me is how many functions explicitly take in a board. I would probably have that board be something higher level so you don't have to pass it in over and over, I don't think that gives you any advantages since you won't have multiple different possible boards in a game. Not sure the best way that would look since I'm not a Ruby guy but I'm thinking maybe the board and the game logic could be separate classes.

There are a few functions I find overly granular, like input_to_index. I don't know exactly what to_i is but that function looks to basically just do subtraction, I don't think it's justified to have functions doing a single basic arithmetic step. Some of the other one-liners are kinda borderline too, that's just one example. position_taken is only called within one other function, why not have its implementation coded directly into the function that calls it? I'm also not sure how you could get to an empty string state there, looks like it initializes the board as a space.

Great now I feel like I'm being the nitpicky person here
... Copied to Clipboard!
Lokarin
03/10/21 8:52:02 PM
#11:


... Copied to Clipboard!
PunishedOni
03/10/21 10:44:23 PM
#12:


its amazing that gamefaqs has a "code" tag that ignores whitespace

anyway

return [" ", " ", " ", " ", " ", " ", " ", " ", " "]

this should be Array.new(9, " ") so that you don't have to count it to make sure it's the right length

WIN_COMBINATIONS = [
...snip...
]

while this works fine for tic tac toe, trying to think algorithmically about how you would check for a win rather than just looking it up in a list will help you write more complicated programs. what about something like this (im using pseudocode since my ruby is bad. it probably has bugs too, and it's not the most elegant way to do it -- just wanted to give an idea of what I meant)

http://codepad.org/oU4PCmdD

I wouldn't worry too much about things like function length or whatever -- lots of people have different opinions on it, and if you end up working on bigger projects with other people the important thing will just be collaborating with your teammates to have a style that everyone's okay with. as long as you don't get in the habit of making heinously long functions it's not really an issue


---
my boyfriend has the highest single-season WAR/g/nmol in low-T baseball history
... Copied to Clipboard!
IronBornCorps
03/10/21 10:46:46 PM
#13:


Thanks for the feedback, this is good stuff!
... Copied to Clipboard!
PunishedOni
03/10/21 10:58:55 PM
#14:


also on the note of checking the victory state with an algorithm - you might think about how using a different data structure could make that easier. right now a cell's index is its row index plus 3 times its column index (e.g. the cell in row 1 and column 0 is at 3), which makes the math for checking it a lot more complicated.

using a different data structure (maybe an array of arrays?) could make that easier. You could also do something like this if you've read/ want to start learning about hash maps and structs

http://codepad.org/4LTSlc5X

(idk if there's a cleaner way to do a hashmap where the keys are coordinates in ruby since I don't write ruby that often, btw. so if there's something less ugly you know of then use that lol)

---
my boyfriend has the highest single-season WAR/g/nmol in low-T baseball history
... Copied to Clipboard!
CarefreeDude
03/10/21 11:04:52 PM
#15:


I came here to comment but @PunishedOni has it covered

---
Switch Code: SW-5421-8761-9807 IGN: Chris
Pokemon Home Friend Code: XSNF-XRED-EWDK 3DS:5112-3770-6561
... Copied to Clipboard!
Topic List
Page List: 1