【AI学习手记】井字棋AI的Ruby实现与橙光实现


1.Ruby实现

无聊做了个Ruby的井字棋游戏,能人机对战,也能CPU对弈(欸?双人对战呢?),甚至可以对弈超多局!

关于AI部分:

1、AI大概率(90%)在先行时落子中间(此外随机走棋)

2、AI预判一步,如果下一步该AI能赢,该AI会下能赢的一步棋;如果下一步AI的对方会赢,AI会下对方赢的一步棋

3、在AI预判没有结果时,AI随机走棋

#encoding=UTF8
#coding in Ruby
#Programmer: APPIX

#打印棋盘
def parr(q)
  puts "当前的棋盘"
  for i in 0..2
    for j in 0..2
      case q[i][j]
      when 0 then printf ". "
      when 1 then printf "O "
      when 2 then printf "X "
      end
    end
    printf "\n"
  end
end

#输入落子
def inputp(q)
  err=0
  while err==0
    puts "请输入你落子的位置"
    puts "1 2 3\n4 5 6\n7 8 9\n"
    puts "================="
    print "位置:"
    getnum=gets.to_i-1
    puts "================="
    i=(getnum/3).to_i
    j=(getnum%3).to_i
    if getnum>8||getnum<0
      puts "非法数值,请重新输入"
      parr q
    elsif q[i][j]==0 
      q[i][j]=1
      err=1
    else 
      puts"这个位置已经有子了,请换个位置"
      parr q
    end
  end
  return q
end

#CPU2落子
def aip(q)
  err=0
  kong=0

  #CPU预判系统
  #CPU先行,大概率落子中间
  for i in 0..2
    for j in 0..2
      if q[i][j]==0
        kong+=1
      end
    end
  end
  if kong==9
    if rand(0..100).to_i<90
      q[1][1]=2
      err=1
    end
  end

  #需要预判的情况1:该CPU还差一步就赢了
  if err==0
    for i in 0..2
      for j in 0..2
        if q[i][j]==0
          q[i][j]=2
          w=winp q
          if w==2 
            err=1
            break
          else
            q[i][j]=0
          end
        end
      end
      if err==1 
        break
      end
    end
  end

  #需要预判的情况2:该CPU的对手还差一步就赢了
  if err==0
    for i in 0..2
      for j in 0..2
        if q[i][j]==0
          q[i][j]=1
          w=winp q
          if w==1 
            q[i][j]=2
            err=1
            break
          else
            q[i][j]=0
          end
        end
      end
      if err==1 
        break
      end
    end
  end

  #不存在预判结果,CPU随机行动
  while err==0
    getnum=rand(0..8).to_i
    i=(getnum/3).to_i
    j=(getnum%3).to_i
    if q[i][j]==0 
      q[i][j]=2
      err=1
    else 
    end
  end
  return q
end

#CPU1落子
def aipme (q)
  err=0
  kong=0

  #CPU预判系统
  #CPU先行,大概率落子中间
  for i in 0..2
    for j in 0..2
      if q[i][j]==0
        kong+=1
      end
    end
  end
  if kong==9
    if rand(0..100).to_i<90
      q[1][1]=1
      err=1
    end
  end

  #需要预判的情况1:该CPu还差一步就赢了
  if err==0
    for i in 0..2
      for j in 0..2
        if q[i][j]==0
          q[i][j]=1
          w=winp q
          if w==1 
            err=1
            break
          else
            q[i][j]=0
          end
        end
      end
      if err==1 
        break
      end
    end
  end

  #需要预判的情况2:该CPU的对手还差一步就赢了
  if err==0
    for i in 0..2
      for j in 0..2
        if q[i][j]==0
          q[i][j]=2
          w=winp q
          if w==2 
            q[i][j]=1
            err=1
            break
          else
            q[i][j]=0
          end
        end
      end
      if err==1 
        break
      end
    end
  end

  #不存在预判结果,CPU随机行动
  while err==0
    getnum=rand(0..8).to_i
    i=(getnum/3).to_i
    j=(getnum%3).to_i
    if q[i][j]==0 
      q[i][j]=1
      err=1
    else 
    end
  end
  return q
end

