Created
September 15, 2019 21:47
-
-
Save amirrajan/896c4e60959b3ae27d7b7ab45a73e827 to your computer and use it in GitHub Desktop.
Tic Tac Toe Written in DragonRuby Game Toolkit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#This sample app is a classic game of Tic Tac Toe. | |
class TicTacToe | |
attr_accessor :_, :state, :outputs, :inputs, :grid, :gtk | |
#Starts the game with player x's turn and creates an array for space combinations. | |
#Calls methods necessary for the game to run properly. | |
def tick | |
state.current_turn ||= :x | |
state.space_combinations = [-1, 0, 1].product([-1, 0, 1]).to_a | |
render_board | |
input_board | |
end | |
#Uses borders to create grid squares for the game's board. Also outputs the game pieces using labels. | |
def render_board | |
square_size = 80 | |
board_left = grid.w_half - square_size * 1.5 | |
board_top = grid.h_half - square_size * 1.5 | |
outputs.borders << all_spaces do |x, y, space| | |
space.border ||= [ | |
board_left + x.add(1) * square_size, | |
board_top + y.add(1) * square_size, | |
square_size, | |
square_size | |
] | |
end | |
outputs.labels << filled_spaces do |x, y, space| | |
label board_left + x.add(1) * square_size + square_size.fdiv(2), | |
board_top + y.add(1) * square_size + square_size - 20, | |
space.piece | |
end | |
#Uses a label to output whether x or o won, or if a draw occurred. | |
#If the game is ongoing, a label shows whose turn it currently is. | |
outputs.labels << if state.x_won | |
label grid.w_half, grid.top - 80, "x won" | |
elsif state.o_won | |
label grid.w_half, grid.top - 80, "o won" | |
elsif state.draw | |
label grid.w_half, grid.top - 80, "a draw" | |
else | |
label grid.w_half, grid.top - 80, "turn: #{state.current_turn}" | |
end | |
end | |
#Calls the methods responsible for handling user input and determining the winner. | |
#Does nothing unless the mouse is clicked. | |
def input_board | |
return unless inputs.mouse.click | |
input_place_piece | |
input_restart_game | |
determine_winner | |
end | |
#Handles user input for placing pieces on the board. | |
def input_place_piece | |
return if state.game_over | |
#Checks to find the space that the mouse was clicked inside of, and makes sure the space does not already | |
#have a piece in it. | |
__, __, space = all_spaces.find do |__, __, space| | |
inputs.mouse.click.point.inside_rect?(space.border) && !space.piece | |
end | |
#The piece that goes into the space belongs to the player whose turn it currently is. | |
return unless space | |
space.piece = state.current_turn | |
state.current_turn = state.current_turn == :x ? :o : :x | |
end | |
#Resets the game. | |
def input_restart_game | |
return unless state.game_over | |
gtk.reset | |
end | |
#Checks if x or o won the game. | |
#If neither player wins and all nine squares are filled, a draw happens. | |
#Once a player is chosen as the winner or a draw happens, the game is over. | |
def determine_winner | |
state.x_won = won? :x | |
state.o_won = won? :o | |
state.draw = true if filled_spaces.length == 9 && !state.x_won && !state.o_won | |
state.game_over = state.x_won || state.o_won || state.draw | |
end | |
#Determines if a player won by checking if there is a horizontal match or vertical match. | |
#Horizontal_match and vertical_match have boolean values. If either is true, the game has been won. | |
def won? piece | |
won = [[-1, 0, 1]].product([-1, 0, 1]).map do |xs, y| | |
horizontal_match = state.spaces[xs[0]][y].piece == piece && | |
state.spaces[xs[1]][y].piece == piece && | |
state.spaces[xs[2]][y].piece == piece | |
vertical_match = state.spaces[y][xs[0]].piece == piece && | |
state.spaces[y][xs[1]].piece == piece && | |
state.spaces[y][xs[2]].piece == piece | |
horizontal_match || vertical_match | |
end | |
won << (state.spaces[-1][-1].piece == piece && | |
state.spaces[ 0][ 0].piece == piece && | |
state.spaces[ 1][ 1].piece == piece) | |
won << (state.spaces[ 1][-1].piece == piece && | |
state.spaces[ 0][ 0].piece == piece && | |
state.spaces[-1][ 1].piece == piece) | |
won.reject_false.any? | |
end | |
#Defines filled spaces on the board by rejecting all spaces that do not have game pieces in them. | |
def filled_spaces | |
state.space_combinations | |
.reject { |x, y| !state.spaces[x][y].piece } | |
.map do |x, y| | |
if block_given? | |
yield x, y, state.spaces[x][y] | |
else | |
[x, y, state.spaces[x][y]] | |
end | |
end | |
end | |
#Defines all spaces on the board. | |
def all_spaces | |
if !block_given? | |
state.space_combinations.map do |x, y| | |
[x, y, state.spaces[x][y]] | |
end | |
else | |
state.space_combinations.map do |x, y| | |
yield x, y, state.spaces[x][y] | |
end | |
end | |
end | |
#Sets values for a label, such as the position, value, size, alignment, and color. | |
def label x, y, value | |
[x, y + 10, value, 20, 1, 0, 0, 0] | |
end | |
end | |
$tic_tac_toe = TicTacToe.new | |
def tick args | |
$tic_tac_toe._ = args | |
$tic_tac_toe.state = args.state | |
$tic_tac_toe.outputs = args.outputs | |
$tic_tac_toe.inputs = args.inputs | |
$tic_tac_toe.grid = args.grid | |
$tic_tac_toe.gtk = args.gtk | |
$tic_tac_toe.tick | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment