12人局的一个游戏
平民阵营(好人阵营):4个平民
神职阵营(好人阵营):4个,分别是预言家,女巫,猎人,白痴
狼人阵营(狼人阵营):4个,4个狼人
2个大的阶段:黑夜阶段,白天阶段
黑夜阶段:(第一阶段)
4个狼人见面,共同去决定猎杀一名玩家,狼人的行为就结束了
神职阵营行动:
1.预言家行动:预言家会查验一个玩家的身份是好人还是狼人
查验3号,3号身份–女巫,查验的结果为好人,查验4号,4号身份–狼人,查验的结果就是狼人。
2.女巫:一局游戏一共有两瓶药,分别解药与毒药。当女巫有解药的时候,会告诉当天晚上谁被狼人袭击了,决定是否救这名玩家。一旦解药被使用,就无法得知谁被杀了。在解药没有任何操作的时候,进行毒药的操作,选择一名玩家的序号,直接毒杀。一旦两瓶药都用完,晚上无任何操作。
女巫两瓶药都在,4号被猎杀了,提示:今晚4号死了,是否使用解药?1.救 2不救
1 -->今天晚上女巫环节就结束了 2–>是否使用毒药?(给定序号) 10 -->10,4两个都死了
3.猎人:晚上无任何行动。当晚上他被狼人猎杀、放逐的时候,白天宣布死亡的那刻,他可以发动技能开枪带走一名玩家。
4.白痴:晚上无任何行动。当白天公投阶段被放逐出时,可以发动技能免除放逐。
平民阵营:无任何行动。
白天阶段:(第二阶段)
1.宣布死讯:公布死亡的玩家序号(不公布其身份),死亡的玩家发表遗言
2.随机指定剩下存活的人的序号,开始发言(3号发言之后,5号发言,6号…)
3.当所有人都发言完毕时候,所有玩家公投一名玩家进行放逐(死亡),如果他的身份是猎人或白痴的话,会发动技能(猎人是带走一名玩家,白痴免疫此次放逐)
黑夜–>白天–>交替进行 直到每个阶段阶段结束后,进行胜负判定
胜负判定:
当其中一方阵营全部死亡,即另一方阵营获胜。
好人获胜:4名狼人全都死了
狼人获胜:4个神职死亡 或者 4个平民死亡 都算狼人获胜
Data类:
package com.azwcl.game;
/**
* 游戏数据类
* @author 吴乘龙
* @Time 2020-9-11 22:00
*/
public class Data {
private final String[] identity = {"平民","平民","平民","平民","预言家","女巫","猎人","白痴","狼人","狼人","狼人","狼人"};//12种身份种类
private final Gamer[] gamers;//玩家数组
private int prophetId;//预言家id
private int sorceressId;//女巫id
private int huntsmanId;//猎人id
private int idiotId;//白痴id
/**
* 初始化函数,初始化gamers数组内Gamer变量
*/
public Data(){
this.gamers = new Gamer[12];
for(int i = 0; i < gamers.length; i++){
gamers[i] = new Gamer();
}
}
/**
* 获取身份方法
* @return String[] 获取身份数组
*/
public String[] getIdentity() {
return identity;
}
/**
* 获取游戏玩家数组
* @return Gamer[] 游戏玩家数组
*/
public Gamer[] getGamers() {
return gamers;
}
/**
* 获取预言家id
* @return int 预言家id
*/
public int getProphetId() {
return prophetId;
}
/**
* 获取女巫id
* @return int 女巫id
*/
public int getSorceressId() {
return sorceressId;
}
/**
* 获取猎人id
* @return int 猎人id
*/
public int getHuntsmanId() {
return huntsmanId;
}
/**
* 获取白痴id
* @return int 白痴id
*/
public int getIdiotId() {
return idiotId;
}
/**
* 设置预言家id
* @param prophetId int 预言家id
*/
public void setProphetId(int prophetId) {
this.prophetId = prophetId;
}
/**
* 设置女巫id
* @param sorceressId int 女巫id
*/
public void setSorceressId(int sorceressId) {
this.sorceressId = sorceressId;
}
/**
* 设置猎人id
* @param huntsmanId int 猎人id
*/
public void setHuntsmanId(int huntsmanId) {
this.huntsmanId = huntsmanId;
}
/**
* 设置白痴id
* @param idiotId int 白痴id
*/
public void setIdiotId(int idiotId) {
this.idiotId = idiotId;
}
}
Gamer类:
package com.azwcl.game;
/**
* 游戏玩家类
* @author 吴乘龙
* @Time 2020-9-11 22:00
*/
public class Gamer {
private boolean isLive;//是否活着
private boolean isGoodPerson;//是否是好人
private String identity;//身份
private boolean isHavePoison;//是否有毒药
private boolean isHaveAntidote;//是否有解药
private boolean isReferendumDied;//免除公投死亡效果
/**
* 构造方法
*/
public Gamer(){
isLive = true;
isHavePoison = false;
isHaveAntidote = false;
isReferendumDied = false;
}
//get和set方法
public boolean getIsLive() {
return isLive;
}
public boolean getIsGoodPerson() {
return isGoodPerson;
}
public String getIdentity() {
return identity;
}
public boolean getIsHavePoison() {
return isHavePoison;
}
public boolean getIsHaveAntidote() {
return isHaveAntidote;
}
public boolean getIsReferendumDied(){
return isReferendumDied;
}
public void setIsLive(boolean live) {
isLive = live;
}
public void setIsGoodPerson(boolean goodPerson) {
isGoodPerson = goodPerson;
}
public void setIdentity(String identity) {
this.identity = identity;
}
public void setIsHavePoison(boolean havePoison) {
isHavePoison = havePoison;
}
public void setIsHaveAntidote(boolean haveAntidote) {
isHaveAntidote = haveAntidote;
}
public void setIsReferendumDied(boolean referendumDied){
isReferendumDied = referendumDied;
}
}
Input类
package com.azwcl.game;
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* 输入类
* @author 吴乘龙
* @Time 2020-9-11 22:00
*/
public class Input {
/**
* 输入类静态方法,方便输入
* @param expertStart int 期望输入整数的开始
* @param expertEnd int 期望输入整数的结束
* @param message String 输入的提示笑死
* @param errorMessage String 输入错误的时候的提示消息
* @return int 返回输入的整数
*/
public static int inputOption(int expertStart, int expertEnd, String message, String errorMessage){
System.out.println("-----+++++-----+++++-----+++++-----");
System.out.print(message);
int option = 0;
while (true){
try{
Scanner sc = new Scanner(System.in);
option = sc.nextByte();
if(option > expertEnd || option < expertStart) {
throw new InputMismatchException();
}
else break;
}catch (InputMismatchException e){
System.out.println(errorMessage);
System.out.print("请重新输入:");
}
}
return option;
}
}
Menu类
package com.azwcl.game;
/**
* 游戏菜单类
* @author 吴乘龙
* @Time 2020-9-11 22:00
*/
public class Menu {
/**
* 游戏欢迎界面菜单
* @param data Data[] 游戏数据数组
* @param stage Stage 游戏阶段类变量
*/
public void welcome(Data data,Stage stage){
System.out.print("正在进入游戏中");
Print.printDot(3);
System.out.println("欢迎您进入狼人杀游戏,祝你游戏愉快...");
System.out.println("-----+++++-----+++++-----+++++-----");
System.out.println("1.开始游戏");
System.out.println("2.退出游戏");
int option = Input.inputOption(1,2,"请输入您的选择:", "对不起,您的选择有误!");
if(option == 1){
startGame(data,stage);
}else if(option == 2) {
gameOverMessage();
}
}
/**
* 游戏开始界面菜单
* @param data Data[] 游戏数据数组
* @param stage Stage 游戏阶段类变量
*/
public void startGame(Data data,Stage stage){
System.out.println("游戏开始了!!!");
System.out.println("请大家准备好~~~~!!!");
System.out.print("分配角色中");
stage.distributionIdentity(data);
Print.printDot(3);
System.out.println("分配角色完毕...");
Print.printIdentity(data);
stage.gaming(data);
}
/**
* 在欢迎界面直接退出提示
*/
private void gameOverMessage() {
System.out.println("不玩玩就走了吗~~~,好的吧~拜拜~");
System.out.println("正在退出");
Print.printDot(3);
}
}
Print类
package com.azwcl.game;
/**
* 简化输出方法
* @author 吴乘龙
* @Time 2020-9-12 13:00
*/
public class Print {
/**
* 输出点方法
* @param number int 要输出的点数目
*/
public static void printDot(int number){
for(int i = 0 ; i < number; i++){
try{
Thread.sleep(300);
}catch (InterruptedException e){
System.out.println("游戏异常,正在退出...");
System.exit(0);
}
System.out.print(".");
}
System.out.println();
}
/**
* 打印各玩家身份
* @param data Data[] 游戏数据
*/
public static void printIdentity(Data data){
System.out.println("各玩家身份:");
for(int i = 0 ; i < 12; i++){
System.out.print((i + 1) + " : " + data.getGamers()[i].getIdentity() + "\t");
}
System.out.println();
}
}
Stage类
package com.azwcl.game;
import java.util.Arrays;
import java.util.Vector;
/**
* 游戏阶段类
* @author 吴乘龙
* @Time 2020-9-11 22:00
*/
public class Stage {
/**
* 分配身份方法
* @param data Data[] 游戏数据数组
*/
public void distributionIdentity(Data data){
Vector<String> copyIdentity = new Vector<String>(Arrays.asList(data.getIdentity()));
for(int i = 0 ; i < 12; i++){
int randomNum = (int) (Math.random() * (12-i));
data.getGamers()[i].setIdentity(copyIdentity.get(randomNum));
copyIdentity.remove(randomNum);
}
//分配完身份,设置data身份数据
for(int i = 0 ; i < 12; i++){
if(data.getGamers()[i].getIdentity().equals("平民")) {
data.getGamers()[i].setIsGoodPerson(true);
}
else if(data.getGamers()[i].getIdentity().equals("狼人")) {
data.getGamers()[i].setIsGoodPerson(false);
}
else if(data.getGamers()[i].getIdentity().equals("预言家")) {
data.setProphetId(i);
data.getGamers()[i].setIsGoodPerson(true);
}
else if(data.getGamers()[i].getIdentity().equals("女巫")) {
data.setSorceressId(i);
data.getGamers()[i].setIsHavePoison(true);
data.getGamers()[i].setIsHaveAntidote(true);
data.getGamers()[i].setIsGoodPerson(true);
}
else if(data.getGamers()[i].getIdentity().equals("猎人")) {
data.setHuntsmanId(i);
data.getGamers()[i].setIsGoodPerson(true);
}
else if(data.getGamers()[i].getIdentity().equals("白痴")) {
data.setIdiotId(i);
data.getGamers()[i].setIsReferendumDied(true);
data.getGamers()[i].setIsGoodPerson(true);
}
}
}
/**
* 晚上过程
* @param data Data[] 游戏数据数组
* @return 0-未结束,1-好人胜利,2-狼人胜利
*/
public int runNight(Data data){
System.out.println("天黑请闭眼...");
//狼人回合
System.out.println("狼人请睁眼...");
int diedGamerId;
while(true){
diedGamerId = Input.inputOption(1,12,"狼人,请你们选择你们即将猎杀的玩家:", "输入有误,请重新输入:");
diedGamerId -= 1;
//判断玩家是否存活
if(data.getGamers()[diedGamerId].getIsLive()) {
data.getGamers()[diedGamerId].setIsLive(false);
break;
}
else System.out.println("你们选择猎杀的玩家在前面的回合中已经死亡,请重新选择!");
}
//判断是否结束
int res = isGamerOver(data);
if(res != 0){
return res;
}
//预言家回合
int seeGamerIdentityId;
if(data.getGamers()[data.getProphetId()].getIsLive() || diedGamerId == data.getProphetId()){
System.out.println("预言家请睁眼...");
while(true){
seeGamerIdentityId = Input.inputOption(1,12,"预言家,请查看您想查看的身份:","输入有误,请重新输入:");
seeGamerIdentityId -= 1;
if(!data.getGamers()[seeGamerIdentityId].getIsLive() && diedGamerId != seeGamerIdentityId){
System.out.println("查看无效,您选择的人在以前的回合已死,无法查看!");
}else break;
}
String seeGamerIdentity = data.getGamers()[seeGamerIdentityId].getIsGoodPerson() ? "好人" : "狼人";
System.out.println("预言家,您查看的人是:" + seeGamerIdentity + "!");
System.out.println("预言家请闭眼!");
}
//女巫行动
System.out.println("女巫请睁眼:");
//女巫有解药
boolean isSave = false;
if(data.getGamers()[data.getSorceressId()].getIsHaveAntidote()){
System.out.println("女巫,昨晚被杀死的人是:" + (diedGamerId + 1));
int save = Input.inputOption(0,1,"请问您是否要救(0-不救,1-救):","输入有误,请重新输入:");
if(save == 1){
data.getGamers()[diedGamerId].setIsLive(true);
data.getGamers()[data.getSorceressId()].setIsHaveAntidote(false);
isSave = true;
}
}
//女巫有毒药
int poisonId = -1;
if(data.getGamers()[data.getSorceressId()].getIsHavePoison() && !isSave){
int isPoison = Input.inputOption(0,1,"请问您是否要使用毒药(0-不使用,1-使用):","输入有误,请重新输入:");
if(isPoison == 1){
while(true){
poisonId = Input.inputOption(1,12, "请选择您要毒死的玩家:", "输入有误,请重新输入:");
poisonId -= 1;
if(!data.getGamers()[poisonId].getIsLive()){
System.out.println("您选择的人已经死了,请重新选择:");
}else {
data.getGamers()[data.getSorceressId()].setIsHavePoison(false);
break;
}
}
}
data.getGamers()[poisonId].setIsLive(false);
//判断是否结束
res = isGamerOver(data);
if(res != 0){
return res;
}
}
//宣布死讯
System.out.println("白天,大家请睁眼!");
if(isSave){
System.out.println("昨晚是个平安夜~");
}else if(poisonId != -1){
System.out.println("昨晚死亡的人是:" + (diedGamerId + 1) + "号和" + (poisonId + 1) + "号玩家!");
}else{
System.out.println("昨晚死亡的人是" + (diedGamerId + 1) + "号玩家!");
}
//如果死亡的是猎人
int huntId = -1;
if(!isSave && (poisonId == data.getHuntsmanId() || diedGamerId == data.getHuntsmanId())){
int isUseSkill = Input.inputOption(0,1,"猎人,昨晚您死亡了,请问,您是否发动技能开枪带走一名玩家(0-否,1-是):","输入有误,请重新输入:");
if(isUseSkill == 1){
while(true){
huntId = Input.inputOption(1,12, "请选择您要猎杀的玩家:", "输入有误,请重新输入:");
huntId -= 1;
if(!data.getGamers()[huntId].getIsLive()){
System.out.println("您选择的人已经死了,请重新选择:");
}else break;
}
}
data.getGamers()[huntId].setIsLive(false);
//判断是否结束
res = isGamerOver(data);
if(res != 0){
return res;
}
}
return 0;
}
/**
* 白天过程
* @param data Data[] 游戏数据数组
* @return 0-未结束,1-好人胜利,2-狼人胜利
*/
public int runDaytime(Data data){
//活着的人存入
Vector<Integer> liveGamers = new Vector<Integer>();
for(int i = 0 ; i < 12; i++){
if(data.getGamers()[i].getIsLive()){
liveGamers.add(i);
}
}
//随机指定人发言
for(int i = liveGamers.size(); i > 0; i--){
int talkGamerId = (int) (Math.random() * i);
System.out.println("请" + (liveGamers.get(talkGamerId)+ 1) + "号玩家发言:");
liveGamers.remove(talkGamerId);
}
//投票
int diedOutId = -1;
while(true){
diedOutId = Input.inputOption(1,12,"请大家商讨,决定要票出的玩家:","输入有误,请重新输入:");
diedOutId -= 1;
if(!data.getGamers()[diedOutId].getIsLive()){
System.out.println("该玩家以前的回合已经死了,请重新决定!");
continue;
}
break;
}
System.out.println("你们票出的玩家是:" + (diedOutId + 1));
data.getGamers()[diedOutId].setIsLive(false);
//判断是否结束
int res = isGamerOver(data);
if(res != 0){
return res;
}
//票出的玩家是猎人:
int huntId = -1;
if(data.getGamers()[diedOutId].getIdentity().equals("猎人")) {
int isUseSkill = Input.inputOption(0, 1, "猎人,您被各位玩家票出,请问,您是否发动技能开枪带走一名玩家(0-否,1-是):", "输入有误,请重新输入:");
if (isUseSkill == 1) {
while (true) {
huntId = Input.inputOption(1, 12, "请选择您要猎杀的玩家:", "输入有误,请重新输入:");
huntId -= 1;
if (!data.getGamers()[huntId].getIsLive()) {
System.out.println("您选择的人已经死了,请重新选择:");
} else break;
}
}
data.getGamers()[huntId].setIsLive(false);
//判断是否结束
res = isGamerOver(data);
if(res != 0){
return res;
}
}
//票出的玩家是白痴:
if(data.getGamers()[diedOutId].getIdentity().equals("白痴")){
if(data.getGamers()[data.getIdiotId()].getIsReferendumDied()){
int isUseSkill = Input.inputOption(0, 1, "白痴,您被各位玩家票出,请问,您是否发动技能保证自己活下来(0-否,1-是):", "输入有误,请重新输入:");
if(isUseSkill == 1){
System.out.println("白痴发动技能生效,免除公投一次");
}else
data.getGamers()[diedOutId].setIsLive(false);
}
}
//判断是否结束
res = isGamerOver(data);
if(res != 0){
return res;
}
else return 0;
}
/**
* 判断游戏是否结束
* @param data Data[] 游戏数据数组
* @return int 0-未结束,1-好人胜利,2-狼人胜利
*/
public int isGamerOver(Data data){
//判断游戏是否结束了
int personNum = 0, wolfNum = 0, godNum = 0;
for(int i = 0 ; i < 12; i++){
if(data.getGamers()[i].getIsLive()){
if(data.getGamers()[i].getIdentity().equals("狼人")) wolfNum++;
else if(data.getGamers()[i].getIdentity().equals("平民")) personNum++;
else godNum++;
}
}
if(wolfNum == 0) return 1;
else if(personNum == 0) return 2;
else if(godNum == 0) return 2;
else return 0;
}
/**
* 游戏阶段
* @param data Data[] 游戏数据数组
*/
public void gaming(Data data){
int res;
while (true){
res = runNight(data);
if(res != 0) break;
res = runDaytime(data);
if(res != 0) break;
}
theGameOver(res);
}
/**
* 游戏结束阶段
* @param res int 最后胜利结果
*/
public void theGameOver(int res){
if(res == 1){
System.out.println("游戏结束,好人胜利");
}else if(res == 2){
System.out.println("游戏结束,狼人胜利");
}
System.out.println("欢饮下次继续玩耍~~~");
System.out.println("正在退出");
Print.printDot(3);
}
}
Main类
package com.azwcl.game;
/**
* 主类
* @author 吴乘龙
* @Time 2020-9-12 14:00
*/
public class Main {
/**
* 主类启动
* @param args String[] 启动方法参数
*/
public static void main(String[] args) {
Data data = new Data();
Stage stage = new Stage();
Menu menu = new Menu();
menu.welcome(data,stage);
}
}