Hướng dẫn tic-tac-toe oop python - tic-tac-toe oop con trăn

Dự án Tic-tac-toe được viết bằng Python. Tệp dự án chứa tập lệnh python [main.py]. Chương trình này thực hiện trò chơi cho hai người chơi. Tất cả các quy tắc chơi đều giống như chúng ta chơi trong thời gian thực tic-tac-toe. Đây là một trò chơi hai người chơi đơn giản.

Về dự án

Trò chơi này chỉ đơn giản là trong dòng lệnh. Đầu tiên, người chơi phải chọn giữa ‘o’ hoặc ‘x’ để bắt đầu trò chơi. Bạn phải gõ từ 1 đến 9 để đặt giá trị vào ô trò chơi. Thiết kế lối chơi rất đơn giản nên người dùng sẽ không cảm thấy khó khăn khi sử dụng và hiểu.

Làm thế nào để chạy dự án?

Để chạy dự án này, bạn phải cài đặt  Python  trên PC của mình. Sau khi tải xuống dự án, hãy làm theo các bước dưới đây:

Bước 1:  Giải nén / Giải nén tệp  Giải nén / Giải nén tệp

Bước 2: Vào  bên trong thư mục dự án, mở cmd sau đó gõ main.py và enter để khởi động hệ thống.  bên trong thư mục dự án, mở cmd sau đó gõ main.py và enter để khởi động hệ thống.

HOẶC LÀ

Bước 2:  Chỉ cần nhấp đúp vào tệp main.py và bạn đã sẵn sàng.  Chỉ cần nhấp đúp vào tệp main.py và bạn đã sẵn sàng.

Đây là một hệ thống dựa trên cmd đơn giản, được viết đặc biệt cho người mới bắt đầu. Dự án này bằng Python với mã nguồn được tải xuống miễn phí. Chỉ sử dụng cho mục đích giáo dục! Chỉ sử dụng cho mục đích giáo dục!

Bản thương mại nhiều người tải nhất

Hãy lựa chọn cho minh project phù hợp nhất, ngoài sản phẩm free , dự án trả phí bạn mua nó về sử dụng khám phá nhiều cái mới lạ


Dự án trò chơi này được viết bằng Python. Tệp dự án chứa tập lệnh python [TicTacToe.py]. Đây là một trò chơi hội đồng chiến lược dựa trên GUI đơn giản, rất dễ hiểu và dễ sử dụng. Tất cả các quy tắc chơi đều giống như chúng ta chơi trong thời gian thực tic-tac-toe. Đây là một trò chơi nhiều người chơi đơn giản.

Về dự án

Trò chơi Tic Tac Toe bắt đầu với một bảng GUI. Đầu tiên, người chơi phải nhấp vào ô bất kỳ để bắt đầu trò chơi. Nó chứa thuật toán Minimax; là quy tắc quyết định được sử dụng cho trò chơi hai người chơi. Giao diện đồ họa 2D đơn giản được cung cấp để dễ dàng chơi game. Thiết kế lối chơi rất đơn giản nên người dùng sẽ không cảm thấy khó khăn khi sử dụng và hiểu.

Làm thế nào để chạy dự án?

Để chạy dự án này, bạn phải cài đặt  Python  trên PC của mình. Sau khi tải xuống dự án, hãy làm theo các bước dưới đây:

Bước 1:  Giải nén / Giải nén tệp  Giải nén / Giải nén tệp

Bước 2: Vào  bên trong thư mục dự án, mở cmd sau đó gõ TicTacToe.py và enter để khởi động hệ thống.  bên trong thư mục dự án, mở cmd sau đó gõ TicTacToe.py và enter để khởi động hệ thống.

HOẶC LÀ

Bước 2:  Chỉ cần nhấp đúp vào tệp TicTacToe.py và bạn đã sẵn sàng.  Chỉ cần nhấp đúp vào tệp TicTacToe.py và bạn đã sẵn sàng.

Đây là một hệ thống dựa trên GUI đơn giản, được viết đặc biệt cho người mới bắt đầu. Tic Tac Toe trong dự án Python với mã nguồn được tải xuống miễn phí


Chuyện là khi mình nghịch Ruby contest ở trang codingame, mình tìm thấy 1 bài toán khá thú vị, đó là tạo game TicTacToe [cờ caro 3x3] bằng code Ruby.

Link bài học : //www.codingame.com/playgrounds/46635/tic-tac-toe-game-implementation

Ở trong link bên trên đã có sẵn phần description và sourecode của bài toán này. Phần sourecode khá ngắn, chỉ có 116 dòng . Và bạn có thể test sourecode khá đơn giản với trình thông dịch Ruby[irb] trong

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
7 của bạn [điều kiện là máy tính của bạn đã cài Ruby] .

Game cờ caro 3x3[

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
8 ] mà bạn có thể tưởng tượng ra là như thế này:
] . [part 2]

Okay, giờ thì bắt đầu thoai.

1. Game TicTacToe chơi như thế nào?

Để chơi game, đầu tiên chúng ta cần một bảng 3x3 ô trống như thế này, tạm gọi là

 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
3 .

irb[main]:118:0> TicTacToe.new.display_board
   |   |   
-----------
   |   |   
-----------
   |   |   

Sẽ chỉ có 2 players, mỗi player tương ứng với 1

 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
4 để điền vào
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
3 là
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
6 hoặc
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
7 . Ở đây ta quy ước như sau:

  • Player 1 tương ứng với
     X | O | X   
    -----------
     O | X | O   
    -----------
     O | X | O  
    => Cat's game
    
    6
  • Player 2 tương ứng với
     X | O | X   
    -----------
     O | X | O   
    -----------
     O | X | O  
    => Cat's game
    
    7 2 players sẽ chơi theo lượt ,
    class TicTacToe
      attr_reader :board
      WIN_COMBINATIONS = [
        [0,1,2],
        [3,4,5],
        [6,7,8],
        [0,3,6],
        [1,4,7],
        [2,5,8],
        [0,4,8],
        [2,4,6]
      ]
    
      def initialize[board = nil, options = {}]
        @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
        @options = @options.merge[options]
        @board = board || Array.new[self.cells_count, @options[:chr_empty]]
      end
    
      def cells_count
        @options[:rows]*@options[:cols]
      end
    
      def get_cell_from_row_col[row, col]
        # puts "row: #{row}, col: #{col}, cell: #{[[row-1]*@options[:cols]]+col-1}"
        @board[[[row-1]*@options[:cols]]+col-1]
      end
    
      def display_board
        @options[:rows].times.with_index[1] do |r, row_index|
          str_row = ''
          @options[:cols].times.with_index[1] do |c, col_index|
            str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
            str_row += @options[:chr_separ_v] if col_index  Cat's game
    
    3
  • Lượt 2 :
    class TicTacToe
      attr_reader :board
      WIN_COMBINATIONS = [
        [0,1,2],
        [3,4,5],
        [6,7,8],
        [0,3,6],
        [1,4,7],
        [2,5,8],
        [0,4,8],
        [2,4,6]
      ]
    
      def initialize[board = nil, options = {}]
        @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
        @options = @options.merge[options]
        @board = board || Array.new[self.cells_count, @options[:chr_empty]]
      end
    
      def cells_count
        @options[:rows]*@options[:cols]
      end
    
      def get_cell_from_row_col[row, col]
        # puts "row: #{row}, col: #{col}, cell: #{[[row-1]*@options[:cols]]+col-1}"
        @board[[[row-1]*@options[:cols]]+col-1]
      end
    
      def display_board
        @options[:rows].times.with_index[1] do |r, row_index|
          str_row = ''
          @options[:cols].times.with_index[1] do |c, col_index|
            str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
            str_row += @options[:chr_separ_v] if col_index  Cat's game
    
    3còn trống trong
     X | O | X   
    -----------
     O | X | O   
    -----------
     O | X | O  
    => Cat's game
    
    3
  • Lượt 3 :
    class TicTacToe
      attr_reader :board
      WIN_COMBINATIONS = [
        [0,1,2],
        [3,4,5],
        [6,7,8],
        [0,3,6],
        [1,4,7],
        [2,5,8],
        [0,4,8],
        [2,4,6]
      ]
    
      def initialize[board = nil, options = {}]
        @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
        @options = @options.merge[options]
        @board = board || Array.new[self.cells_count, @options[:chr_empty]]
      end
    
      def cells_count
        @options[:rows]*@options[:cols]
      end
    
      def get_cell_from_row_col[row, col]
        # puts "row: #{row}, col: #{col}, cell: #{[[row-1]*@options[:cols]]+col-1}"
        @board[[[row-1]*@options[:cols]]+col-1]
      end
    
      def display_board
        @options[:rows].times.with_index[1] do |r, row_index|
          str_row = ''
          @options[:cols].times.with_index[1] do |c, col_index|
            str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
            str_row += @options[:chr_separ_v] if col_index  Cat's game
    
    3 .......còn trống trong
     X | O | X   
    -----------
     O | X | O   
    -----------
     O | X | O  
    => Cat's game
    
    3 .......
  • Lượt 9 :
    class TicTacToe
      attr_reader :board
      WIN_COMBINATIONS = [
        [0,1,2],
        [3,4,5],
        [6,7,8],
        [0,3,6],
        [1,4,7],
        [2,5,8],
        [0,4,8],
        [2,4,6]
      ]
    
      def initialize[board = nil, options = {}]
        @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
        @options = @options.merge[options]
        @board = board || Array.new[self.cells_count, @options[:chr_empty]]
      end
    
      def cells_count
        @options[:rows]*@options[:cols]
      end
    
      def get_cell_from_row_col[row, col]
        # puts "row: #{row}, col: #{col}, cell: #{[[row-1]*@options[:cols]]+col-1}"
        @board[[[row-1]*@options[:cols]]+col-1]
      end
    
      def display_board
        @options[:rows].times.with_index[1] do |r, row_index|
          str_row = ''
          @options[:cols].times.with_index[1] do |c, col_index|
            str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
            str_row += @options[:chr_separ_v] if col_index  Cat's game
    
    3còn trống trong
     X | O | X   
    -----------
     O | X | O   
    -----------
     O | X | O  
    => Cat's game
    
    3

Khi 9 ô trong

 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
3 được điền đầy
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
4 thì game kết thúc ở 1 trong 3 trạng thái :

  • Player 1 thắng.
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
  • Player 2 thắng
 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
  • Hòa.
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game

2. Giải thích sourecode của trang codingame.

Dưới đây là 116 dòng sourecode của class TicTacToe trên trang

  def initialize
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @board = Array.new[self.cells_count, @options[:chr_empty]]
  end
  
  def cells_count
    @options[:rows]*@options[:cols]
  end
2 nói trên:

class TicTacToe
  attr_reader :board
  WIN_COMBINATIONS = [
    [0,1,2],
    [3,4,5],
    [6,7,8],
    [0,3,6],
    [1,4,7],
    [2,5,8],
    [0,4,8],
    [2,4,6]
  ]

  def initialize[board = nil, options = {}]
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @options = @options.merge[options]
    @board = board || Array.new[self.cells_count, @options[:chr_empty]]
  end

  def cells_count
    @options[:rows]*@options[:cols]
  end

  def get_cell_from_row_col[row, col]
    # puts "row: #{row}, col: #{col}, cell: #{[[row-1]*@options[:cols]]+col-1}"
    @board[[[row-1]*@options[:cols]]+col-1]
  end

  def display_board
    @options[:rows].times.with_index[1] do |r, row_index|
      str_row = ''
      @options[:cols].times.with_index[1] do |c, col_index|
        str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
        str_row += @options[:chr_separ_v] if col_index  Cat's game
1 bằng
  def initialize
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @board = Array.new[self.cells_count, @options[:chr_empty]]
  end
  
  def cells_count
    @options[:rows]*@options[:cols]
  end
6 [
  def initialize
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @board = Array.new[self.cells_count, @options[:chr_empty]]
  end
  
  def cells_count
    @options[:rows]*@options[:cols]
  end
7 của nó là
  def initialize
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @board = Array.new[self.cells_count, @options[:chr_empty]]
  end
  
  def cells_count
    @options[:rows]*@options[:cols]
  end
8 ]

  def initialize
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @board = Array.new[self.cells_count, @options[:chr_empty]]
  end
  
  def cells_count
    @options[:rows]*@options[:cols]
  end
irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>

Ta lưu màn chơi mới này bằng biến

  def initialize
    @options = {rows: 3, cols: 3, chr_empty: ' ', chr_separ_v: '|', chr_separ_h: '-', players: {'Player 1': 'X', 'Player 2': 'O'}}
    @board = Array.new[self.cells_count, @options[:chr_empty]]
  end
  
  def cells_count
    @options[:rows]*@options[:cols]
  end
9 với 2 giá trị quan trọng là được lưu vào các instance variable:
irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
0 và
irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
1 . Mình sẽ giải thích về 2 giá trị này.

irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
0 là một
irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
3 lưu các giá trị liên quan đến settings của trò chơi.

  • irb[main]:119:0> game = TicTacToe.new
    => #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
    
    4 và
    irb[main]:119:0> game = TicTacToe.new
    => #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
    
    5 lưu số hàng và số cột của
     X | O | X   
    -----------
     O | X | O   
    -----------
     O | X | O  
    => Cat's game
    
    3 . [ở đây mặc định là 3x3] .
  • irb[main]:119:0> game = TicTacToe.new
    => #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
    
    7,
    irb[main]:119:0> game = TicTacToe.new
    => #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
    
    8,
    irb[main]:119:0> game = TicTacToe.new
    => #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
    
    9 lưu các ký tự để vẽ lên board trong terminal như sau:
   |   |   
-----------
   |   |   
-----------
   |   |   
  •    |   |   
    -----------
       |   |   
    -----------
       |   |   
    
    0 =
       |   |   
    -----------
       |   |   
    -----------
       |   |   
    
    1 là 1 hash lưu lại token của Player 1 và Player 2, phục vụ cho mục đích truy xuất xem cuối cùng ai là người thắng cuộc.

Về giá trị

irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
1, nó là một mảng lưu lại tất cả giá trị 'X', 'O' đã được điền trong suốt màn chơi. Cụ thể, các giá trị của
irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
1 thể hiện trên màn hình như sau:

 @board[0] | @board[1] | @board[2]  
----------------------------------
 @board[3] | @board[4] | @board[5]  
----------------------------------
 @board[6] | @board[7] | @board[8]  

Như vậy, quá trình chơi game tương ứng với quá trị gán giá trị cho các phần từ từ

   |   |   
-----------
   |   |   
-----------
   |   |   
4 . Khi khởi tạo một đối tượng, mặc định 1 board sẽ được tạo ra

2.2 Hiển thị board

Như vậy là ta đã tạo xong một màn chơi mới, giờ ta sẽ thử hiển thị board của màn chơi mới bằng

   |   |   
-----------
   |   |   
-----------
   |   |   
5 :

  def get_cell_from_row_col[row, col]
    @board[[[row-1]*@options[:cols]]+col-1]
  end

  def display_board
    @options[:rows].times.with_index[1] do |r, row_index|
      str_row = ''
      @options[:cols].times.with_index[1] do |c, col_index|
        str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
        str_row += @options[:chr_separ_v] if col_index  Cat's game
3 trên màn hình giống như việc in ra ma trận từ một mảng 2 chiều. Tuy nhiên ở đây, mình lưu
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
3 dưới dạng mảng 1 chiều
irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
1, nên mình cần có thêm 1 method sau:

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
1

 @board[0] | @board[1] | @board[2]  
----------------------------------
 @board[3] | @board[4] | @board[5]  
----------------------------------
 @board[6] | @board[7] | @board[8]  
0 sẽ trả về giá trị 'X' hoặc 'O' tương ứng trong
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
3 , khi biết chỉ số hàng và cột. Cụ thể:

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
2
 @board[0] | @board[1] | @board[2]  
----------------------------------
 @board[3] | @board[4] | @board[5]  
----------------------------------
 @board[6] | @board[7] | @board[8]  

Ví dụ,

  • với row = 1, col = 1 ,
     @board[0] | @board[1] | @board[2]  
    ----------------------------------
     @board[3] | @board[4] | @board[5]  
    ----------------------------------
     @board[6] | @board[7] | @board[8]  
    
    0 trả về giá trị
     @board[0] | @board[1] | @board[2]  
    ----------------------------------
     @board[3] | @board[4] | @board[5]  
    ----------------------------------
     @board[6] | @board[7] | @board[8]  
    
    3
  • với row = 2, col = 3 ,
     @board[0] | @board[1] | @board[2]  
    ----------------------------------
     @board[3] | @board[4] | @board[5]  
    ----------------------------------
     @board[6] | @board[7] | @board[8]  
    
    0 trả về giá trị
     @board[0] | @board[1] | @board[2]  
    ----------------------------------
     @board[3] | @board[4] | @board[5]  
    ----------------------------------
     @board[6] | @board[7] | @board[8]  
    
    5

Trở lại với

   |   |   
-----------
   |   |   
-----------
   |   |   
5, mình sẽ giải thích nó bằng comment trong code:

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
4

2.3 Chơi game thôi .

Sau khi khởi tạo màn chơi, chúng ta sẽ bắt đầu chơi bằng

 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
0
 @board[0] | @board[1] | @board[2]  
----------------------------------
 @board[3] | @board[4] | @board[5]  
----------------------------------
 @board[6] | @board[7] | @board[8]  
8 : Về method play: Về method play:

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
5

Để hiểu

 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
0
 @board[0] | @board[1] | @board[2]  
----------------------------------
 @board[3] | @board[4] | @board[5]  
----------------------------------
 @board[6] | @board[7] | @board[8]  