#判断胜负
def winp(q)
  if q[0][0]==q[0][1]&&q[0][1]==q[0][2]&&q[0][0]!=0
    out=q[0][0]
  elsif q[1][0]==q[1][1]&&q[1][1]==q[1][2]&&q[1][0]!=0
    out=q[1][0]
  elsif q[2][0]==q[2][1]&&q[2][1]==q[2][2]&&q[2][0]!=0
    out=q[2][0]
  elsif q[0][0]==q[1][0]&&q[0][0]==q[2][0]&&q[0][0]!=0
    out=q[0][0]
  elsif q[0][1]==q[1][1]&&q[0][1]==q[2][1]&&q[0][1]!=0
    out=q[0][1]
  elsif q[0][2]==q[1][2]&&q[0][2]==q[2][2]&&q[0][2]!=0
    out=q[0][2]
  elsif q[0][0]==q[1][1]&&q[1][1]==q[2][2]&&q[0][0]!=0
    out=q[0][0]
  elsif q[2][0]==q[1][1]&&q[1][1]==q[0][2]&&q[2][0]!=0
    out=q[2][0]
  else 
    kong=0
    for i in 0..2
      for j in 0..2
        if q[i][j]==0
          kong+=1
        end
      end
    end
    if kong==0
      out=3
    else 
      out=0
    end
  end
  return out
end

#进行游戏
def play
  arr=[[0,0,0],[0,0,0],[0,0,0]]
  win=0
  parr arr
  if rand(0..100).to_i<50
    puts "================="
    puts "我方先行"
    puts "================="
    while win==0
      arr=inputp(arr)
      win=winp(arr)
      if win==0
        arr=aip(arr)
        win=winp(arr)
      end
      parr arr
    end
  else
    puts "================="
    puts "CPU先行"
    puts "================="
    while win==0
      arr=aip(arr)
      win=winp(arr)
      parr arr
      if win==0
        arr=inputp(arr)
        win=winp(arr)
        if win==1
          parr arr
        end
      end
    end
  end
  puts "================="
  case win 
  when 1 then puts "游戏结束,我方胜利"
  when 2 then puts "游戏结束,CPU胜利"
  when 3 then puts "游戏结束,双方平局"
  end
  "================="
end

#CPU对战模式
def playcpu
  arr=[[0,0,0],[0,0,0],[0,0,0]]
  win=0
  parr arr
  if rand(0..100).to_i<50
    puts "================="
    puts "CPU1先行"
    puts "================="
    while win==0
      arr=aipme(arr)
      win=winp(arr)
      parr arr
      if win==0
        arr=aip(arr)
        win=winp(arr)
        parr arr
      end
      
    end
  else
    puts "================="
    puts "CPU2先行"
    puts "================="
    while win==0
      arr=aip(arr)
      win=winp(arr)
      parr arr
      if win==0
        arr=aipme(arr)
        win=winp(arr)
        if win==1
          parr arr
        end
      end
    end
  end
  puts "================="
  case win 
  when 1 then
   puts "游戏结束,CPU1胜利"
   $cpu1win+=1
  when 2 then puts "游戏结束,CPU2胜利"
   $cpu2win+=1
  when 3 then puts "游戏结束,双方平局"
  end
  "================="
end

#主函数
puts "================="
puts "Ruby井字棋v1.0 "
loop{
  $cpu1win=0
  $cpu2win=0
  puts "================="
  puts "按回车键开始游戏,输入q结束,输入c看CPU激情对战!?\n输入cr疯狂看激情对战"
  puts "================="
  g=gets
  if g=="q\n" 
    break
  elsif g=="c\n" 
    puts "================="
    playcpu
  elsif g=="cr\n" 
    puts"要看多少局"
    t=gets.to_i
    if t<=0
      puts"输入非法"
    else
      t.times do
        playcpu
      end
      puts "特么的玩了#{t}局,CPU1赢了#{$cpu1win}局,CPU2赢了#{$cpu2win}局,平局#{t-$cpu1win-$cpu2win}"
    end
    
  else
    puts "================="
    play
  end
}

AI进行一步预判,测试可以看出AI行动已经符合预期了,比较智能。

接下来就是对井字棋游戏的必胜手段阻止,井字棋这个游戏 存在第一步走角,对方不走中间必败、以及第一步走中间,对方不走角必败的必胜手段。所以根据必胜手段的阻止进化出了普通和困难两种AI

三种难度的AI性能测试:
AI Vs随机走子 100局 97胜3平
困难AI Vs 简单AI 5000局 895胜783负3322平
困难AI Vs 普通AI 5000局 747胜687负3566平
普通AI Vs 简单AI 5000局 909胜589负3502平

2.橙光实现

同样的手段在橙光重做了一遍,具体的地址是:点击开玩

并上架素材交易平台:购买橙光版模板

 


想要成为自己的未来