fork download
  1. require "curses"
  2. include Curses
  3.  
  4. class Playfield < Window
  5.  
  6. def draw_vertical_line(x, y_start, y_finish)
  7. for y in y_start..y_finish
  8. setpos(y, x)
  9. addch '|'
  10. end
  11. end
  12.  
  13. def draw_horizontal_line(y, x_start, x_finish)
  14. for x in x_start..x_finish
  15. setpos(y, x)
  16. addch '_'
  17. setpos(y, x + 7)
  18. addch '_'
  19. setpos(y, x + 14)
  20. addch '_'
  21. end
  22. end
  23.  
  24. def move_cursor(ch, pos)
  25. case ch
  26. when "\167"
  27. pos[:y] -= 3 if pos[:y] > 1
  28. setpos(pos[:y], pos[:x])
  29. when "\163"
  30. pos[:y] += 3 if pos[:y] < 7
  31. setpos(pos[:y], pos[:x])
  32. when "\141"
  33. pos[:x] -= 7 if pos[:x] > 3
  34. setpos(pos[:y], pos[:x])
  35. when "\144"
  36. pos[:x] += 7 if pos[:x] < 17
  37. setpos(pos[:y], pos[:x])
  38. end
  39. end
  40.  
  41. def place_mark(mark, marks, pos)
  42. if inch == ' '.ord
  43. addch(mark)
  44. marks.each do |line|
  45. line.each do |element|
  46. element[:value] = mark if element[:y] == pos[:y] && element[:x] == pos[:x]
  47. end
  48. end
  49. setpos(pos[:y], pos[:x])
  50. return 'OK'
  51. else
  52. return nil
  53. end
  54. end
  55.  
  56. def check_marks(marks, mark)
  57. # horizontal
  58. marks.each do |line|
  59. return 'win' if line.count{|element| element[:value] == mark} == 3
  60. end
  61.  
  62. # vertical
  63. transposed_marks = marks.transpose
  64. transposed_marks.each do |column|
  65. return 'win' if column.count{|element| element[:value] == mark} == 3
  66. end
  67.  
  68. # diagonal
  69. return 'win' if marks[0][0][:value] == mark && marks[1][1][:value] == mark && marks[2][2][:value] == mark
  70. return 'win' if marks[2][0][:value] == mark && marks[1][1][:value] == mark && marks[0][2][:value] == mark
  71.  
  72. # draw?
  73. counter = 0
  74. marks.each do |line|
  75. line.each { |element| counter += 1 if element[:value] == ' ' }
  76. end
  77. return "draw" if counter == 0
  78.  
  79. return nil
  80. end
  81.  
  82. end
  83.  
  84.  
  85. init_screen
  86. crmode
  87. noecho
  88.  
  89. # controls
  90. message = "Press W, A, S, D to navigate the cursor, press Space to place your mark."
  91. c = Window.new(1, message.length, lines/2 + 11, 0)
  92. c.addstr(message)
  93. c.refresh
  94.  
  95. # hints
  96. h = Window.new(3, 38, lines/2 + 6, cols/2 - 18)
  97. h.addstr "player 1's turn".ljust(38)
  98. h.refresh
  99.  
  100.  
  101. # playfield
  102. p = Playfield.new(9, 20, lines/2 - 5, cols/2 - 9)
  103.  
  104. # draw grid
  105. p.draw_vertical_line(6, 0, 8)
  106. p.draw_vertical_line(13, 0, 8)
  107. p.draw_horizontal_line(2, 0, 5)
  108. p.draw_horizontal_line(5, 0, 5)
  109.  
  110. # kostyl
  111. cursor_pos = { y: 4, x: 10 }
  112. p.setpos(cursor_pos[:y], cursor_pos[:x])
  113.  
  114. # array of marks with coordinates
  115. y = [1, 4, 7]
  116. x = [3, 10, 17]
  117. marks = Array.new(3) { Array.new(3) }
  118. marks.each_index do |line|
  119. marks[line].each_index do |column|
  120. marks[line][column] = { y: y[line], x: x[column], value: ' ' }
  121. end
  122. end
  123.  
  124. # game part
  125. mark = []
  126. if rand(1..2) == 1
  127. mark[1] = 'X'
  128. mark[2] = 'O'
  129. else
  130. mark[1] = 'O'
  131. mark[2] = 'X'
  132. end
  133.  
  134. turn = 1 # 1st player's turn
  135. begin
  136. begin
  137. ch = p.getch
  138. p.move_cursor(ch, cursor_pos)
  139. end until ch == ?\s
  140. if p.place_mark(mark[turn], marks, cursor_pos)
  141. result = p.check_marks(marks, mark[turn])
  142. unless result
  143. h.setpos(0, 0)
  144. if turn == 1
  145. turn = 2
  146. h.addstr "player #{turn}'s turn".rjust(38)
  147. else
  148. turn = 1
  149. h.addstr "player #{turn}'s turn".ljust(38)
  150. end
  151. h.refresh
  152. end
  153. end
  154. end until result
  155.  
  156. h.setpos(0, 0)
  157. if result == "draw"
  158. h.addstr "DRAW!".center(38)
  159. else
  160. h.addstr "PLAYER #{turn} WINS!".center(38)
  161. end
  162. h.setpos(2, 0)
  163. h.addstr "Press any key to exit.".center(38)
  164. h.refresh
  165.  
  166. p.getch
  167. p.close
  168.  
  169. close_screen
  170.  
Runtime error #stdin #stdout #stderr 0.02s 8616KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Error opening terminal: unknown.