8, chúng ta phải hiểu được các
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
0
  def get_cell_from_row_col[row, col]
    @board[[[row-1]*@options[:cols]]+col-1]
  end

  def display_board
    @options[:rows].times.with_index[1] do |r, row_index|
      str_row = ''
      @options[:cols].times.with_index[1] do |c, col_index|
        str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
        str_row += @options[:chr_separ_v] if col_index  Cat's game
4
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
6 được điền vào
 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
3 ở tổ hợp các vị trí sau:

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
8

Điều tương tự xảy ra với người chơi

 X | O | X   
-----------
 O | X | O   
-----------
 O | X | O  
=> Cat's game
7 .

Xét các tổ hợp vị trí nói trên, ta suy ra được 8 trường hợp tương ứng với việc một trong 2 người chơi dành chiến thắng:8 trường hợp tương ứng với việc một trong 2 người chơi dành chiến thắng:

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
9

8 trường hợp dành chiến thắng này được lưu bởi hằng số

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 . Sau khi hiểu được hằng số này, việc hiểu
  def get_cell_from_row_col[row, col]
    @board[[[row-1]*@options[:cols]]+col-1]
  end

  def display_board
    @options[:rows].times.with_index[1] do |r, row_index|
      str_row = ''
      @options[:cols].times.with_index[1] do |c, col_index|
        str_row += @options[:chr_empty]+get_cell_from_row_col[row_index, col_index]+@options[:chr_empty]
        str_row += @options[:chr_separ_v] if col_index  #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
1 đã đủ 9 phần tử có giá trị 'X' hoặc 'O' .

Trường hợp này được kiểm tra bằng

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
08 khá dễ hiểu:

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
1

2.3.2 Method turn

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
09 được dùng để nhập token ở mỗi lượt chơi của 2 player như sau:

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
2

Như vậy là mình đã giải thích xong cách mà các method trong

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
9 hoạt động. Giờ chúng ta cùng thử tìm cách sửa lại
 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
9 này 1 chút để tạo ra các game cờ caro 4x4 hoặc 5x5 .

3. Thử tạo ra game cờ caro nxn [n>3]

Để tạo ra game cờ caro nxn [n>3] khá đơn giản, chúng ta chỉ cần sửa lại

irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
0 và hằng số
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 một chút.

Mình sẽ thử với trường hợp 4x4 . Đầu tiên, với biến

irb[main]:119:0> game = TicTacToe.new
=> #3, :cols=>3, :chr_empty=>" ", :chr_separ_v=>"|", :chr_separ_h=>"-", :players=>{:"Player 1"=>"X", :"Player 2"=>"O"}}, @board=[" ", " ", " ", " ", " ", " ", " ", " ", " "]>
0 trong
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
15, chúng ta sẽ sửa số
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
16 và
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
17 thành 4.

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
3

Tiếp theo, chúng ta sửa

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 như sau:

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
4

Toàn bộ phần

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
9 còn lại của game 3x3 sẽ được giữ nguyên và ta có
 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
9 mới cho game cờ caro 4x4 như sau:

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
5

Mình sẽ thử chơi với

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
9 mới nhé:

Như vậy mấu chốt để tạo ra game cờ caro

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
22 là hằng số
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 . Chúng ta có thể nhận thấy 1 quy luật khá rõ ràng:

 X |   | X   
-----------
   | X |    
-----------
 O | O | O  
=> Congratulations O!
6

Với n < 8, các bạn hoàn toàn có thể dùng

 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
24 để thiết lập
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 . Tuy nhiên với n = 20 chẳng hạn, ngồi tìm ra 42 phần tử của
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 đúng là mắc mợt . Cách tốt nhất là chúng ta nên viết một method để sinh ra
 X | X | X   
-----------
 O |   |    
-----------
   | O | O   
 => Congratulations X!
05 với tham số là n. Tuy nhiên, bài viết đến đây là đủ dài rồi, mình sẽ chia sẻ thuật toán để viết method này vào part 2 của bài viết.

4. Tạm biệt

Chốt lại, ở các phần sau của bài viết, mình sẽ giải quyết các vấn đề sau:

  • Thuật toán tạo
     X | X | X   
    -----------
     O |   |    
    -----------
       | O | O   
     => Congratulations X!
    
    05 với tham số n cho trước.
  • Mông má thêm 1 chút HTML, CSS, JS + Rails để tạo một webgame TicTacToe

Còn bây giờ thì tạm biệt.

References:

//www.codingame.com/playgrounds/46635/tic-tac-toe-game-implementation

Chủ Đề