一个取火柴的小游戏,规则:一堆火柴,玩家(或电脑)轮流取1到4根,取到最后一根算输。
游戏中可以人机(一个人)或者多人(30人以内)对战,火柴数可以指定或者随机,电脑难度有两种,困难难度要赢很困难(废话)。初学作品,还请多多指教。
package aMatchGame;
//主类
public class Main {
public static void main(String []args){
new Show().showMe();
}
}
package aMatchGame;
//主界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
class Show {
private Config config;
private DateFormat df = new SimpleDateFormat("HH:mm:ss");
private JFrame frame;
private JMenuBar bar;
private JMenu mode;
private JMenuItem pC;
private JMenuItem pP;
private JMenuItem isRandom;
private JMenu setting;
private JMenuItem sysSet;
private JMenuItem aiSet;
private JMenu help;
private JMenuItem rule;
private JMenuItem about;
private JLabel match;
private JTextArea log;
private JLabel player;
private JTextField field;
private JButton submit;
private final static String RUL = "游戏规则:\n 规定或随机取一些火柴,玩家轮流取1~4根火柴,取到最后一根火柴的玩家算输。\n\n操作方法:\nstart:开始游戏\nstop:结束游戏";
private final static String VER = "火柴游戏 \n\n版本号:V2.5\n\n开发者:董悦\n开发时间:2017年10月";
private final static Object[] AI = {"简单","困难"};
Show(){
config = new Config();
frame = new JFrame("火柴游戏");
bar = new JMenuBar();
mode = new JMenu("模式(M)");
mode.setMnemonic(KeyEvent.VK_M);
pC = new JMenuItem("人机对战(当前)");
pC.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_DOWN_MASK));
pP = new JMenuItem("多人对战");
pP.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,InputEvent.CTRL_DOWN_MASK));
isRandom = new JMenuItem("随机(当前)");
isRandom.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,InputEvent.CTRL_DOWN_MASK));
setting = new JMenu("设置(S)");
setting.setMnemonic(KeyEvent.VK_S);
sysSet = new JMenuItem("系统设置");
sysSet.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_DOWN_MASK));
aiSet = new JMenuItem("AI 设置");
aiSet.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,InputEvent.CTRL_DOWN_MASK));
help = new JMenu("帮助(H)");
help.setMnemonic(KeyEvent.VK_H);
rule = new JMenuItem("游戏帮助");
rule.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H,InputEvent.CTRL_DOWN_MASK));
about = new JMenuItem("关于");
about.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_DOWN_MASK));
match = new JLabel("————输入start开始游戏————");
log = new JTextArea(5,20);
log.setEditable(false);
log.setLineWrap(true);
player = new JLabel("");
field = new JTextField(12);
submit = new JButton("确认");
}
private void init(){
mode.add(pC);
mode.add(pP);
mode.add(isRandom);
setting.add(sysSet);
setting.add(aiSet);
help.add(rule);
help.add(about);
bar.add(mode);
bar.add(setting);
bar.add(help);
frame.setJMenuBar(bar);
JPanel north = new JPanel();
north.add(match);
frame.add(north,BorderLayout.NORTH);
JPanel center = new JPanel();
JScrollPane jsp = new JScrollPane(log);
center.add(jsp);
frame.add(center, BorderLayout.CENTER);
JPanel south = new JPanel();
GridLayout grid = new GridLayout(2,1,3,3);
south.setLayout(grid);
south.add(player);
JPanel input = new JPanel();
input.add(field);
input.add(submit);
south.add(input);
frame.add(south,BorderLayout.SOUTH);
frame.pack();
frame.setResizable(false);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
field.requestFocus();
frame.setLocationRelativeTo(null);
}
private void reg(){ //整理事件注册
submit.addActionListener(new Submit());
pC.addActionListener(e1 -> {
pC.setText("人机对战(当前)");
pP.setText("多人对战");
config.setMode(1);
System.out.println(df.format(new Date()) + "设置模式为人机对战");
});
pP.addActionListener(e2 -> {
String tmp = JOptionPane.showInputDialog(frame,"请输入游戏人数:\n","提示",JOptionPane.PLAIN_MESSAGE);
int mode;
if(tmp == null){
mode = -2;
}
else {
mode = config.toInt(tmp);
}
if((mode <= 1 && mode != -2) || mode > 30){
JOptionPane.showMessageDialog(frame,"您输入的人数不正确,已经帮您恢复默认设置。","提示",JOptionPane.INFORMATION_MESSAGE);
pC.setText("人机对战(当前)");
pP.setText("多人对战");
config.setMode(1);
System.out.println(df.format(new Date()) + "设置错误模式为人机对战");
}
else if(mode != -2){
pC.setText("人机对战");
pP.setText(mode + "人对战(当前)");
config.setMode(mode);
System.out.println(df.format(new Date()) + "设置模式为" + config.getMode() + "人对战");
}
});
isRandom.addActionListener(e3 -> {
if(isRandom.getText().equals("随机(当前)")){
String tmp =JOptionPane.showInputDialog(frame,"请输入火柴数:","提示",JOptionPane.PLAIN_MESSAGE);
int matchNum;
if(tmp == null)
matchNum = -2;
else
matchNum = config.toInt(tmp);
if(matchNum == -1){
JOptionPane.showMessageDialog(frame,"您输入的火柴数不正确,已帮您恢复随机模式。","提示",JOptionPane.INFORMATION_MESSAGE);
}
else if((matchNum < 10 || matchNum > 250) && matchNum != -2){
if(JOptionPane.showConfirmDialog(frame,"您选择的火柴数不是很适合,您确定吗?","提示",JOptionPane.YES_NO_OPTION) == 0){
config.setRandom(false);
config.setMatchNum(matchNum);
isRandom.setText("选择(当前)");
System.out.println(df.format(new Date()) + "设置模式随机,火柴数" + matchNum);
}
}
else if(matchNum != -2){
config.setRandom(false);
config.setMatchNum(matchNum);
isRandom.setText("选择(当前)");
System.out.println(df.format(new Date()) + "设置模式为选择,火柴数" + matchNum);
}
}
else{
config.setRandom(true);
isRandom.setText("随机(当前)");
System.out.println(df.format(new Date()) + "设置模式为随机");
}
});
sysSet.addActionListener(new SystemSet());
aiSet.addActionListener(e4 -> {
String aiLv = (String)JOptionPane.showInputDialog(frame,"请选择 AI 难度\n","AI 设置",JOptionPane.QUESTION_MESSAGE,null,AI,config.getAiLv());
if(aiLv != null) {
config.setAiLv(aiLv);
System.out.println(df.format(new Date()) + "设置AI难度为" + aiLv);
}
});
rule.addActionListener(e5 -> JOptionPane.showMessageDialog(frame,RUL,"游戏帮助",JOptionPane.PLAIN_MESSAGE));
about.addActionListener(e6 -> JOptionPane.showMessageDialog(frame,VER,"关于",JOptionPane.PLAIN_MESSAGE));
}
void showMe(){
init();
reg();
frame.setVisible(true);
}
private class SystemSet implements ActionListener{ //系统设置界面
private JDialog dialog;
private JLabel min;
private JTextField minField;
private JLabel max;
private JTextField maxField;
private JCheckBox pre;
private JButton yes;
private JButton no;
SystemSet(){
dialog = new JDialog(frame,"系统设置",true);
min = new JLabel("随机最小值:");
minField = new JTextField(3);
max = new JLabel("随机最大值:");
maxField = new JTextField(3);
pre = new JCheckBox("人机对战先手");
yes = new JButton("确认");
no = new JButton("取消");
JPanel north = new JPanel();
GridLayout grid = new GridLayout(1,2);
north.setLayout(grid);
JPanel minInput = new JPanel();
minInput.add(min);
minInput.add(minField);
JPanel maxInput = new JPanel();
maxInput.add(max);
maxInput.add(maxField);
north.add(minInput);
north.add(maxInput);
JPanel center = new JPanel();
center.add(pre);
JPanel south = new JPanel();
south.add(yes);
south.add(no);
dialog.add(north,BorderLayout.NORTH);
dialog.add(center,BorderLayout.CENTER);
dialog.add(south,BorderLayout.SOUTH);
dialog.pack();
dialog.setResizable(false);
dialog.setDefaultCloseOperation(dialog.DISPOSE_ON_CLOSE);
dialog.setLocationRelativeTo(null);
yes.addActionListener(e1 ->{
int r1 = config.toInt(minField.getText());
int r2 = config.toInt(maxField.getText());
boolean isPre;
if(r1 == -1 || r2 == -1 || r1 >= r2){
JOptionPane.showMessageDialog(dialog,"数值不正确哦!","提示",JOptionPane.INFORMATION_MESSAGE);
}
else {
if (r1 < 10 || r1 > 250 || r2 < 10 || r2 > 250)
if(JOptionPane.showConfirmDialog(dialog,"数值不是很合适,你确定吗?","提示",JOptionPane.YES_NO_OPTION) == 1)
return;
isPre = pre.isSelected();
config.set(r1,r2,isPre);
System.out.println(df.format(new Date()) + "设置" + config.dataOut());
dialog.dispose();
}
});
no.addActionListener(e2 -> dialog.dispose());
}
@Override
public void actionPerformed(ActionEvent e) {
pre.setSelected(config.getPre());
minField.setText("" + config.getMinRandom());
maxField.setText("" + config.getMaxRandom());
dialog.setVisible(true);
}
}
private class Submit implements ActionListener{ //提交按钮事件
@Override
public void actionPerformed(ActionEvent e) {
String txt = field.getText();
int num;
if(txt.equals("start")){
if(!config.start())
JOptionPane.showMessageDialog(frame,"游戏已经开始喽!\n如果想重新开始输入“stop”结束哦!","提示",JOptionPane.INFORMATION_MESSAGE);
else {
match.setText("————剩余" + config.getMatchNum() + "根火柴————");
if(config.getMode() == 1) {
if(config.getPre())
player.setText("轮到玩家抽取");
else {
log.append("电脑取走" + config.ai() + "根火柴\n");
if(config.getMatchNum() == 0){
JOptionPane.showMessageDialog(frame,"恭喜!玩家赢了","提示",JOptionPane.PLAIN_MESSAGE);
config.stop();
match.setText("————输入start开始游戏————");
field.setText("");
player.setText("");
}
else {
match.setText("————剩余" + config.getMatchNum() + "根火柴————");
player.setText("轮到玩家抽取");
}
}
}
else
player.setText("轮到玩家" + config.getTurn() + "抽取");
}
}
else if(txt.equals("stop")){
if(!config.stop())
JOptionPane.showMessageDialog(frame,"游戏已经停止楼!\n如果想开始游戏输入“start”开始哦!","提示",JOptionPane.INFORMATION_MESSAGE);
else {
log.setText("");
match.setText("————输入start开始游戏————");
player.setText("");
}
}
else if(!txt.equals("")){
num = config.toInt(txt);
if(num == -1 || num < 1 || num > 4 || num > config.getMatchNum())
JOptionPane.showMessageDialog(frame,"您的输入不正确哦!","提示",JOptionPane.INFORMATION_MESSAGE);
else{
if(config.getMode() == 1){
config.remove(num);
log.append("玩家取走" + num + "根火柴\n");
if(config.getMatchNum() == 0){
JOptionPane.showMessageDialog(frame,"很遗憾,电脑赢了","提示",JOptionPane.PLAIN_MESSAGE);
config.stop();
match.setText("————输入start开始游戏————");
log.setText("");
player.setText("");
}
else {
log.append("电脑取走" + config.ai() + "根火柴\n");
if(config.getMatchNum() == 0){
JOptionPane.showMessageDialog(frame,"恭喜!玩家赢了","提示",JOptionPane.PLAIN_MESSAGE);
config.stop();
match.setText("————输入start开始游戏————");
log.setText("");
player.setText("");
}
else {
match.setText("————剩余" + config.getMatchNum() + "根火柴————");
player.setText("轮到玩家抽取");
}
}
}
else{
config.remove(num);
log.append("玩家" + config.getTurn() + "取走" + num + "根火柴\n");
if(config.getMatchNum() == 0){
JOptionPane.showMessageDialog(frame,"很遗憾,玩家" + config.getTurn() + "输了","提示",JOptionPane.PLAIN_MESSAGE);
config.stop();
match.setText("————输入start开始游戏————");
log.setText("");
player.setText("");
}
else {
config.next();
match.setText("————剩余" + config.getMatchNum() + "根火柴————");
player.setText("轮到玩家" + config.getTurn() + "抽取");
}
}
}
}
field.setText("");
}
}
}
package aMatchGame;
//数据存储和游戏处理(类名取得不太好)
class Config {
private boolean isStart;
private String aiLv;
private int matchNum;
private boolean isRandom;
private int minRandom;
private int maxRandom;
private int mode;
private int turn;
private boolean pre;
private AI ai;
Config(){
isStart = false;
aiLv = "简单";
matchNum = 21;
isRandom = true;
minRandom = 15;
maxRandom = 35;
mode = 1;
pre = false;
turn = 0;
}
int getMatchNum() {
return matchNum;
}
void setMatchNum(int matchNum) {
this.matchNum = matchNum;
}
int getMode() {
return mode;
}
void setMode(int mode) {
this.mode = mode;
}
int getMinRandom() {
return minRandom;
}
int getMaxRandom() {
return maxRandom;
}
boolean getPre(){
return pre;
}
String getAiLv(){
return aiLv;
}
void setAiLv(String lv){
aiLv = lv;
}
void setRandom(boolean isRandom){
this.isRandom = isRandom;
}
int toInt(String str){
int sum = 0;
for(int i = 0;i < str.length();i++){
if(str.charAt(i) < '0' || str.charAt(i) > '9')
return -1;
else {
sum *= 10;
sum += str.charAt(i) - '0';
}
}
return sum;
}
void set(int min,int max,boolean pre){
minRandom = min;
maxRandom = max;
this.pre = pre;
}
String dataOut(){
return "最小值" + minRandom + ",最大值" + maxRandom + ",玩家先手" + pre;
}
int getTurn(){
return turn;
}
void next(){
if(turn == mode)
turn = 1;
else
turn ++;
}
boolean start(){
if(isStart)
return false;
else {
isStart = true;
turn = 1;
if(isRandom){
matchNum = (int)(Math.random() * (maxRandom - minRandom + 1) + minRandom);
}
if(mode == 1){
if(aiLv.equals("简单"))
ai = new EasyAi();
else
ai = new DifficultAi();
}
return true;
}
}
boolean stop(){
if(!isStart)
return false;
else {
isStart = false;
return true;
}
}
void remove(int num){
matchNum -= num;
}
int ai(){
int drop = ai.index(matchNum);
matchNum -= drop;
return drop;
}
}
package aMatchGame;
//AI接口(虽然没有必要,但我初学练手)
public interface AI {
int index(int match);
}
package aMatchGame;
//简单级别AI
public class EasyAi implements AI {
@Override
public int index(int match) {
if(match == 1)
return 1;
else if(match <= 5){
return match - 1;
}
else {
return (int)(Math.random() * 4 +1); //随机取火柴直到火柴小于6根
}
}
}
package aMatchGame;
//困难模式AI
public class DifficultAi implements AI {
@Override
public int index(int match) {
if(match == 1)
return 1;
else if(match <= 5)
return match - 1;
else {
if((match - 5) % 4 == 0)
return 4; //将局面扳向玩家取走倒数第6根,这样剩下2-5根电脑取走火柴数-1根玩家必输
else
return (match - 5) % 4;
}
}
}