`

Crazy Java Practice 第1章 控制台五子棋

    博客分类:
  • Java
阅读更多
package org.crazyit.gobang;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 五子棋游戏类
 * 
 * @author yangenxiong yangenxiong2009@gmail.com
 * @author Kelvin Mak kelvin.mak125@gmail.com
 * @version  1.0
 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 * <br>Copyright (C), 2009-2010, yangenxiong
 * <br>This program is protected by copyright laws.
 */
public class GobangGame {
	// 定义达到赢条件的棋子数目
	private final int WIN_COUNT = 5;
	// 定义用户输入的X坐标
	private int posX = 0;
	// 定义用户输入的X坐标
	private int posY = 0;
	// 定义棋盘
	private Chessboard chessboard;

	/**
	 * 空构造器
	 */
	public GobangGame() {
	}

	/**
	 * 构造器,初始化棋盘和棋子属性
	 * 
	 * @param chessboard
	 *            棋盘类
	 */
	public GobangGame(Chessboard chessboard) {
		this.chessboard = chessboard;
	}

	/**
	 * 检查输入是否合法。
	 * 
	 * @param inputStr
	 *            由控制台输入的字符串。
	 * @return 字符串合法返回true,反则返回false。
	 */
	public boolean isValid(String inputStr) {
		// 将用户输入的字符串以逗号(,)作为分隔,分隔成两个字符串
		String[] posStrArr = inputStr.split(",");
		try {
			posX = Integer.parseInt(posStrArr[0]) - 1;
			posY = Integer.parseInt(posStrArr[1]) - 1;
		} catch (NumberFormatException e) {
			chessboard.printBoard();
			System.out.println("请以(数字,数字)的格式输入:");
			return false;
		}
		// 检查输入数值是否在范围之内
		if (posX < 0 || posX >= Chessboard.BOARD_SIZE || posY < 0
				|| posY >= Chessboard.BOARD_SIZE) {
			chessboard.printBoard();
			System.out.println("X与Y坐标只能大于等于1,与小于等于" + Chessboard.BOARD_SIZE
					+ ",请重新输入:");
			return false;
		}
		// 检查输入的位置是否已经有棋子
		String[][] board = chessboard.getBoard();
		if (board[posX][posY] != "十") {
			chessboard.printBoard();
			System.out.println("此位置已经有棋子,请重新输入:");
			return false;
		}
		return true;
	}

	/**
	 * 开始下棋
	 */
	public void start() throws Exception {
		// true为游戏结束
		boolean isOver = false;
		chessboard.initBoard();
		chessboard.printBoard();
		// 获取键盘的输入
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String inputStr = null;
		// br.readLine:每当键盘输入一行内容按回车键,则输入的内容被br读取到
		while ((inputStr = br.readLine()) != null) {
			isOver = false;
			if (!isValid(inputStr)) {
				// 如果不合法,要求重新输入,再继续
				continue;
			}
			// 把对应的数组元素赋为"●"
			String chessman = Chessman.BLACK.getChessman();
			chessboard.setBoard(posX, posY, chessman);
			// 判断用户是否赢了
			if (isWon(posX, posY, chessman)) {
				isOver = true;

			} else {
				// 计算机随机选择位置坐标
				int[] computerPosArr = computerDo();
				chessman = Chessman.WHITE.getChessman();
				chessboard.setBoard(computerPosArr[0], computerPosArr[1],
						chessman);
				// 判断计算机是否赢了
				if (isWon(computerPosArr[0], computerPosArr[1], chessman)) {
					isOver = true;
				}
			}
			// 如果产生胜者,询问用户是否继续游戏
			if (isOver) {
				// 如果继续,重新初始化棋盘,继续游戏
				if (isReplay(chessman)) {
					chessboard.initBoard();
					chessboard.printBoard();
					continue;
				}
				// 如果不继续,退出程序
				break;
			}
			chessboard.printBoard();
			System.out.println("请输入您下棋的坐标,应以x,y的格式输入:");
		}
	}

	/**
	 * 是否重新开始下棋。
	 * 
	 * @param chessman
	 *            "●"为用户,"○"为计算机。
	 * @return 开始返回true,反则返回false。
	 */
	public boolean isReplay(String chessman) throws Exception {
		chessboard.printBoard();
		String message = chessman.equals(Chessman.BLACK.getChessman()) ? "恭喜您,您赢了,"
				: "很遗憾,您输了,";
		System.out.println(message + "再下一局?(y/n)");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		if (br.readLine().equals("y")) {
			// 开始新一局
			return true;
		}
		return false;

	}

	/**
	 * 计算机随机下棋
	 */
	public int[] computerDo() {
		int posX = (int) (Math.random() * (Chessboard.BOARD_SIZE - 1));
		int posY = (int) (Math.random() * (Chessboard.BOARD_SIZE - 1));
		String[][] board = chessboard.getBoard();
		while (board[posX][posY] != "十") {
			posX = (int) (Math.random() * (Chessboard.BOARD_SIZE - 1));
			posY = (int) (Math.random() * (Chessboard.BOARD_SIZE - 1));
		}
		int[] result = { posX, posY };
		return result;
	}

	/**
	 * 判断输赢
	 * 
	 * @param posX
	 *            棋子的X坐标。
	 * @param posY
	 *            棋子的Y坐标
	 * @param ico
	 *            棋子类型
	 * @return 如果有五颗相邻棋子连成一条直接,返回真,否则相反。
	 */
	public boolean isWon(int posX, int posY, String ico) {
		// 直线起点的X坐标
		int startX = 0;
		// 直线起点Y坐标
		int startY = 0;
		// 直线结束X坐标
		int endX = Chessboard.BOARD_SIZE - 1;
		// 直线结束Y坐标
		int endY = endX;
		// 同条直线上相邻棋子累积数
		int sameCount = 0;
		int temp = 0;

		// 计算起点的最小X坐标与Y坐标
		temp = posX - WIN_COUNT + 1;
		startX = temp < 0 ? 0 : temp;
		temp = posY - WIN_COUNT + 1;
		startY = temp < 0 ? 0 : temp;
		// 计算终点的最大X坐标与Y坐标
		temp = posX + WIN_COUNT - 1;
		endX = temp > Chessboard.BOARD_SIZE - 1 ? Chessboard.BOARD_SIZE - 1
				: temp;
		temp = posY + WIN_COUNT - 1;
		endY = temp > Chessboard.BOARD_SIZE - 1 ? Chessboard.BOARD_SIZE - 1
				: temp;
		// 从左到右方向计算相同相邻棋子的数目
		String[][] board = chessboard.getBoard();
		for (int i = startY; i < endY; i++) {
			if (board[posX][i] == ico && board[posX][i + 1] == ico) {
				sameCount++;
			} else if (sameCount != WIN_COUNT - 1) {
				sameCount = 0;
			}
		}
		if (sameCount == 0) {
			// 从上到下计算相同相邻棋子的数目
			for (int i = startX; i < endX; i++) {
				if (board[i][posY] == ico && board[i + 1][posY] == ico) {
					sameCount++;
				} else if (sameCount != WIN_COUNT - 1) {
					sameCount = 0;
				}
			}
		}
		if (sameCount == 0) {
			// 从左上到右下计算相同相邻棋子的数目
			int j = startY;
			for (int i = startX; i < endX; i++) {
				if (j < endY) {
					if (board[i][j] == ico && board[i + 1][j + 1] == ico) {
						sameCount++;
					} else if (sameCount != WIN_COUNT - 1) {
						sameCount = 0;
					}
					j++;
				}
			}
		}
		return sameCount == WIN_COUNT - 1 ? true : false;
	}

	public static void main(String[] args) throws Exception {

		GobangGame gb = new GobangGame(new Chessboard());
		gb.start();
	}
}



package org.crazyit.gobang;

/**
 * 棋子枚举类
 * 
 * @author yangenxiong yangenxiong2009@gmail.com
 * @author Kelvin Mak kelvin.mak125@gmail.com
 * @version  1.0
 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 * <br>Copyright (C), 2009-2010, yangenxiong
 * <br>This program is protected by copyright laws.
 */
public enum Chessman {
	BLACK("●"), WHITE("○");
	private String chessman;

	/**
	 * 私有构造器
	 */
	private Chessman(String chessman) {
		this.chessman = chessman;
	}

	/**
	 * @return String 黑棋或者白棋
	 */
	public String getChessman() {
		return this.chessman;
	}
}


package org.crazyit.gobang;

/**
 * 棋盘对象
 * 
 * @author yangenxiong yangenxiong2009@gmail.com
 * @author Kelvin Mak kelvin.mak125@gmail.com
 * @version  1.0
 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 * <br>Copyright (C), 2009-2010, yangenxiong
 * <br>This program is protected by copyright laws.
 */
public class Chessboard {
	// 定义一个二维数组来充当棋盘
	private String[][] board;
	// 定义棋盘的大小
	public static final int BOARD_SIZE = 22;

	/**
	 * 初始化棋盘
	 * 
	 * @return void
	 */
	public void initBoard() {
		// 初始化棋盘数组
		board = new String[BOARD_SIZE][BOARD_SIZE];
		// 把每个元素赋值为“十”,用于控制台输出棋盘
		for (int i = 0; i < BOARD_SIZE; i++) {
			for (int j = 0; j < BOARD_SIZE; j++) {
				board[i][j] = "十";
			}
		}
	}
	
	public void test() {
		Object[][] array = new Object[10][10];
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				array[i][j] = new Object();
			}
		}
	}

	/**
	 * 在控制台输出棋盘的方法
	 */
	public void printBoard() {
		// 打印每个数组元素
		for (int i = 0; i < BOARD_SIZE; i++) {
			for (int j = 0; j < BOARD_SIZE; j++) {
				// 打印后不换行
				System.out.print(board[i][j]);
			}
			// 每打印完一行数组元素就换行一次
			System.out.print("\n");
		}
	}

	/**
	 * 给棋盘位置赋值
	 * 
	 * @param posX
	 *            X坐标
	 * @param posY
	 *            Y坐标
	 * @param chessman
	 *            棋子
	 */
	public void setBoard(int posX, int posY, String chessman) {
		this.board[posX][posY] = chessman;
	}

	/**
	 * 返回棋盘
	 * 
	 * @return 返回棋盘
	 */
	public String[][] getBoard() {
		return this.board;
	}
}


isWon() 必须加入这段代码(随书代码无此段代码),否则,撇方向(斜杠/)方向的同色棋子不会得到检测
		if (sameCount == 0) {
			int j=1;
			for(int i = posX; i <= endX; i++){
				if((posX + j <= endX) && (posY - j >= startY)){
					if (board[posX][posY] == ico && board[posX + j][posY - j] == ico) {
						sameCount++;
					} else if (sameCount != WIN_COUNT - 1) {
						sameCount = 0;
					}
					j++;
				}
			}
			j=1;
			for(int i = posX; i >= startX; i--){
				if((posX - j >= startX) && (posY + j <= endY)){
					if (board[posX][posY] == ico && board[posX - j][posY + j] == ico) {
						sameCount++;
					} else if (sameCount != WIN_COUNT - 1) {
						sameCount = 0;
					}
					j++;
				}
			}			
		}
分享到:
评论

相关推荐

    Crazy Java Practice 第3章 图片浏览器

    《Crazy Java Practice 第3章 图片浏览器》 在Java编程的世界中,开发一个图片浏览器是一种常见的实践项目,它能够帮助我们深入理解图形用户界面(GUI)编程、文件操作以及图像处理等核心概念。本章节将围绕这个...

    Crazy-JAVA-mind-map.zip_Crazy JAVA mind map_crazy_java-mindmap_m

    这份"Crazy-JAVA-mind-map.zip"压缩包包含了一个名为"Crazy JAVA mind map.mmap"的思维导图文件,这个导图就是对《疯狂JAVA讲义》内容的高度概括和逻辑梳理,旨在帮助学习者更好地理解和记忆书中的知识点。...

    java疯狂讲义源代码项目_CrazyJava.zip

    java疯狂讲义源代码项目_CrazyJava

    Java 项目-java的JAVA五子棋手机网络对战游戏的设计与实现.zip

    【描述】: 这个Java项目专注于开发一个基于网络的五子棋手机游戏,允许玩家在线进行实时对战。它利用Java语言的强大功能,结合网络编程技术,为用户提供了一个互动的对战平台。 【标签】: 1. **Java**: Java是一种...

    java实现学生管理系统(控制台)

    编写学生管理系统,学生信息(学员信息:学号、姓名、年龄、性别、家庭住址,其他属性可以自行给定)以对象方式存入数组中,利用控制台显示; 需求:1.用户需要登陆,如果无法登陆的用户需要先注册(登陆,注册,...

    Java 项目-java的基于Java的五子棋游戏的设计.zip

    Java 项目,包含:项目源码、数据库脚本、部署说明等,前后端代码都在里面 。 该系统功能完善、界面美观、...1. Java,用IDEA 或者 Ecplise 即可 2. 数据库可视化软件,推荐使用它 Navicat,MySql 建议使用 5.7 版本

    java7源码-crazyJava3_4:疯狂java3-4的学习

    crazyJava3_4 疯狂java3-4的学习 简单介绍 此代码,主要是为了学习java基础而创建 本代码中大部分代码是从疯狂java的源码中copy过来的.主要是用于跑一下.演示加强自己对疯狂java讲义中所讲述的含义的理解. 在copy过来...

    讲java源码的书-CrazyJava:《疯狂的Java讲义》书籍源代码

    《疯狂的Java讲义》是一本深入探讨Java编程语言的书籍,其源代码库名为"CrazyJava",在开源社区中广泛流传。这本书的核心目标是帮助读者深入理解Java的内部机制,通过源码分析,提升编程技能和问题解决能力。在阅读...

    crazy-eights:Crazy Heights,Java 游戏(学者项目,2011)

    Crazy Heights是一款基于Java开发的桌面游戏,灵感来源于经典的“疯狂八”(Crazy Eights)纸牌游戏。这个游戏由学术项目开发,旨在提供一个数字化的平台,让玩家可以在线上进行游戏。在2011年,Java作为主流的编程...

    Crazy Bump大理石生成软件

    Crazy Bump是一款强大的纹理生成软件,为设计师、艺术家和游戏开发者提供了快速高效的纹理转换和编辑工具。无论您是在创建3D模型、设计游戏场景,还是进行艺术创作,Crazy Bump都能为您提供丰富多样的纹理效果,让...

    Crazy8s:编程 Crazy 8s 游戏介绍 (Java)

    本教程将重点介绍如何使用Java语言来创建一个疯狂8s游戏的模拟器。 **Java编程基础** 在开始编写Crazy 8s游戏之前,我们需要了解Java的基本语法和面向对象编程的概念。Java是一种强类型、面向对象的语言,具有丰富...

    CrazyStone2016疯狂石头深度学习版

    英文破解版 CrazyStone、天顶与银星号称已战胜专业棋手的三大围软,当“狗狗”还不能进入普通个人电脑的当今,这三大围软已足以在2016年掀起冲击人脑的狂风暴雨。 CrazyStone深度学习版比CrazyStone2013强约4子左右...

    test_jni_hooks.rar_crazy

    1. **编写测试代码**:在`test_jni_hooks.c`中,开发者会创建一个JNI函数,该函数会调用`crazy_context_set_java_vm()`并检查其返回值和副作用。 2. **编译和链接**:使用合适的编译器(如GCC或Clang)将C源代码编译...

    Crazy Browser

    Crazy Browser

    java免费下载资源网站

    Java是一种广泛使用的编程语言,由Sun Microsystems(现为Oracle公司的一部分)于1995年发布。它以其“一次编写,到处运行”的特性而闻名,适用于各种操作系统,包括Windows、Linux和macOS。Java的设计理念是面向...

    Crazy

    "Crazy"这个标题可能是指一种独特的、富有创意的字体或者一个与字体设计相关的项目。下面我们将深入探讨字体设计的相关知识点。 1. **字体分类**:字体通常分为衬线字体(如Times New Roman)、无衬线字体(如Arial...

    win10 crazy error.exe

    C++实现轻量级win10 crazy error.使用前请先在同一目录创建error.vbs,内容随意(非vbs代码就行)源码我也上传了,csdn上找一找把 注:不要拿来坑人,后果自负

    疯狂Java全书代码

    《疯狂Java全书》是李刚老师的一部经典著作,主要面向Java初学者,通过深入浅出的方式讲解了Java编程的基础知识和高级特性。这本书的代码库包含了书中所有示例和练习的源代码,这对于学习者来说是一份极其宝贵的资源...

    Crazy Cubes 3D.app

    因此,"Crazy Cubes 3D.app" 是一个专门为Mac设计的应用程序,它提供了一个游戏平台,让玩家可以在自己的Mac电脑上体验这款游戏。 游戏的名称“Crazy Cubes 3D”暗示了其核心玩法——玩家将面对各种三维立方体的...

Global site tag (gtag.js) - Google Analytics