You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将双人版Connect 4游戏改为玩家vs电脑模式?

实现Connect 4玩家vs电脑模式的解决方案

看起来你已经把玩家vs玩家的逻辑跑通了,卡在电脑自动落子的触发上——核心问题是你生成了随机数,但没在回合判断里跳过玩家输入的环节,直接让电脑执行选择。下面给你一步步修改的方案:

1. 给Board类添加游戏模式区分

首先在初始化方法里加一个模式参数,用来标记当前是玩家vs玩家(PVP)还是玩家vs电脑(PVE):

class Board
  attr_accessor :board
  attr_reader :turn, :identifier, :game_mode

  def initialize(game_mode = :pvp)
    @board = Array.new(6) { Array.new(7, nil) } # 标准Connect4是6行7列,你可以根据自己的棋盘调整
    @turn = 1
    @identifier = { 1: 'X', 2: 'O' }
    @game_mode = game_mode # 新增模式属性,:pvp或:pve
  end

2. 新增辅助方法:获取可用列

电脑不能选已经满了的列,所以先写个方法找出当前还能落子的列:

def available_columns
  # 检查每一列是否还有空位(第一行对应位置为空,说明列还没满)
  @board.first.each_index.select { |col| @board.first[col].nil? }
end

3. 修改回合处理逻辑,触发电脑自动落子

原来的回合方法应该是在等待玩家输入,现在要加判断:如果是PVE模式且轮到电脑(玩家2),就自动选可用列中的随机一个,跳过玩家输入:

def take_turn(col = nil)
  if @game_mode == :pve && @turn == 2
    # 电脑随机选一个可用列
    col = available_columns.sample
    puts "电脑选择了第#{col + 1}列" # 给玩家反馈选了哪一列
  else
    # 保留原来的玩家输入逻辑,只在玩家回合执行
    until col && available_columns.include?(col)
      puts "玩家#{@turn},请选择列(1-7):"
      col = gets.chomp.to_i - 1 # 转成数组索引(因为用户输入1-7,对应0-6)
    end
  end

  # 通用落子逻辑:找到当前列最底部的空位
  row = @board.rindex { |r| r[col].nil? }
  @board[row][col] = @identifier[@turn]

  # 切换回合
  @turn = @turn == 1 ? 2 : 1
end

4. 启动游戏时让用户选择模式

在游戏的入口代码里,加个模式选择的逻辑,让玩家选PVP还是PVE:

puts "请选择游戏模式:"
puts "1. 玩家vs玩家"
puts "2. 玩家vs电脑"
choice = gets.chomp.to_i
game_mode = choice == 2 ? :pve : :pvp

# 初始化棋盘并开始游戏循环
board = Board.new(game_mode)
until board.winner? || board.full? # 假设你已经有判断赢家和平局的方法
  board.render # 渲染棋盘的方法,你原来的代码里应该有实现
  board.take_turn
end

# 游戏结束后的提示
if board.winner?
  winner = board.game_mode == :pve && board.winner == 2 ? "电脑" : "玩家#{board.winner}"
  puts "#{winner}获胜!"
else
  puts "平局!"
end

小优化:进阶电脑AI(可选)

如果觉得随机选列太简单,你可以给电脑加基础的智能:

  • 优先选择能让自己直接赢的列
  • 其次选择能阻止玩家赢的列
  • 最后再随机选列

比如可以加这样的方法:

def best_column
  # 先检查电脑能不能一步赢
  available_columns.each do |col|
    temp_board = Marshal.load(Marshal.dump(@board)) # 复制棋盘模拟落子
    row = temp_board.rindex { |r| r[col].nil? }
    temp_board[row][col] = @identifier[2]
    return col if winner?(temp_board, 2)
  end

  # 再检查要不要阻止玩家赢
  available_columns.each do |col|
    temp_board = Marshal.load(Marshal.dump(@board))
    row = temp_board.rindex { |r| r[col].nil? }
    temp_board[row][col] = @identifier[1]
    return col if winner?(temp_board, 1)
  end

  # 都没有就随机选
  available_columns.sample
end

然后在take_turn里把available_columns.sample换成best_column就行。

内容的提问来源于stack exchange,提问作者Max Slatter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:30:15