井字棋代码

井字棋代码

package a;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;


public class TT2
{
	private Scanner scan;
	Set set_all;  // 所有位置
	Set[] set_xo; // 双方已经落子的位置
	int igo;  //有走棋权一方的索引
	Set[] set_win; //所有赢棋子力排列局面
	int iAI;  //让AI持哪一方
	int last_step; // 最后一步走在哪里
	
	public TT2()
	{
		scan = new Scanner(System.in);
		
		set_all = new HashSet();
		for(int i=0; i<9; i++) set_all.add(i);
		
		set_xo = new Set[2];
		set_xo[0] = new HashSet();
		set_xo[1] = new HashSet();
		igo = 0;
		
		int[][] tmp = {{0,1,2},{3,4,5},{6,7,8},
			{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
		set_win = new Set[tmp.length];
		for(int i=0; i<tmp.length; i++){
			set_win[i] = new HashSet();
			for(int j=0; j<tmp[i].length; j++) set_win[i].add(tmp[i][j]);
		}
		
		iAI = -1;  // AI不参与
		last_step = -1;  // 还没有最后一步
	}
	
	// >0 必赢 <0必输 =0 平局
	private int tryAIgo()
	{
		if(set_all.size() == set_xo[0].size() + set_xo[1].size()) return 0;//0的一方和1的一方棋子容量相等了
		
		Set t = new HashSet(); 
		t.addAll(set_all);//初始化棋盘
		t.removeAll(set_xo[0]);//去掉走棋的位置
		t.removeAll(set_xo[1]);//去掉另一方走棋的位置
		
		int rr = -1; //假设必输
		for(Object k: t){
			set_xo[igo].add(k); //试走
			try{
				if(test_finish()==igo) return 1;
				
				igo = (igo+1)%2;
				try{
					int r = tryAIgo();
					if(r<0) return 1;
					if(r==0) rr = 0;  // 发现平局走法
				}
				finally{
					igo = (igo+1)%2;  //回溯
				}
			}
			finally{
				set_xo[igo].remove(k);
			}
		}
		
		return rr;
	}
	
	// 机器走棋
	private int getAIresult()
	{
		Set t = new HashSet(); 
		t.addAll(set_all);
		t.removeAll(set_xo[0]);
		t.removeAll(set_xo[1]);
		
		List win = new ArrayList();  // 记录所有赢局招法
		List tie = new ArrayList();  // 记录所有平局招法
		
		for(Object k: t){
			set_xo[igo].add(k); //试走
			try{
				if(test_finish()==igo){ 
					win.add(k);
					continue;
				}
				
				igo = (igo+1)%2;
				try{
					int r = tryAIgo();
					if(r<0) win.add(k);
					if(r==0) tie.add(k);
				}
				finally{
					igo = (igo+1)%2;  //回溯
				}
			}
			finally{
				set_xo[igo].remove(k);
			}
		}
		
		
		if(win.size()>0) return (Integer)win.get((int)(Math.random() * win.size()));
		
		if(tie.size()>0) return (Integer)tie.get((int)(Math.random() * tie.size()));
		
		//虽然机器智能判负,但棋盘仍可走,可以随机走一步,期待对手失误。
		return randomGo();
	}	
	
	private int randomGo()
	{
		if(set_all.size() == set_xo[0].size() + set_xo[1].size()) return -1;

		List t = new ArrayList();	
		t.addAll(set_all);
		t.removeAll(set_xo[0]);
		t.removeAll(set_xo[1]);
		return (Integer)t.get((int)(Math.random() * t.size()));
	}
	
	private void show()
	{
		for(int i=0; i<9; i++){
			if(i%3==0) System.out.println();
			char c = '.';
			if(set_xo[0].contains(i)) c = 'x';
			if(set_xo[1].contains(i)) c = 'o';
			if(i == last_step) c -= 32;
			System.out.print(c + " ");
		}
		System.out.println();
	}
	
	private int getPlayerInput()
	{
		char c = 'x';
		if(igo==1) c = 'o';
		for(;;){
			try{
				System.out.print("请" + c + "方走棋:");
				int n = (iAI==igo)?
					getAIresult() :
					Integer.parseInt(scan.nextLine());
				if(n<0) return n; // 认输
				if(set_all.contains(n)==false) throw new Exception("");
				if(set_xo[0].contains(n) || set_xo[1].contains(n)) throw new Exception("");
				return n;
			}
			catch(Exception e){
				System.out.println("不正确的输入位置....");
			}
		}
	}
	

	// 0,1:有胜负分出,2:全部下完没分胜负,平局,-1:尚无胜负,可以继续下
	private int test_finish()
	{
		for(int i=0; i<set_win.length; i++){
			if(set_xo[0].containsAll(set_win[i])) return 0; // x胜
			if(set_xo[1].containsAll(set_win[i])) return 1; // o胜
		}
		
		if(set_xo[0].size() + set_xo[1].size() == set_all.size()) return 2; //平局
		
		return -1; //继续
	}
	
	// 设置AI持有哪一方
	public void setAI(int n)
	{
		if(n>1) return;
		iAI = n;
	}
	
	public void start()
	{
		for(;;){
			show();
			int r = test_finish(); //检测是否棋局应该结束
			if(r==0) System.out.println("x方胜出!");
			if(r==1) System.out.println("o方胜出!");
			if(r==2) System.out.println("平局结束!");
			if(r>=0) break;
			
			int pi = getPlayerInput();
			
			if(pi<0){
				char c = igo==0 ? 'x' : 'o';
				System.out.println(c + "方放弃!游戏结束!");
				break;
			}
			
			set_xo[igo].add(pi);
			last_step = pi;
			igo = (igo+1)%2;
		}
	}
	
	private static void welcome()
	{
		System.out.println("----------------");
		System.out.println("井字棋游戏  coded by gyhang");
		System.out.println("九宫格用 0~8 的数字表示:");
		System.out.println("0 1 2");
		System.out.println("3 4 5");
		System.out.println("6 7 8");
		System.out.println("x方与o方轮流走棋,x方先走,连成一条直线的一方获胜。");
		System.out.println("------------------------------------------------------");
	}
	
	public static void main(String[] args)
	{
		welcome();
		TT2 a = new TT2();
		a.setAI(0);  //机器先走
		//a.setAI(1);  //人先走
		//a.setAI(-1);  //机器不参与
		a.start();
	}
}


----------------
井字棋游戏  coded by gyhang
九宫格用 0~8 的数字表示:
0 1 2
3 4 5
6 7 8
x方与o方轮流走棋,x方先走,连成一条直线的一方获胜。
------------------------------------------------------

. . . 
. . . 
. . . 
请x方走棋:
X . . 
. . . 
. . . 
请o方走棋:4

x . . 
. O . 
. . . 
请x方走棋:
x . . 
. o X 
. . . 
请o方走棋:1

x O . 
. o x 
. . . 
请x方走棋:
x o . 
. o x 
. X . 
请o方走棋:8

x o . 
. o x 
. x O 
请x方走棋:
x o X 
. o x 
. x o 
请o方走棋:3

x o x 
O o x 
. x o 
请x方走棋:
x o x 
o o x 
X x o 
平局结束!



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值