/**
1.先将jansi-1.11.jar文件的路径加入classpath中,里面包含可以改变控制台打印字符颜色的方法.
2.导入需要用到的包
*/
import org.fusesource.jansi.AnsiConsole;
import static org.fusesource.jansi.Ansi.*;
import java.io.IOException;
import java.util.Scanner;
public class KnightChess {
//游戏只有两个玩家,定义两个玩家对象
public static Player p1;
public static Player p2;
//定义一个二维数组来保存地图
public static String[][] map;
//定义一个获取键盘输入的对象
public static Scanner sc = new Scanner(System.in);
//主函数
public static void main(String[] args) throws Exception{
System.out.println("---------------------------------------------------------------------------");
System.out.println("-----------------------------骑士飞行棋------------------------------------");
System.out.println("---------------------------------------------------------------------------");
System.out.println("---------------------------------------------------------------------------");
System.out.println("游戏规则:有两名玩家,已定义成甲和乙。甲、乙玩家轮流"
+ "掷骰子,谁先到终点就赢得比赛。\r\n甲和乙掷骰子都只需要按enter键.");
//创建两个玩家甲 乙
p1 = new Player("甲");
p2 = new Player("乙");
//初始化地图
initMap();
//开始游戏
GameBegin();
//为了线程阻塞,停留在结束画面
System.out.println("-----------游戏结束-----------");
}
//初始化地图
public static void initMap(){
//地图是一个21行30列的二维数组
//给二维数组的每个位置赋值,使打印时显示迂回前进的地图
map = new String[21][30];
for(int i = 0; i < map.length; i++){
for(int j = 0; j < 30; j++){
map[j] = "□";
}
if(i % 4 == 1){
for(int j = 0; j < 29; j++){
map[j] = "我";
}
}
if(i % 4 == 3){
for(int j = 1; j < 30; j++){
map[j] = "我";
}
}
}
//初始化有魔法功能的特殊位置
magicMap();
//甲在数组中的位置
map[p1.posY][p1.posX] = p1.getName();
//乙在数组中的位置
map[p2.posY][p2.posX] = p2.getName();
}
public static void display()throws Exception{
//产生一个进程调用控制台的命令用来清屏
new ProcessBuilder("cmd", "/C", "cls").inheritIO().start();
//因为这里不加这个线程睡眠的语句,打印出的地图有问题,所以加了
//应该是上面进程与下面打印的并行进行,前面打印出的字符都被清屏的进程给清掉了.
Thread.sleep(30);
AnsiConsole.systemInstall();
//根据数组中存储的不同字符打印出不同的字符
for(int i = 0; i < map.length; i++){
for(int j = 0; j < map[0].length; j++){
String shape = map[j];
switch (shape) {
case "□":
System.out.print(ansi().render("@|white " + shape +"|@"));
break;
case "○":
System.out.print(ansi().render("@|red " + shape +"|@"));
break;
case "▽":
System.out.print(ansi().render("@|blue " + shape +"|@"));
break;
case "△":
System.out.print(ansi().render("@|yellow " + shape +"|@"));
break;
case "☆":
System.out.print(ansi().render("@|cyan " + shape +"|@"));
break;
case "◇":
System.out.print(ansi().render("@|white " + shape +"|@"));
break;
case "甲":
System.out.print(ansi().render("@|magenta " + shape +"|@"));
break;
case "乙":
System.out.print(ansi().render("@|yellow " + shape +"|@"));
break;
default:
System.out.print(" ");
break;
}
}
System.out.println();
}
}
//游戏开始
public static void GameBegin() throws Exception{
while(true){
if(Player.flag == "结")
break;
System.out.println("请甲开始掷骰子");
//接收键盘输入,按回车后,执行下一条语句.
sc.nextLine();
//甲玩游戏
p1.play();
if(Player.flag == "结")
break;
System.out.println("请乙开始掷骰子");
sc.nextLine();
//乙玩游戏
p2.play();
}
}
//自定义了不同魔法功能特殊地点的位置
public static void magicMap(){
int[][] mine = {{0,4},{2,9},{4,20},{6,29},{8,10},{10,17},{12,0},{20,5}};
int[][] luckplace = {{0,5},{4,10},{8,13},{10,20},{16,16},{18,20},{20,11},{14,15}};
int[][] back = {{0,7},{2,8},{6,10},{8,7},{10,7},{16,20},{12,8},{14,19}};
int[][] forword = {{14,7},{16,2},{18,13},{20,26},{10,7},{8,0},{6,20},{20,10}};
foreach(luckplace,"☆",map);
foreach(forword,"△",map);
foreach(back,"▽",map);
foreach(mine,"○",map);
}
//给地图设置特殊地点符号
public static void foreach (int[][] arr, String symbol, String[][] map) {
for (int i = 0; i < arr.length; i++) {
int x = arr[0];
int y = arr[1];
map[x][y] = symbol;
}
}
}
public class Player {
//玩家的姓名
private String name;
//玩家在地图中的位置,posX代表玩家所在的列数,posY代表玩家所在的行数.
public int posX;
public int posY;
//定义一个长度为2的数组来存储玩家的位置
public int[] point = new int[2];
//一个判断玩家所在位置魔法功能的旗标
public static String flag;
public String getName(){
return name;
}
//初始化玩家姓名的构造方法
public Player(String name){
this.name = name;
}
/**
玩家玩游戏的方法
*/
public void play() throws Exception{
//随机生成1-6之间的数,模拟掷骰子
int temp = Dice.getNum();
//玩家前进temp步数,并返回前进后位置,此处只算好玩家前进后位置,并没有将玩家移动到该位置
point = forwordLogic(posX,posY,temp);
//获得玩家所在列数
posX = point[0];
//获得玩家所在行数
posY = point[1];
//假如得到自己定义的结束信息,将flag赋值为结
if(posY == 1 && posX == 1)
{
KnightChess.map[1][1] = "结";
flag = "结";
}
//判断玩家是否到达终点,获取玩家所在位置的符号
else if(posY < 21 && posX < 30){
flag = KnightChess.map[posY][posX];
}
//根据前面算出的玩家位置,得到将要到达位置的字符类型,并执行相应的操作,得到最终的地址
point = magicExecute(posX,posY);
//获得玩家最终所在列数
posX = point[0];
//获得玩家最终所在行数
posY = point[1];
//初始化地图,为了消除前面对地图数组赋值产生的改变
KnightChess.initMap();
//显示地图
KnightChess.display();
//输出掷骰子的结果
System.out.print(name + "投掷出了数字:" + temp + "\t");
//通过switch case语句,根据玩家所处位置输出相应的语句
switch (flag) {
case "☆":
System.out.println(name + "搭上火箭了,前进10格!!!!");
break;
case "△":
System.out.println(name + "龙卷风!!前进5格");
break;
case "○":
System.out.println(name + "踩到地雷了,给我直接回到原点!!!!");
break;
case "▽":
System.out.println(name + "脚底打滑,后退5格!!!!");
break;
case "结":
System.out.println(name + "恭喜你!!赢得了比赛!!");
default:
break;
}
}
/**
判断所处位置的符号,根据不同符号执行不同的动作
*/
public int[] magicExecute(int posX, int posY){
if(flag == "☆"){
point = forwordLogic(posX,posY,10); //前进10格
}
if(flag == "△"){
point = forwordLogic(posX,posY,5); //前进5格
}
if(flag == "○"){
point = new int[]{0,0}; //回到原点
}
if(flag == "▽"){
point = backLogic(posX,posY); //后退5格,后退步数方法内写死了
}
return point;
}
/**
实现棋子前进的方法
*/
public int[] forwordLogic(int posX, int posY, int step){
if(posY % 4 == 0){ //玩家位于第0 4 8 12 16 20行
if(posX + step < 30){ //玩家前进step步后依然在本行
posX += step;
}
else if(posX + step == 30){ //玩家前进step步后推进1行,刚好位于转弯点
posX = 29;
posY += 1;
}
else{ //玩家前进step步后推进了2行
posY += 2;
posX = 60 - posX - step;
}
}
else if(posY % 4 == 1){ //玩家位于第1 5 9 13 17行,也就是在转折点,所以肯定进入下一行
posY += 1;
posX = 30 - step;
}
else if(posY % 4 == 2){ //玩家位于第2 6 10 14 18行,前进时列数posX的值减去step
if(posX - step > -1){ //依然有三种情况,分析和前面相同
posX -= step;
}else if(posX - step == -1){
posY += 1;
posX = 0;
}else{
posY += 2;
posX = step - posX - 2;
}
}
else if(posY % 4 == 3){ //玩家位于第3 7 11 15 19行,前进后行数一定加1,并且列数posX的变化方向改变
posY += 1;
posX = posX + step - 1;
}
if(posY < 21 && posX < 30){ //当玩家没有到达终点,返回point数组,存储了玩家位置信息
point[0] = posX;
point[1] = posY;
}else{ //当玩家到达终点,将玩家的位置设置到点(1,1),并返回数组point
point[0] = 1;
point[1] = 1;
}
return point;
}
/**
实现棋子后退的方法
逻辑刚好与前进的相反
*/
public int[] backLogic(int posX, int posY){
int backStep = 5;
if(posY % 4 == 0){
if(posX - backStep > -1){
posX -= backStep;
}else if(posX - backStep == -1){
posY -= 1;
posX = 0;
}else{
posY += 2;
posX = backStep - posX - 2;
}
}
else if(posY % 4 == 1){
posY += 1;
posX = posX - backStep + 1;
}
else if(posY % 4 == 2){
if(posX + backStep < 30){
posX += backStep;
}else if(posX + backStep == 30){
posX = 29;
posY += 1;
}else{
posY += 2;
posX = 60 - posX - backStep;
}
}
else if(posY % 4 == 3){
posY += 1;
posX = posX + backStep - 1;
}
point[0] = posX;
point[1] = posY;
return point;
}
}
/**
1.骰子类,里面方法定义成static当成工具类
2.产生1-6的随机数
*/
public class Dice {
public static int getNum(){
return (int)(Math.random() * 6 + 1);
}
}
图片.png (83.07 KB, 下载次数: 9)
骑士飞行棋
101.32 KB, 下载次数: 53
可以在控制台打印有颜色字符的jar包
8.58 KB, 下载次数: 38
源码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |