所以我的任务是在Java中使用gui创建游戏。游戏描述如下:
游戏在大小为n×m的区域中进行,其中m和n小于50。每个单元格从一组中包含单个颜色或字符或数字(您的选择)可能的值。该程序由三个参数n,m,k定义。该程序在二维字段上随机放置字符/颜色/数字。首先颜色/字符/数字属于玩家。游戏的目的是玩家用自己的颜色绘制整个比赛场地。着色通过选择源字段和目标字段。如果它们是相同的颜色,则游戏将所有相邻字段替换为目标颜色作为源字段颜色中的目标字段。游戏向用户显示颜色/字符/数字的列表。当用户绘制整个字段时,游戏结束,移动次数为所选字段的数量。
我创建了gui:
公开GGGame {
Butt0nz();
theFrame();
}
public void Butt0nz() {
colors.add(Color.RED);
colors.add(Color.GREEN);
colors.add(Color.BLUE);
colors.add(Color.YELLOW);
colors.add(Color.ORANGE);
b1 = new JButton("Restart");
b1.addActionListener(this);
b2 = new JButton("Moves: "+ "0");
b3 = new JButton("Is continuation possible: ");
menubar = new JMenuBar();
file = new JMenu("File");
open = new JMenuItem("Open");
save = new JMenuItem("Save");
close = new JMenuItem("Exit");
save.addActionListener(this);
open.addActionListener(this);
close.addActionListener(this);
menubar.add(file);
file.add(open);
file.add(save);
file.add(close);
}
public Color randomColor() {
return colors.get(new Random().nextInt(colors.size()));
}
public void theFrame() {
JPanel panel = new JPanel();
setLayout(new BorderLayout());
panel.setLayout(new GridLayout(n, m));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
button[i][j] = new JButton();
button[i][j].setOpaque(true);
button[i][j].setBackground(randomColor());
panel.add(button[i][j]);
}
}
JPanel butt0n = new JPanel();
butt0n.add(b1);
butt0n.add(b2);
butt0n.add(b3);
setJMenuBar(menubar);
setTitle("Color Game");
add(butt0n, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
setSize(1000, 1000);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
'''
我只想就如何开始游戏的逻辑提出一些建议。我读了一些东西,我知道游戏的逻辑就像是扫雷的,并且我知道应该执行FloodFill算法以使其起作用,但是我只想更清楚地了解如何开始。
我认为您从JButton
中的GridLayout(n, m)
开始很好,因为与在自定义绘画的大面板上添加鼠标侦听器相比,它使您可以更干净地处理事件。
我建议将网格(即JPanel
和GridLayout
的JButton
放在一起)放入JScrollPane
,以便具有更大的按钮。例如,如果不使用JScrollPane
,并且该程序打算在分辨率为1366x768的屏幕上运行,并且在50x50的游戏中,您最多使用1200x700像素(以便为窗口边框留一些余量),表示每个按钮24x14(宽度乘以高度)像素。如果您认为可以,那么依靠屏幕的分辨率可能不好。而是将网格放在JScrollPane
中。我并不是在建议不要使用类似300x300的按钮(因为这可能不必要的大),但是例如30x30甚至更大的按钮,并不是很难点击。
另一个想法是让用户即时设置每个按钮的大小,即通过程序中的设置,例如,它可以是两个滑块(一个用于宽度,一个用于高度)。
我建议不要使用numbers或characters选项,因为与设置背景颜色相比,这很难注意到。
出于明显的原因,我会为每个按钮的背景建议一个not强烈的颜色。例如,考虑使用您指定的颜色填充整个区域...这可能使某人(至少我自己哈哈)失明。例如,您可以使用这些颜色的darker()
版本。如果那行不通,我测试了另一个选择:添加一些透明度(即alpha颜色分量),以使按钮的原始颜色显示出来,据我所知,该颜色不会使盲人看到。] >
这是用透明的红色绘制一些按钮的示例代码:
darker()
而且我认为结果不会使任何人致盲(尽管它几乎是明显的红色):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(final String[] args) {
final int rows = 10, cols = 10;
final JPanel panel = new JPanel(new GridLayout(0, cols));
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j) {
final JButton button = new JButton() {
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(new Color(255, 0, 0, 50));
g.fillRect(0, 0, getWidth(), getHeight());
}
};
button.setPreferredSize(new Dimension(30, 30));
panel.add(button);
}
final JFrame frame = new JFrame("ColorGame.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
我认为解释得很好。因此,除了那里的材料之外,您不需要其他东西来实现它。它还提供了一些递归伪代码来解决该问题。
为了轻松检查结束条件,您可以使用背景数量等于播放器所选择颜色的按钮数量的Flood Fill algorithm in Wikipedia计数器/ int
。当该数字等于N乘以M时,则结束游戏。但是不要忘了每次更新按钮背景都会更新您的计数器。如果您不想使用此计数器,例如,因为它可能使代码不那么干净且更容易出错,那么您最简单的操作可能是在每次移动后遍历每个按钮,并计算哪些按钮具有用户的颜色作为背景,但这将是无效的,尽管在我看来,对于这种特定情况,解决尺寸最大为50x50(即2500个颜色相等性检查)的效率并不是很大。
[为了方便调整,我建议使用子类,例如JButton
类,并重写getPreferredSize()
方法以返回类型为Dimension
的共享库,该共享库将包含由用户的设置滑块选择的值。然后,每次更新此共享的可变对象时,只需在revalidate()
的JScrollPane
视图(即包含按钮的面板)上调用Viewport
,它将更新JScrollPane
。
由于您将JButton
子类化,您可能希望添加按钮在网格中所对应的行数和列数,因此,当调用ActionListener
时,您将知道用户单击的位置(只需使用相同的[ C0]对象用于所有来源/按钮)。在这种情况下,您可能不必忘记检查ActionListener
的source
[比ActionEvent
更合适,我认为可以使用JButton
。因此,以这种方式,您可以让用户知道哪个是源目标按钮对中他们选择的第一个按钮,如果再次单击同一按钮,则撤消其初始选择。当然,当选择一个切换按钮时,您将需要维护对第一个切换按钮的引用,以使其与第二个切换按钮匹配并知道从何处开始。
这是我到目前为止所拥有的,只是让您入门。如果您需要更多信息或说明,请在评论中告诉我。