一、石头剪刀布游戏
1.1【问题描述】
用 JAVA 语言设计如下界面的石头剪刀布游戏。 游戏的一方点击界面上石头、剪刀、布按钮,游戏的另一方计算机随机选择, 然后给出游戏结果。
1.2【基本要求】
按照下面给出的步骤设计石头剪刀布游戏, 并完成以下工作:
- 在“//” 后给出必要的注释;
- 为程序添加菜单; 至少 2 个菜单: 结果显示方式和关于游戏; 结果显示方式菜单有 3 个菜单项: 文本显示、 图形显示、 结束游戏; 实现菜单中的功能, 自行搜索能体现石头、剪刀、布的图形或图片, 用这些图形或图片显示游戏结果。
1.3【模块划分】
public class Two{
public static void main(String[] args) {
// 启动游戏
new Work();
}
//功能
static class Work extends JFrame implements ActionListener{}
}
// 功能详解
static class Work extends JFrame implements ActionListener{
// 按钮
JButton
// 面板
JPanel
// 组件
JLabel
// 菜单
JMenuItem
// 图片路径
private static final String BASE_PATH
// 默认游戏主题
int theme
// 得分情况
int score
// 初始化菜单
public void initMenu(){}
// 初始化窗体
public void initFrame(){
// 设置标题
setTitle("石头剪刀布游戏");
// 设置窗体左上顶点坐标
setLocation(250,250);
// 设置窗体大小
setSize(350,350);
// 设置关闭模式
setDefaultCloseOperation(EXIT_ON_CLOSE);
// 设置窗体置顶
setAlwaysOnTop(true);
}
// 初始化窗口
public Work() {
// 初始化窗体
initFrame();
// 初始化菜单
initMenu();
// 绘制游戏界面顶部
paintViewTop();
// 绘制游戏界面中间
paintViewBot();
//使窗体可见
setVisible(true);
}
// 鼠标点击事件
@Override
public void actionPerformed(ActionEvent e){}
}
// 初始化菜单
public void initMenu(){
// 创建菜单栏
JMenuBar jMenuBar = new JMenuBar();
// 创建菜单
JMenu jMenu1 = new JMenu("显示方式");
JMenu jMenu2 = new JMenu("关于我们");
// 增加菜单选项
jMenuBar.add(jMenu1);
jMenuBar.add(jMenu2);
// 增加菜单项
jMenu1.add(item1);
jMenu1.add(item2);
jMenu1.add(item3);
// 给选项添加点击事件
item1.addActionListener(this);
item2.addActionListener(this);
item3.addActionListener(this);
// 4. 给窗体对象设置菜单.
setJMenuBar(jMenuBar);
}
// 绘制游戏界面顶部
public void paintViewTop(){
// 设置面板1背景
panel1.setBackground(Color.yellow);
//把组件放进窗体中
panel1.add(jiandao);
panel1.add(shitou);
panel1.add(bu);
panel1.add(clear);
//下面的四行是事件监听器,监听用户的输入
shitou.addActionListener(this);
bu.addActionListener(this);
jiandao.addActionListener(this);
clear.addActionListener(this);
add(panel1,BorderLayout.NORTH);
}
// 绘制游戏界面中间
public void paintViewBot(){
// 取消默认布局
pane12.setLayout(null);
// 设置面板2背景
pane12.setBackground(Color.green);
// 分数界面
scoreLabel = new JLabel("得分: " + score);
scoreLabel.setBounds(120, 20, 100, 20);
pane12.add(scoreLabel);
// 放置组件
pane12.add(user);
user.setBounds(10,50,100,100);
pane12.add(com);
com.setBounds(230,50,100,100);
pane12.add(label);
label.setBounds(120,50,100,100);
pane12.add(userLabel);
userLabel.setBounds(10, 20, 100, 20);
pane12.add(comLabel);
comLabel.setBounds(230, 20, 100, 20);
add(pane12,BorderLayout.CENTER);
}
1.4【算法思想】
巧用加法实现判断猜拳结果
// 结果判定
public void judgeGame(int user){
// 防止同一个编译器产生相同的数字
Random num = new Random();
// 随机生成 4,7,10 中的一个数字
int i = 4 + (3 *((int)(num.nextInt() * 10)) % 3);
int res = i + user;
if(res == 6|| res == 7 || res == 11){
showView(theme,2,user,(user + 2)%3);
}else if(res == 5 || res == 9 || res == 10){
showView(theme,0,user,(user + 1)%3);
}else if(res == 4 || res == 8 || res == 12){
showView(theme,1,user,user);
}
}
// 鼠标点击事件
@Override
public void actionPerformed(ActionEvent e){
// 监听按下的键,执行对应的操作
if(e.getSource()== jiandao){
userOpt = 0;
}
else if(e.getSource()== shitou){
userOpt = 1;
}
else if(e.getSource()== bu){
userOpt = 2;
}
else if(e.getSource()==clear){
// 清除界面
clearAll();
// 重置用户操作
userOpt = -1;
}
// 用户已进行操作
if(userOpt != -1){
// 开始绘制界面
judgeGame(userOpt);
}
}
1.5【题解】
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
/**
* @author xh
*/
public class Two{
public static void main(String[] args) {
// 启动游戏
new Work();
}
static class Work extends JFrame implements ActionListener{
// 按钮
JButton jiandao = new JButton("剪刀"),
shitou = new JButton("石头"),
bu = new JButton("布"),
clear = new JButton("清除");
// 面板
JPanel pane12 = new JPanel(), panel1 = new JPanel();
// 组件
JLabel label = new JLabel("选择剪刀、石头、布开始游戏"), scoreLabel,
userLabel = new JLabel("用户"),comLabel = new JLabel("电脑"),
user = new JLabel(),com = new JLabel();
// 菜单
JMenuItem item1 = new JMenuItem("文本显示"),
item2 = new JMenuItem("图形显示"),
item3 = new JMenuItem("结束游戏");
// 图片路径
private static final String BASE_PATH = "C:\\Users\\Administrator\\Desktop\\homework\\Two\\新建文件夹\\";
String[] transOne = {"剪刀","石头","布"};
String[] transTwo = {"失败","平手","胜利"};
// 默认游戏主题
int theme = 0;
// 得分情况
int score = 0;
// 用户的选择
int userOpt = -1;
// 初始化菜单
public void initMenu(){
// 创建菜单栏
JMenuBar jMenuBar = new JMenuBar();
// 创建菜单
JMenu jMenu1 = new JMenu("显示方式");
JMenu jMenu2 = new JMenu("关于我们");
// 增加菜单选项
jMenuBar.add(jMenu1);
jMenuBar.add(jMenu2);
// 增加菜单项
jMenu1.add(item1);
jMenu1.add(item2);
jMenu1.add(item3);
// 给选项添加点击事件
item1.addActionListener(this);
item2.addActionListener(this);
item3.addActionListener(this);
// 4. 给窗体对象设置菜单.
setJMenuBar(jMenuBar);
}
// 初始化窗体
public void initFrame(){
// 设置标题
setTitle("石头剪刀布游戏");
// 设置窗体左上顶点坐标
setLocation(250,250);
// 设置窗体大小
setSize(350,350);
// 设置关闭模式
setDefaultCloseOperation(EXIT_ON_CLOSE);
// 设置窗体置顶
setAlwaysOnTop(true);
}
// 绘制游戏界面顶部
public void paintViewTop(){
// 设置面板1背景
panel1.setBackground(Color.yellow);
//把组件放进窗体中
panel1.add(jiandao);
panel1.add(shitou);
panel1.add(bu);
panel1.add(clear);
//下面的四行是事件监听器,监听用户的输入
shitou.addActionListener(this);
bu.addActionListener(this);
jiandao.addActionListener(this);
clear.addActionListener(this);
add(panel1,BorderLayout.NORTH);
}
// 绘制游戏界面中间
public void paintViewBot(){
// 取消默认布局
pane12.setLayout(null);
// 设置面板2背景
pane12.setBackground(Color.green);
// 分数界面
scoreLabel = new JLabel("得分: " + score);
scoreLabel.setBounds(120, 20, 100, 20);
pane12.add(scoreLabel);
// 放置组件
pane12.add(user);
user.setBounds(10,50,100,100);
pane12.add(com);
com.setBounds(230,50,100,100);
pane12.add(label);
label.setBounds(120,50,100,100);
pane12.add(userLabel);
userLabel.setBounds(10, 20, 100, 20);
pane12.add(comLabel);
comLabel.setBounds(230, 20, 100, 20);
add(pane12,BorderLayout.CENTER);
}
// 结果判定
public void judgeGame(int user){
// 防止同一个编译器产生相同的数字
Random num = new Random();
// 随机生成 4,7,10 中的一个数字
int i = 4 + (3 *((int)(num.nextInt() * 10)) % 3);
int res = i + user;
if(res == 6|| res == 7 || res == 11){
showView(theme,2,user,(user + 2)%3);
}else if(res == 5 || res == 9 || res == 10){
showView(theme,0,user,(user + 1)%3);
}else if(res == 4 || res == 8 || res == 12){
showView(theme,1,user,user);
}
}
// 显示方式
public void showView(int theme, int res, int i, int j){
if(theme == 0){
// 清除图片
clearIcon();
user.setText("用户: " + transOne[i]);
com.setText("电脑:" + transOne[j]);
label.setText("本局结果: " + transTwo[res] + "!");
}else if(theme == 1){
// 清除文本
clearText();
user.setIcon(new ImageIcon(BASE_PATH + theme + i + ".png"));
com.setIcon(new ImageIcon(BASE_PATH + theme + j + ".png"));
label.setIcon(new ImageIcon(BASE_PATH + theme + "_" + res + ".png"));
}
if(res == 2){
score += 10;
}
scoreLabel.setText("得分: " + score);
}
// 初始化窗口
public Work() {
// 初始化窗体
initFrame();
// 初始化菜单
initMenu();
// 绘制游戏界面顶部
paintViewTop();
// 绘制游戏界面中间
paintViewBot();
//使窗体可见
setVisible(true);
}
// 清除界面
public void clearAll(){
clearText();
clearIcon();
label.setText("选择剪刀、石头、布开始游戏");
score = 0;
scoreLabel.setText("得分: " + score);
}
// 清除图片
public void clearIcon(){
user.setIcon(null);
com.setIcon(null);
label.setIcon(null);
}
// 清除文本
public void clearText(){
user.setText(null);
com.setText(null);
}
// 鼠标点击事件
@Override
public void actionPerformed(ActionEvent e){
// 监听按下的键,执行对应的操作
if(e.getSource()== jiandao){
userOpt = 0;
}
else if(e.getSource()== shitou){
userOpt = 1;
}
else if(e.getSource()== bu){
userOpt = 2;
}
else if(e.getSource()==clear){
// 清除界面
clearAll();
// 重置用户操作
userOpt = -1;
}
// 切换显示方式
if (e.getSource() == item1) {
theme = 0;
} else if (e.getSource() == item2) {
theme = 1;
} else if (e.getSource() == item3) {
theme = 2;
// 退出窗口,清除内存
dispose();
}
// 用户已进行操作
if(userOpt != -1){
// 开始绘制界面
judgeGame(userOpt);
}
}
}
}
用到的图片素材:
文件命名格式
运行界面:
关于中文乱码、界面白屏,请打开IDAE设置
输入-Dfile.encoding=gbk
拓展:制作网页版
代码:
HTML:
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>石头剪子布游戏</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<form>
<!-- 定义表单单选框选项 -->
<input type="radio" id="rock-rock" name="rock-paper-scissors">
<input type="radio" id="rock-paper" name="rock-paper-scissors">
<input type="radio" id="rock-scissors" name="rock-paper-scissors">
<input type="radio" id="paper-rock" name="rock-paper-scissors">
<input type="radio" id="paper-paper" name="rock-paper-scissors">
<input type="radio" id="paper-scissors" name="rock-paper-scissors">
<input type="radio" id="scissors-rock" name="rock-paper-scissors">
<input type="radio" id="scissors-paper" name="rock-paper-scissors">
<input type="radio" id="scissors-scissors" name="rock-paper-scissors">
<div>
<h1>石头剪子布</h1>
<!-- 构造手的指头 -->
<div id="hands">
<!-- 电脑 -->
<div class="hand" id="computer-hand">
<div class="fist"></div>
<div class="finger finger-1"></div>
<div class="finger finger-2"></div>
<div class="finger finger-3"></div>
<div class="finger finger-4"></div>
<div class="thumb"></div>
<div class="arm"></div>
</div>
<!-- 用户 -->
<div class="hand" id="user-hand">
<div class="fist"></div>
<div class="finger finger-1"></div>
<div class="finger finger-2"></div>
<div class="finger finger-3"></div>
<div class="finger finger-4"></div>
<div class="thumb"></div>
<div class="arm"></div>
</div>
<div id="icons">
<div>
<label for="rock-rock">✊</label>
<label for="paper-rock">✊</label>
<label for="scissors-rock">✊</label>
</div>
<div>
<label for="rock-paper">👋</label>
<label for="paper-paper">👋</label>
<label for="scissors-paper">👋</label>
</div>
<div>
<label for="rock-scissors">✌</label>
<label for="paper-scissors">✌</label>
<label for="scissors-scissors">✌</label>
</div>
</div>
</div>
</div>
<div id="message">
<h2></h2>
<input type="reset" value="重新开始" />
</div>
</form>
</body>
</html>
CSS:
@charset "utf-8";
// 摇动手
@keyframes changeOrder {
from { z-index: 9;}
to { z-index: 1; }
}
@keyframes handShake {
0%,100% { transform: rotate(10deg); }
50% { transform: rotate(-10deg); }
}
@keyframes handShake2 {
0%,100% { transform: rotateY(180deg) rotate(10deg); }
50% { transform: rotateY(180deg) rotate(-10deg); }
}
// 页面基本设置
html, body {
margin: 0;
padding: 0;
border: 0;
line-height: 1;
font-family: Acme, Arial, sans-serif;
}
form {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
h1 {
text-align: center;
}
// 手的属性
#hands {
text-align: center;
}
input:checked ~ div .hand {
animation: none !important;
}
.hand {
margin: 20px;
width: 200px;
height: 200px;
position: relative;
transform: rotate(10deg);
display: inline-block;
animation: handShake 2s infinite;
}
.hand > div {
position: absolute;
box-sizing: border-box;
border: 2px solid black;
background: gold;
transition: all 0.1s;
}
.fist {
height: 110px;
left: 40px;
top: 50px;
width: 90px;
border-radius: 20px 0 0 20px;
}
.finger {
width: 70px;
height: 30px;
border-radius: 20px;
left: 80px;
transform-origin: 0 50%;
}
.finger-1 { top: 50px; --dif: 0px; }
.finger-2 { top: 78px; left: 84px; --dif: 4px; }
.finger-3 { top: 106px; --dif: 0px; }
.finger-4 { top: 134px; height: 26px; left: 76px; --dif: -8px; }
div.thumb {
width: 35px;
height: 70px;
border-radius: 0 20px 20px 20px;
top: 50px;
left: 80px;
border-left: 0 solid;
box-shadow: -17px 6px 0 -15px black;
}
div.arm {
width: 22px;
height: 70px;
left: 20px;
top: 70px;
border: 0;
border-top: 2px solid black;
border-bottom: 2px solid black;
}
#user-hand {
transform: rotateY(180deg);
animation: handShake2 2s infinite;
position: relative;
}
input[type="radio"] {
position: absolute;
top: -1000in;
left: -1000in;
}
input[id$="scissors"]:checked ~ div #user-hand .finger-1,
input[id^="scissors"]:checked ~ div #computer-hand .finger-1 {
width: 130px;
transform:rotate(-5deg);
}
input[id$="scissors"]:checked ~ div #user-hand .finger-2,
input[id^="scissors"]:checked ~ div #computer-hand .finger-2 {
width: 130px;
transform:rotate(5deg);
}
input[id$="paper"]:checked ~ div #user-hand .finger-1,
input[id$="paper"]:checked ~ div #user-hand .finger-2,
input[id$="paper"]:checked ~ div #user-hand .finger-3,
input[id$="paper"]:checked ~ div #user-hand .finger-4,
input[id^="paper"]:checked ~ div #computer-hand .finger-1,
input[id^="paper"]:checked ~ div #computer-hand .finger-2,
input[id^="paper"]:checked ~ div #computer-hand .finger-3,
input[id^="paper"]:checked ~ div #computer-hand .finger-4 {
left: 124px;
left: calc(124px + var(--dif));
width: 80px;
border-left: 0;
border-radius: 0 20px 20px 0;
}
// 游戏结果
#rock-rock:checked ~ div h2::before,
#paper-paper:checked ~ div h2::before,
#scissors-scissors:checked ~ div h2::before {
content: "平局!"
}
#rock-paper:checked ~ div h2::before,
#paper-scissors:checked ~ div h2::before,
#scissors-rock:checked ~ div h2::before {
content: "你赢了!"
}
#rock-scissors:checked ~ div h2::before,
#paper-rock:checked ~ div h2::before,
#scissors-paper:checked ~ div h2::before {
content: "电脑赢了!"
}
#message {
text-align: center;
display: none;
}
input:checked ~ #message {
display: block;
}
#hands {
display: flex;
align-items: center;
justify-content: center;
}
#icons {
width: 30px;
height: 200px;
display: inline-flex;
flex-direction: column;
}
#icons > div {
flex: 1;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
overflow: hidden;
position: relative;
}
label:active {
position:static;
margin-left: 60px;
}
label:active::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
z-index: 10;
height: 60px;
}
label {
animation: changeOrder 0.45s infinite linear;
background: #f5f5f5;
border: 1px solid #ccc;
box-sizing: border-box;
cursor: pointer;
display: block;
height: 60px;
width: 60px;
line-height: 60px;
font-size: 2rem;
position: absolute;
top: 0;
left: 0;
user-select: none;
}
label:nth-of-type(1) { animation-delay: -0.00s; }
label:nth-of-type(2) { animation-delay: -0.15s; }
label:nth-of-type(3) { animation-delay: -0.30s; }